document this 插件 mac_基于"发布订阅"的原生 JS 插件封装

大家好,我是神三元。 今天我们来做一个小玩意,用原生 JS 封装一个动画插件。效果如下:

6fea1c102abf2c467ab0a106e8d07e22.gif这个飞驰的小球看起来是不是特有灵性呢?没错,它就是用原生JS实现的。 接下来,就让我们深入细节,体会其中的奥秘。相信这个实现的过程,会比动画本身更加精彩!

一、需求分析

封装一个插件,将小球的 DOM 对象作为参数传入,使得小球在鼠标按下和放开后能够运动,在水平方向做匀减速直线运动,初速度为鼠标移开瞬间的速度,在竖直方向的运动类似于自由落体运动。并且,小球的始终在不离开浏览器的边界运动,碰到边界会有如图的反弹效果。

二、梳理思路

分析这样的一个过程,其中大致会经历一下的关键步骤:

  • 1、鼠标按下时,记录小球的初始位置信息

  • 2、鼠标按下后滑动,记录松开鼠标瞬间的移动速度

  • 3、鼠标松开后,在水平方向上,让小球根据刚刚记录的移动速度进行匀减速运动,竖直方向设定一个竖直向下的加速度,开始运动。

  • 4、水平方向速度减为 0 时,水平方向运动停止;竖直方向速度减为 0 或者足够小时,竖直方向运动停止。

三、难点分析

看到这里,估计你的思路清晰了不少,但可能还是有一些比较难以搞定的问题。

首先,你怎么拿到松开手瞬间的小球移动速度?如何去表达出这个加速度的效果?

在实现方面,这是非常重要的问题。不过,其实非常的简单。

浏览器本身就是存在反应时间的,你可以把它当做一个摄像机,在给 DOM 元素绑定了事件之后,每隔一段时间(一般非常的短,根据不同浏览器厂商和电脑性能而定,这里我用到 chrome,保守估计为 20ms)会给这个元素拍张照,记录它的状态。在按下鼠标之后的拖动过程中,事实上会给元素拍摄无数张照片。如果现在每经过一段时间,我记录当下当前照片与上一段照片的位置差,那么最后一次拍照和倒数第二次拍照的小球位置差距,是不是就可以作为离开的瞬时速度呢?当然可以啦。废话不多说,上图:

f68389e5ab9e6a210865391122ba2e8a.png

同样,对实现加速度的效果,首先弄清一个问题,什么是速度?速度就是单位时间内运动的距离,这里暂且把它当做 20ms 内的距离,那么我每次拍照时,将这个距离增加或减少一个值,这个值就是加速度。

四、初步实现

当大部分问题考虑清楚之后,现在开始实现。 首先是基本的样式,比较简单。

charset="UTF-8">

狂奔的小球

rel="stylesheet" href="css/reset.min.css">

html, body {

height: 100%;

overflow: hidden;

}

#box{

position: absolute;

top: 100px;

left: 100px;

width: 150px;

height: 150px;

border-radius: 50%;

background: lightcoral;

cursor: move;

z-index: 0;

}

id="box">

现在来完成核心的 JS 代码,采用 ES6 语法

//drag.js

class Drag {

//ele为传入的DOM对象

constructor(ele) {

//初始化参数

this.ele = ele;

['strX', 'strY', 'strL', 'strT', 'curL', 'curT'].forEach(item => {

this[item] = null;

});

//为按下鼠标绑定事件,事件函数一定要绑定this,在封装过程中this统一指定为实例对象,下不赘述

this.DOWN = this.down.bind(this);

this.ele.addEventListener('mousedown', this.DOWN);

}

down(ev) {

let ele = this.ele;

this.strX = ev.clientX;//鼠标点击处到浏览器窗口最左边的距离

this.strY = ev.clientY;//鼠标点击处到浏览器窗口最上边的距离

this.strL = ele.offsetLeft;//元素到浏览器窗口最左边的距离

this.strT = ele.offsetTop;//元素到浏览器窗口最上边的距离

this.MOVE = this.move.bind(this);

this.UP = this.up.bind(this);

document.addEventListener('mousemove', this.MOVE);

document.addEventListener('mouseup', this.UP);

//flag

//清理上一次点击形成的一些定时器和变量

clearInterval(this.flyTimer);

this.speedFly = undefined;

clearInterval(this.dropTimer);

}

move(ev) {

let ele = this.ele;

this.curL = ev.clientX - this.strX + this.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值