一个随机在边边角角运动的实例
<style>#papa {
margin: 50px auto 0;
width: 720px;
height: 600px;
box-shadow: 4px 4px 24px #000;
position: relative;
}
#piece {
position: absolute;
width: 90px;
height: 66px;
transition: all 4s;
}
</style>
<div id="papa">
<imgid="piece" alt="" src="/data/attachment/forum/202207/08/225900jzc7ctq9wa99r83a.gif" />
</div>
<script>
let aniFlag = 0; //动画标识
let num = (min, max) => Math.floor(Math.random() * (max-min+1)) + min;
setTimeout(gogo,100); //初次运行动画
function gogo() { //动画函数
let idx1 =num(0,1), idx2 = num(0,1);
let w1 = papa.clientWidth, w2 = piece.clientWidth, h1 = papa.clientHeight, h2 = piece.clientHeight;
piece.style.left = (w1 - w2) * idx1 + 'px';
piece.style.top = (h1 - h2) * idx2 + 'px';
setTimeout(gogo,6000);
}
</script>
代码:
<style>
#papa {
margin: 50px auto 0;
width: 720px;
height: 600px;
box-shadow: 4px 4px 24px #000;
position: relative;
}
#piece {
position: absolute;
width: 90px;
height: 66px;
transition: all 4s;
}
</style>
<div id="papa">
<imgid="piece" alt="" src="/data/attachment/forum/202207/08/225900jzc7ctq9wa99r83a.gif" />
</div>
<script>
let aniFlag = 0; //动画标识
let num = (min, max) => Math.floor(Math.random() * (max-min+1)) + min;
setTimeout(gogo,100); //初次运行动画
function gogo() { //动画函数
let idx1 =num(0,1), idx2 = num(0,1);
let w1 = papa.clientWidth, w2 = piece.clientWidth, h1 = papa.clientHeight, h2 = piece.clientHeight;
piece.style.left = (w1 - w2) * idx1 + 'px';
piece.style.top = (h1 - h2) * idx2 + 'px';
setTimeout(gogo,6000);
}
</script>
本帖最后由 马黑黑 于 2022-7-8 23:15 编辑
预设的“飞行”路线是酱紫:
每一次都从四个角出发,有时候不出发,因为是随机的,上一个随机数可能与下一次随机数重合,有时候会重合几次。路线有边线,也有对角线。
驱动的实现,利用 left 与 top 值的变更促成:上一个 left 与 top,在一个定时器周期完成后转换为下一个 left 与 top,借助运动对象元素的 transition 设定,达成规定时间内沿两点间的位移效果。transition 的时间少于定时器周期时长,这是逻辑关系问题:动作做完之后才能发起下一个位移。
下楼讲讲JS代码。
本帖最后由 马黑黑 于 2022-7-8 23:32 编辑
下面重点解释一下自定义的 gogo() 函数
[*]function gogo() { //动画函数
[*] let idx1 =num(0,1), idx2 = num(0,1);
[*] let w1 = papa.clientWidth, w2 = piece.clientWidth, h1 = papa.clientHeight, h2 = piece.clientHeight;
[*] piece.style.left = (w1 - w2) * idx1 + 'px';
[*] piece.style.top = (h1 - h2) * idx2 + 'px';
[*] setTimeout(gogo,6000);
[*]}
函数不长。
首先,32行,声明并赋值两个变量,idx1和idx2,它们都是通过前面声明的 num() 函数获得 0 到 1 的整数,不是0就是1。这两个变量的作用是随机设定四个角的依据。着四个角,左上、右上、右下、左下可以记为 {0,0}、{0,1}、{1,1}、{0,1},其中,0表示left或top不变,是0px,1表示left或top有变,是父元素宽或高减去子元素宽或高之后的值。
接着,33行,用w1、w2分别获取父元素、子元素的宽度,用h1、h2分别获取父元素、子元素的高度;
34行,计算子元素(id="piece")的左边值(left),(父宽-子宽)* idx1 的式子能理解吧?idx1是随机获得是要么是0要么是1的数,是0时,left值就是0px了,是1时,left值则是 父宽-子宽 个像素的值。
35行,计算子元素的上边值(top),原理和34行同。
35行,setTimeout定时器调用本函数。setTimeout定时器在函数内部运行函数,叫递归调用,会循环不已,前提是要有的函数外的首次调用(这在前面已经有了)。
这个例子,在使用UFO图片之前,我还加入了一个 animation 动画,它运动对象要么向左转动,要么向右旋转,这个UFO已经有这个动作(虽然性质不同),就取消掉了。
结合 @keyframes 令对象运动,可以使得运动的样式更为多样化。 运动方向是随机的,能猜出它下一个运动方向的,去摸奖肯定能中{:4_170:} 如果想设置更复杂的路线,比如可以在任一点停留,思路要改一改:
在 gogo 函数里用一个数组直接装载各点的{xy}像素值,像下面这样,
let psAr = [,,, ....];
预存储的数组元素越多,运动的路线就越丰富。
然后,用随机数抓取数组中的xy点:
let idx1 = psAr,idx2 = psAr;
再将idx1和idx2赋值给子元素的 left 和 top 值:
piece.style.left = idx1 + 'px';
piece.style.top = idx2 + 'px'; JS里,不见声明待操作元素的操作句柄,例如要对 <div id="piece"></div> 进行相关操作,必先取得其代理变量:
var piece = document.getElementById('piece');
然后才可通过 piece 进行相关的操作。本例直接操作 piece ,事先并未声明,是什么道理?
原来:在 HTML5 里,拥有唯一标识的元素,该标识直接指向该元素,JS中可以直接使用该标识对之进行识别与操作。可能部分浏览器不支持,但不支持的都是已经过时、被废弃的浏览器,如IE和基于IE内核的第三方封装浏览器。我们无需去兼容这一类浏览器,可以按照HTML5的标准去编写代码。 看到一个飞碟在探索边边角角,这是外星人要入侵的节奏么{:4_173:} 马黑黑 发表于 2022-7-8 23:59
如果想设置更复杂的路线,比如可以在任一点停留,思路要改一改:
在 gogo 函数里用一个数组直接装载各点 ...
这个是随机抓取,如果设计个线路,依次抓取是怎样的代码? 红影 发表于 2022-7-9 08:41
这个是随机抓取,如果设计个线路,依次抓取是怎样的代码?
随机的太难控,喜欢它按照约定的线路行进{:4_173:} 本帖最后由 马黑黑 于 2022-7-9 08:57 编辑
红影 发表于 2022-7-9 08:41
这个是随机抓取,如果设计个线路,依次抓取是怎样的代码?
从头到尾依次获得数组中的位置,需要设置一个自增变量,放在JS的比较开始的位置,比如设定为 myIdx:
let myIdx = 0; //开始时是0
然后在自定义函数内,通过 myIdx 得到数组的第 myIdx 元素并将值分别赋予元素的left和top:
piece.style.left = psAr;
piece.style.top = psAr;
接着,在函数内处理 myIdx 增量问题:
myIdx ++;
if(myIdx > psAr.length - 1) myIdx = 0;
上面第一句,是 myIdx 使用完一次就增量,增量会突破数组元素总数,所以要处理一下,这就是第二句:如果 myIdx 大于等于数组元素总数减去1,则 myIdx 回到0,从头开始。读取数组下标从 0 开始,所以式子总是像上面那样去处置。 红影 发表于 2022-7-9 08:40
看到一个飞碟在探索边边角角,这是外星人要入侵的节奏么
是要治理沙漠 红影 发表于 2022-7-9 08:42
随机的太难控,喜欢它按照约定的线路行进
随机需要规定范围便可。既定路线,则需要编写好路线图(用数组装载xy坐标),这也是繁琐的工作。设计一个作品,设计的东西的确很多、很细。 山人 发表于 2022-7-9 07:07
JS里,不见声明待操作元素的操作句柄,例如要对进行相关操作,必先取得其代理变量:
var piece = docum ...
拥有唯一标识的元素,可以不用先取得其代理变量。嗯嗯,记下了{:4_187:} 马黑黑 发表于 2022-7-8 23:38
运动方向是随机的,能猜出它下一个运动方向的,去摸奖肯定能中
能猜出它下一个运动方向的,肯定第一个被外星人抓走{:4_170:} 红影 发表于 2022-7-9 09:01
能猜出它下一个运动方向的,肯定第一个被外星人抓走
因为脑电波对上号了? 马黑黑 发表于 2022-7-8 23:07
下面重点解释一下自定义的 gogo() 函数
原来随机调用是let idx1 =num(0,1), idx2 = num(0,1);
这个let num = (min, max) => Math.floor(Math.random() * (max-min+1)) + min;没看懂,能详细解释一下么?
红影 发表于 2022-7-9 09:18
原来随机调用是let idx1 =num(0,1), idx2 = num(0,1);
这个let num = (min, max) => Math.floor(Math. ...
这是箭头函数,简化的写法。两个参数,min, max,分别表示一大一小的两个数,调用时是这样:
num(1,100)
这将返回从 1(包含1)到 100(包含100)的一个随机整数。
函数的内容是一些运算机制,几个数学方法、式子套用,其中:
Math.random() * (max - min + 1)将得到一个随机浮点数,Math.random() 得到的是 从 0 到 1(不包含1)的浮点数,乘以 max-min+1 自己思考一下。浮点数之前加入Math.floor 表示向下取整。因为这一节获得的数字有可能是0,所以后面加上 min,确保 边界最小数能有机会获取。 马黑黑 发表于 2022-7-9 08:53
从头到尾依次获得数组中的位置,需要设置一个自增变量,放在JS的比较开始的位置,比如设定为 myIdx:
l ...
谢谢黑黑,有个这个,我貌似也应该做个帖子,试验一下按规定线路走{:4_173:}