原生JavaScript运动函数篇 (二) (加速度运动、弹性运动、重力场运动(多方向+碰撞检测+重力加速度+能量损失运动)拖拽运动)层层深入

原生JavaScript运动函数篇 (二) (加速度运动、弹性运动、重力场运动(多方向+碰撞检测+重力加速度+能量损失运动)拖拽运动)层层深入

前言:

本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小生感激不尽。

本篇文章为您分析一下原生JS写加速度运动、弹性运动、重力场运动(多方向+碰撞检测+重力加速度+能量损失运动)拖拽运动

层层深入,到封装插件

由于篇幅过大,博主把拖拽运动写到下面这篇博文里面了

- js运动函数篇(三)链接: https://www.cnblogs.com/qq4297751/p/12814248.html

HTML结构【加速度运动】

CSS样式【加速度运动】

#oDiv {

position: absolute;

left: 0px;

top: 0px;

height: 100px;

width: 100px;

background-color: orange;

}

JS行为【加速度运动】

// v = v + at;

var oDiv = document.getElementsByTagName('div')[0];

var timer = null;

oDiv.onclick = function () {

startMove(this);

}

// 加速度不变的加速运动 运动方向是向右

// 加速度不变的减速运动 加速度不变加速运动 运动方向是向左

function startMove(dom) {

clearInterval(timer);

// 定义一个加速度

var a = 2;

// 定义一个初速度

var iSpeed = 20;

timer = setInterval(function () {

// 每次运动时让它的加速度加上当前的速度

iSpeed = iSpeed + a;

oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';

}, 30);

}

页面效果如下:

速度是越来越快了,但是我们要让他到达某个目标点时停下来

HTML结构【弹性运动】

CSS样式【弹性运动】

.flex {

position: absolute;

left: 0px;

top: 0px;

width: 100px;

height: 100px;

background-color: orange;

}

span {

position: absolute;

left: 300px;

top: 0px;

background-color: black;

width: 1px;

height: 100px;

}

页面效果如下:

我们让它到达目标点之后有一个弹性效果

JS行为【弹性运动】

var oDiv = document.querySelector('.flex');

oDiv.onclick = function () {

startMove(this, 300);

}

var timer = null;

function startMove(dom, target) {

clearInterval(timer);

var iSpeed = 0; // 定义一个初速度

var a = 3; // 定义一个加速度

timer = setInterval(function () {

// 判断速度的正负值

if (dom.offsetLeft < target) {

iSpeed += a;

} else {

iSpeed -= a;

}

dom.style.left = dom.offsetLeft + iSpeed + 'px';

}, 30);

}

上面的运动效果有些软弱无力

跟我们现实生活中的弹性运动有些不一致

我们真实生活中的弹性运动它的加速度是会变化的

因此,我们要让它的加速度时时刻刻改变

我们先来分析一下

转换成代码

function startMove(dom, target) {

clearInterval(timer);

var iSpeed = 0; // 定义一个初速度

var a = 3; // 定义一个加速度

timer = setInterval(function () {

// 判断速度的正负值

a = (target - dom.offsetLeft) / 5;

// 速度的改变

iSpeed += a;

dom.style.left = dom.offsetLeft + iSpeed + 'px';

}, 30);

}

页面效果如下:

动是比较动感了

但是没法停下来

现实生活中的弹性运动应该是有能量的损耗的

function startMove(dom, target) {

clearInterval(timer);

var iSpeed = 0; // 定义一个初速度

var a = 3; // 定义一个加速度

timer = setInterval(function () {

// 判断速度的正负值

a = (target - dom.offsetLeft) / 5;

// 速度的改变

iSpeed += a;

// 能量的损耗

iSpeed *= 0.8;

dom.style.left = dom.offsetLeft + iSpeed + 'px';

}, 30);

}

页面效果如下:

你会发现它确实停了下来

但是他并没有直接就停留在目标点上

在页面中打印速度iSpeed和target - dom.offsetLeft看看

你会发现它一直在0和1的正负之间徘徊

因此我们可以拿它们作为停止的依据

var oDiv = document.querySelector('.flex');

oDiv.onclick = function () {

startMove(this, 300);

}

var timer = null;

function startMove(dom, target) {

clearInterval(timer);

var iSpeed = 0; // 定义一个初速度

var a = 3; // 定义一个加速度

timer = setInterval(function () {

// 判断速度的正负值

a = (target - dom.offsetLeft) / 5;

// 速度的改变

iSpeed += a;

// 能量损耗

iSpeed *= 0.8;

// 判断速度的绝对值是否小于1 并且 目标的距离减去当前的距离是否小于1

if (Math.abs(iSpeed) < 1 && Math.abs(target - dom.offsetLeft) < 1) {

clearInterval(timer);

} else {

dom.style.left = dom.offsetLeft + iSpeed + 'px';

}

}, 30);

}

页面效果如下:

它会稳稳的停在目标点上

有了上面的基础

下面我们实现一个弹性导航栏效果

弹性导航栏

HTML结构

  • cst
  • cg
  • dg
  • dxm

