zoukankan      html  css  js  c++  java
  • 小程序商品飞入购物车组件

    wxml

    <view class="fly-ball"
          hidden="{{ hidden }}"
          animation="{{ animation }}"
          style="top:{{ top }}px;left:{{ left }}px"></view>
    

    wxss

    .fly-ball {
         30rpx;
        height: 30rpx;
        position: fixed;
        border-radius: 100%;
        z-index: 100;
        background: red;
        top: 200px;
        left: 10px;
        display: block;
        box-shadow: 0 1px 1px #000, 0 0 3px #fff inset;
    }
    

    JS

    import { bezier } from "../../utils/util";
    
    const app = getApp()
    
    Component({
        /**
         * 组件的属性列表
         */
        properties: {},
    
        /**
         * 组件的初始数据
         */
        data: {
            loading: false,  // 动画是否进行中
            animation: {},
            hidden: true,
            top: 0,
            left: 0
        },
    
        /**
         * 组件的方法列表
         */
        methods: {
    
            // 动画
            ballAnimation(e) {
    
                // 节流
                if (this.data.loading) {
                    return
                }
    
                let topPoint = {},
                    finger = {},
                    busPos = {
                        x: 250,
                        y: app.globalData.screenHeight
                    }
    
                finger.x = e.touches[0].clientX  // 点击的位置
                finger.y = e.touches[0].clientY
    
                this.setData({
                    top: finger.y,
                    left: finger.x,
                    hidden: false,
                    loading: true
                })
    
                // 控制点y值定在低的点上方250px处
                if (finger.y < busPos.y) {
                    topPoint.y = finger.y - 250
                } else {
                    topPoint.y = busPos.y - 250
                }
    
                // 控制点确保x在点击点和购物车间
                if (finger.x > busPos.x) {
                    topPoint.x = (finger.x - busPos.x) / 2 + busPos.x
                } else {
                    topPoint.x = (busPos.x - finger.x) / 2 + finger.x
                }
    
                let linePos = bezier([busPos, topPoint, finger], 10),
                    startPoint = linePos[linePos.length - 1]
    
                let animation = wx.createAnimation({
                    duration: 40
                })
    
                for (let i = linePos.length - 1; i >= 0; i--) {
    
                    // 根据坐标值逐个计算各点的translate
                    let startPointX = startPoint.x,
                        startPointY = startPoint.y,
                        nextPointX = linePos[i].x,
                        nextPointY = linePos[i].y,
                        x = nextPointX - startPointX,
                        y = nextPointY - startPointY,
                        scale = 1
    
                    if (i < 2) {
                        scale = 0.6
                    }
    
                    animation.translateX(x).translateY(y).scale(scale).step()
                }
    
                this.setData({
                    animation: animation.export()
                })
    
                setTimeout(() => {
    
                    this.setData({
                        loading: false,
                        animation: {
                            actions: [{
                                animates: [{ type: "translateX", args: [0] }, {
                                    type: "translateY",
                                    args: [0]
                                }, { type: "scale", args: [0, 0] }],
                                option: {
                                    transition: { duration: 0 }
                                }
                            }]
                        }
                    })
                }, 800)
            }
        }
    })
    

    二次贝塞尔曲线
    util.js

    function bezier(pots, amount) {
        let pot,
            lines,
            ret = [],
            points
    
        for (let i = 0; i <= amount; i++) {
            points = pots.slice(0)  // 购物车坐标、控制点坐标、点击坐标
            lines = []
    
            while (pot = points.shift()) {
    
                if (points.length) {
                    lines.push(pointLine([pot, points[0]], i / amount))
                } else if (lines.length > 1) {
                    points = lines
                    lines = []
                } else {
                    break
                }
            }
    
            ret.push(lines[0])
        }
    
        function pointLine(points, rate) {
            let pointA, pointB, pointDistance, xDistance, yDistance, tan, radian, tmpPointDistance
            let ret = []
    
            pointA = points[0]
            pointB = points[1]
            xDistance = pointB.x - pointA.x
            yDistance = pointB.y - pointA.y
            pointDistance = Math.pow(Math.pow(xDistance, 2) + Math.pow(yDistance, 2), 1 / 2)  // 斜边长
            tan = yDistance / xDistance
            radian = Math.atan(tan)
            tmpPointDistance = pointDistance * rate
    
            if (pointA.x < pointB.x) {
                ret = {
                    x: pointA.x + tmpPointDistance * Math.cos(radian),
                    y: pointA.y + tmpPointDistance * Math.sin(radian)
                }
            } else {
                ret = {
                    x: pointA.x - tmpPointDistance * Math.cos(radian),
                    y: pointA.y - tmpPointDistance * Math.sin(radian)
                }
            }
    
            return ret
        }
    
        return ret
    }
    

    调用

    this.selectComponent("#flyBall").ballAnimation(e)
    

    代码主要是抄考网上大神的,改动的地方只是把定时器换成了小程序支持的Animation并且可左右飞入
    核心是二次贝塞尔曲线的计算,这个有机会要研究下...

    学习资料

    小程序购物车抛物线动画(通用)
    贝塞尔曲线算法之JS获取点
    贝塞尔曲线原理
    贝塞尔曲线介绍及一阶、二阶推导

  • 相关阅读:
    职业生涯起步不要去顶级公司
    discuz uc密码修改
    习惯决定成功与否
    世上没有理想的工作
    中山市慧海人力资源服务有限公司
    Codeforces Round #365 (Div. 2) B 前缀和
    Codeforces Round #365 (Div. 2) A 水
    tyvj 1067 dp 两次LIS(nlogn)
    Codeforces Round #303 (Div. 2) D 贪心
    Codeforces Round #303 (Div. 2) C dp 贪心
  • 原文地址:https://www.cnblogs.com/Grani/p/14020950.html
Copyright © 2011-2022 走看看