vue 类似于红包雨 匀速下降

image.png


list: [
        {x: 120, y: 0, w: 60, h: 60, text:'A', },
        {x: 280, y: 0, w: 60, h: 60, text:'B', },
        {x: 120, y: 0, w: 60, h: 60, text:'C', },
    ],

A球在C球下方,求实现圆球匀速下落或者加速下落写法, 三个小球不是同时下落,随机有先有后下落

 window.setInterval(_ => {
    this.list.forEach(item => {
        item.y += 1
    })
}, 30)

暂停时,让所有小球暂停,但下面的代码无效
window.clearInterval(this.timer)

阅读 2.9k
4 个回答

https://codepen.io/jamesfancy...

const $balls = $("span.ball");

function randomInt(max) {
    return Math.floor(Math.random() * max);
}

const step = 300 / 4;
const start = step;
$balls.each((i, ball) => {
    $(ball).css("left", `${start + step * i - 10}px`);
    // 将高度初始化为随机的负值(拉开距离)
    // 如果想动画一开始就看到下落,可以修正他们的高度,使最下面一个小球的高度正好在顶线外
    $(ball).css("top", `${-randomInt(200)}px`);
});

// 定时下落(匀速)
const fallStep = 3;
const timer = setInterval(() => {
    let allDown = true;

    // 依次改变高度
    $balls.each((_, ball) => {
        const $ball = $(ball);
        let top = $ball.position().top;
        top += fallStep;
        $ball.css("top", `${top}px`);
        if (top < 500) {
            allDown = false;
        }
    });

    // 如果所有小球都落到底线外,停止动画
    if (allDown) {
        clearInterval(timer);
    }
}, 40);

如果想加速度,可以在计算高度增量的时候把加速度算进去。

如果希望各小球的速度不一样,但都从顶点加速下落,可以把高度初始化成同一个,但是开始下落的时机不同。每个小球内(通过 $.data() 等手段)保存自己的触发次数(即时间),从而计算当前速度。

每个小球不同时下落,那么他们每一个都是一个实例,你应该分别管理他们,这可以写一个数组,或者就直接把定时器放在list元素上

var maxy = 600 // 最大高度,不能无限下落吧,是的话把这个去掉

function animat(item, t = 1000 / 60){
    item.timer = setTimeout(() => {
        item.y += 1 // 速度 1, 加速可以写个加速算法
        
        if(item.y <= maxy){
            // 第二个参数不传,使用默认时间(第二次后使用的时间)
            animat(item)
        }
    }, t)
}

// 开始
function start(){
    list.forEach(item => {
        // 第一次下落,提供随机下落时间
        let t = Math.random() * 1000
        animat(item, t)
    })
}

// 结束
function end(){
    list.forEach(item => {
        clearTimeout(item.timer)
    })
}

setInterval 函数每执行一次都会返回一个定时器 ID,将这个 ID 传递给 clearInterval执行就可以停止这个 ID 对应的定时器。
很明显你贴出的代码里,setInterval 执行产生的 ID 并没有存储,传给 clearIntervalthis.timer 自然也是毫无来由的。
至少应该这样做:

const  timer = setInterval(function callback(){
    // 定时器的内容
});

// 到了应该停止的时候
clearInterval(timer);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题