* {

margin: 0;

padding: 0;

list-style: none;

}

ul {

position: relative;

margin: 100px auto 0px;

width: 800px;

height: 100px;

}

ul .ele {

float: left;

width: 198px;

border: 1px solid #000000;

height: 98px;

line-height: 98px;

text-align: center;

background-color: orange;

}

.bg {

position: absolute;

left: 0;

top: 0;

width: 200px;

height: 100px;

opacity: 0.4;

background-color: deeppink;

}

var oLiArray = document.getElementsByTagName('li');

var oLiBg = oLiArray[oLiArray.length - 1];

console.log(oLiBg)

for (var i = 0; i < oLiArray.length - 1; i++) {

oLiArray[i].onmouseenter = function () {

startMove(oLiBg, this.offsetLeft);

}

}

var timer = null;

function startMove(dom, target) {

clearInterval(timer);

var iSpeed = 0;

var a = 3;

var u = 0.8;

timer = setInterval(function () {

a = (target - dom.offsetLeft) / 7;

iSpeed += a;

iSpeed *= u;

if (Math.abs(iSpeed) < 1 && Math.abs(target - dom.offsetLeft) < 1) {

clearInterval(timer);

dom.style.left = target + 'px';

} else {

dom.style.left = iSpeed + dom.offsetLeft + 'px';

}

}, 30);

}

页面效果如下:

有了上面的基础

下面我们模拟实现重力场的运动方式

HTML结构【重力场运动 + 多方向运动】

CSS样式【重力场运动 + 多方向运动】

#demo {

position: absolute;

left: 0;

top: 0;

background-color: red;

width: 100px;

height: 100px;

border-radius: 50%;

}

JS行为【重力场运动 + 多方向运动】

JS分析

**重力场运动就是模拟一个篮球从空中落下的过程**

1. 方向肯定有 x 和 y 两个

2. 还要有重力 g

3. 小球碰撞地面会反弹

var oDiv = document.getElementById('demo');

oDiv.onclick = function () {

startMove(this)

}

function startMove(dom) {

clearInterval(dom.timer);

// 定义横向运动速度

var iSpeedX = 6;

// 定义纵向运动速度

var iSpeedY = 8;

// 开启定时器

dom.timer = setInterval(function () {

// 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newLeft = dom.offsetLeft + iSpeedX;

// 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newTop = dom.offsetTop + iSpeedY;

// 设置当前的位置

dom.style.left = newLeft + 'px';

dom.style.top = newTop + 'px';

}, 30);

}

页面效果如下:

下面要进行边界的判断

如果触碰到边界方向要相应的改变方向

function startMove(dom) {

clearInterval(dom.timer);

// 第一步: 定义横向运动速度

var iSpeedX = 6;

// 1.1 定义纵向运动速度

var iSpeedY = 8;

dom.timer = setInterval(function () {

// 第二步: 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newLeft = dom.offsetLeft + iSpeedX;

// 2.1 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newTop = dom.offsetTop + iSpeedY;

// 第四步: 判断边界

// 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的高度 (触碰到界面边框)

if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {

// 4.1 方向要改变

iSpeedY *= -1;

// 4.2 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = document.documentElement.clientHeight - dom.clientHeight;

}

if (newTop <= 0) {

// 4.3 方向要改变

iSpeedY *= -1;

// 4.4 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = 0;

}

// 4.5 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的宽度 (触碰到界面边框)

if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {

// 4.6 方向要改变

iSpeedX *= -1;

// 4.7 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = document.documentElement.clientWidth - dom.clientWidth;

}

if (newLeft <= 0) {

// 4.8 方向要改变

iSpeedX *= -1;

// 4.9 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = 0;

}

// 第三步: 设置当前的位置

dom.style.left = newLeft + 'px';

dom.style.top = newTop + 'px';

}, 30);

}

那么真实的运动是会受到重力的影响的

不可能一直这样匀速的运动

下面我们进行代码编写

// 第五步

function startMove(dom) {

clearInterval(dom.timer);

// 第一步: 定义横向运动速度

var iSpeedX = 6;

// 1.1 定义纵向运动速度

var iSpeedY = 8;

// 第五步: 定义一个重力加速度

var g = 3;

dom.timer = setInterval(function () {

// 第五步: 5.1 纵向速度每次加当前的重力

iSpeedY += g;

// 第二步: 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newLeft = dom.offsetLeft + iSpeedX;

// 2.1 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newTop = dom.offsetTop + iSpeedY;

// 第四步: 判断边界

// 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的高度 (触碰到界面边框)

if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {

// 4.1 方向要改变

iSpeedY *= -1;

// 4.2 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = document.documentElement.clientHeight - dom.clientHeight;

}

if (newTop <= 0) {

// 4.3 方向要改变

iSpeedY *= -1;

// 4.4 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = 0;

}

// 4.5 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的宽度 (触碰到界面边框)

if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {

// 4.6 方向要改变

iSpeedX *= -1;

// 4.7 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = document.documentElement.clientWidth - dom.clientWidth;

}

if (newLeft <= 0) {

// 4.8 方向要改变

iSpeedX *= -1;

// 4.9 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = 0;

}

// 第三步: 设置当前的位置

dom.style.left = newLeft + 'px';

dom.style.top = newTop + 'px';

}, 30);

}

