ustbhuangyi / vue-sell

:rice: Vue.js高仿饿了么外卖App课程源码 http://coding.imooc.com/class/74.html
3.46k stars 1.36k forks source link

小球动画所暴露出的问题, 望作者回复. #68

Open ResearchWorld opened 6 years ago

ResearchWorld commented 6 years ago

问题

问题设想

思考这样一个问题,当动画需求时间要长或电脑比较卡迟钝。 当第一次点击一个cartcontrol,第二次点击另一个cartcontrol。那么当第二次点击时触发的beforeDrop会遍历前面那个还在动画过程中的小球,并把前面第一个小球的位置赋予当前的这个。

测试结果

经过我本人测试,也确实如上面所说的一样,不过他表现出来的现象又是正常的,并没受到遍历后面小球所得位置所影响,这个有些不能理解且如何解决上面那个逻辑所露出来的问题呢?

代码部分

JS如下

        beforeDrop (el) {
            let pos = this.balls.length;
            console.log('begin-beforeDrop');
            while (pos--) {
                if (this.balls[pos].show) {
                    let rect = this.balls[pos].el.getBoundingClientRect();
                    let x = rect.left - 32;
                    let y = -(window.innerHeight - 22 - rect.top - 16);

                    el.style.webkitTransform = `translate(${x}px,0)`;
                    el.style.transform = `translate(${x}px,0)`;

                    let inner_el = el.getElementsByClassName('inner-hook')[0];
                    inner_el.style.webkitTransform = `translate(0,${y}px)`;
                    inner_el.style.transform = `translate(0,${y}px)`;

                    el.style.display = '';
                    console.log(`x:${x},y:${y}`);
                }
            }
            console.log('end-beforeDrop\n');
        }

CSS如下:

    .ball-container{
        .ball{
            position: fixed;
            left: 32px;
            bottom: 22px;
            z-index: 200;
            transition: all 10s cubic-bezier(.04,.76,.34,1.4);  // 把动画设成了10秒的过程
            .inner{
                width: 16px;
                height: 16px;
                border-radius: 50%;
                background: rgb(0, 160, 220);
                transition: all 10s linear;  // 把动画设成了10秒的过程
            }
        }
    }

输出结果

begin-beforeDrop
x:289,y:-358
end-beforeDrop

begin-beforeDrop
x:289,y:-259
x:289,y:-358 // 这里表示不能理解,也觉得不知道到底是不是问题。
end-beforeDrop 
duolaAmeng0901 commented 6 years ago

ele.getBoundingClientRect()会触发回流。

正常情况下浏览器会对引起回流和重绘的操作进行优化。比如我们对DOM的操作,浏览器会在一定时间内将统一计算,并将最终的结果绘制到页面上。

没有触发回流,浏览器渲染一次,直接将while循环的最终结果绘制到页面上,按照上面的例子(第二次点击时): 直接 x: 289 y:-358

触发回流,浏览器渲染多次,按照上述例子为(第二次点击时): 从 x:289,y:-259 到 x:289,y:-358 但是因为这2次之间时间很短,所以看起来几乎不见。

不确定是否说的明白,只是我的理解!