前端设计模式-策略模式(小球动画)

14,108 阅读1分钟

写在前面:本文所有内容和案例都来自于《Javascript设计模式与开发实践》,本文所记录的内容属于对所学再重新复习一遍,加深印象。欢迎大家一键三连,谢谢大家

实现小球的动画

让小球运动起来通过分析可以得到:

  1. 需要小球的初始位置
  2. 小球运动后的目标位置
  3. 动画开始时间
  4. 动画持续时间

class Animate {
    constructor(dom) { 
        this.dom = dom
        // 开始位置
        this.startPos = 0
        // 结束位置
        this.endPos = 0
        // 动画开始时间
        this.startTime = 0
        // 动画算法
        this.easying = null
        // 动画持续时间
        this.duration = 0
        // 需要改变的属性名
        this.propertyName = null
        // 动画结束时间
        this.endTime = 0
    }
    
    start (propertyName, endPos, duration, easying) {
        this.startPos = this.dom.getBoundingClientRect()[propertyName] 
        this.endPos = endPos
        this.startTime =  +(new Date())
        this.propertyName = propertyName
        this.duration = duration
        this.easying = tween[easying]
        this.endTime = this.duration + this.startTime
        let timeId = setInterval( ()=> {
            // 动画执行结束清除定时器
            if(this.step() === false) {
                clearInterval(timeId)
            }
        }, 16)
    }
    step() {
        let nowDate = +(new Date()) 
        // 动画时间结束时 修正动画位置
        if(nowDate >= this.endTime ) {
            this.update(this.endPos)
            return false
        }
        const pos = this.easying(nowDate - this.startTime, this.startPos,   this.endPos - this.startPos, this.duration)
        this.update(pos)
        return true
    }
    // 更新小球动画位置
    update(pos) {
        this.dom.style[this.propertyName] = pos + 'px'
    }
}


/**
     * 动画算法
     * @param {动画已消耗的时间} t 
     * @param {小球原始位置} b 
     * @param {小球目标位置} c 
     * @param {动画持续的总时间} d 
     * @returns 
     */
const tween = {

    linear: function (t, b, c, d) {
        return c * t / d + b;
    },
    easeIn: function (t, b, c, d) {
        return c * (t /= d) * t + b;
    },
    strongEaseIn: function (t, b, c, d) {
        return c * (t /= d) * t * t * t * t + b;
    },
    strongEaseOut: function (t, b, c, d) {
        return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
    },
    sineaseIn: function (t, b, c, d) {
        return c * (t /= d) * t * t + b;
    },
    sineaseOut: function (t, b, c, d) {
        return c * ((t = t / d - 1) * t * t + 1) + b;
    }
};


// html
<style>
#animate {
        width: 50px;
        height: 50px;
        border-radius: 50%;
        background: #000;
        margin-top: 100px;
        margin-left: 100px;
        position:relative;
        left:  0;
        }
</style>
<body>
    <div id="animate"> </div>
    <button id="animateStartBtn">动画开始</button>

</body>

const animate = new Animate(document.getElementById('animate'))
document.getElementById('animateStartBtn').addEventListener('click', function() {
    animate.start('left', 500, 1000, 'linear')
})

到现在我们就完成了一个控制小球的动画,把动画放到放到tween,方便后期扩展。