页面效果如下:

不仅有重力的影响

能量也会进行相应的损耗

下面我们进行代码编写

// 第六步 第七步

function startMove(dom) {

clearInterval(dom.timer);

// 第一步: 定义横向运动速度

var iSpeedX = 6;

// 1.1 定义纵向运动速度

var iSpeedY = 8;

// 第五步: 定义一个重力加速度

var g = 3;

// 第六步: 定义一个损耗

var u = 0.8;

// 开启定时器

dom.timer = setInterval(function () {

// 第五步: 5.1 纵向速度每次加当前的重力

iSpeedY += g;

// 第二步: 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newLeft = dom.offsetLeft + iSpeedX;

// 2.1 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newTop = dom.offsetTop + iSpeedY;

// 第四步: 判断边界

// 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的高度 (触碰到界面边框)

if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {

// 4.1 方向要改变

iSpeedY *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.2 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = document.documentElement.clientHeight - dom.clientHeight;

}

if (newTop <= 0) {

// 4.3 方向要改变

iSpeedY *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.4 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = 0;

}

// 4.5 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的宽度 (触碰到界面边框)

if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {

// 4.6 方向要改变

iSpeedX *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.7 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = document.documentElement.clientWidth - dom.clientWidth;

}

if (newLeft <= 0) {

// 4.8 方向要改变

iSpeedX *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.9 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = 0;

}

// 第三步: 设置当前的位置

dom.style.left = newLeft + 'px';

dom.style.top = newTop + 'px';

}, 30);

}

页面效果如下:

你会发现他好像稳稳的停在那儿了

但是我们并没有将定时器停止清空

那么我们要进行分析

纵向速度为0或者横向速度为0时都不满足停止的条件

纵向速度为0并且横向速度为0时也不一定满足停止的条件,因为还要判断他是否落到底边

我们在页面上打印速度(iSpeedX、iSpeedY)的值看看

你会发现它是一个非常小的数几点几的E次方

因此我们要进行判断

function startMove(dom) {

clearInterval(dom.timer);

// 第一步: 定义横向运动速度

var iSpeedX = 6;

// 1.1 定义纵向运动速度

var iSpeedY = 8;

// 第五步: 定义一个重力加速度

var g = 3;

// 第六步: 定义一个损耗

var u = 0.8;

// 开启定时器

dom.timer = setInterval(function () {

// 第五步: 5.1 纵向速度每次加当前的重力

iSpeedY += g;

// 第二步: 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newLeft = dom.offsetLeft + iSpeedX;

// 2.1 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度

var newTop = dom.offsetTop + iSpeedY;

// 第四步: 判断边界

// 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的高度 (触碰到界面边框)

if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {

// 4.1 方向要改变

iSpeedY *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.2 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = document.documentElement.clientHeight - dom.clientHeight;

}

if (newTop <= 0) {

// 4.3 方向要改变

iSpeedY *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.4 设置当前的newTop值 如果不设置,它会超出一些边界

newTop = 0;

}

// 4.5 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的宽度 (触碰到界面边框)

if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {

// 4.6 方向要改变

iSpeedX *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.7 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = document.documentElement.clientWidth - dom.clientWidth;

}

if (newLeft <= 0) {

// 4.8 方向要改变

iSpeedX *= -1;

// 第七步: 每次碰撞都会受到能量的损耗 不管横向纵向都会受到能量损耗

iSpeedY *= u;

iSpeedX *= u;

// 4.9 设置当前的newLeft值 如果不设置,它会超出一些边界

newLeft = 0;

}

console.log(iSpeedY, iSpeedX);

// 第八步: 8.1 进行判断 随便小于一个1或2的值 用来保留iSpeedX的精确值

if (Math.abs(iSpeedX) < 1) {

iSpeedX = 0;

}

// 第八步: 8.2 进行判断 随便小于一个1或2的值 用来保留iSpeedY的精确值

if (Math.abs(iSpeedY) < 1) {

iSpeedY = 0;

}

// 第九步: 判断当前的 iSpeedX == 0 并且 iSpeedY == 0 并且 当前的 newTop 值 (落到了地面上)

if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom.clientHeight) {

// 清空定时器 停止运动

clearInterval(dom.timer);

console.log('over');

// 第十步: 否则

} else {

// 第三步: 设置当前的位置

dom.style.left = newLeft + 'px';

dom.style.top = newTop + 'px';

}

}, 30);

}

页面效果如下:

结语

整完!!!

由于篇幅过大,博主把拖拽运动写到下面这篇博文里面了

- js运动函数篇(三)链接: https://www.cnblogs.com/qq4297751/p/12814248.html

相关推荐

refa沙龙版和升级版的区别 refa升级版和沙龙版哪个好
光大活期宝怎么样 光大活期宝有什么特点
雨刮器怎么开关
365bet平台网投

雨刮器怎么开关

06-29 946