Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to optimize Mini Program Shopping cart Animation

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to optimize the shopping cart animation of Mini programs. Xiaobian thinks it is quite practical, so share it with you for reference. I hope you can gain something after reading this article.

Mini programs shopping cart animation optimization

When the company Mini programs click Add Purchase, a parabolic animation will be drawn. This parabolic animation is the calculated coordinates of each point on the Bezier curve, and then js traverses the coordinates of the points, and then dynamically sets the style of the points to realize the animation. But it causes stuttering and frame dropping.

this.goodBoxTimer = setInterval(() => { index-- this.setData({ 'movingBallInfo.posX': linePos[index][0], 'movingBallInfo.posY': linePos[index][1], }) if (index

< 1) { this.resetGoodBoxStatus() }}, 30) 前置知识:Event Loop, Task, micro Task, UI Rendering javascript是单线程语言,这就意味着所有任务都要进行排队。任务分为两种:一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。 而异步任务又分为宏任务(Task)和微任务(micro Task),同理任务队列也分为宏任务队列和微任务队列。 事件循环(Event Loop) 大致步骤: 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。 只要异步任务有了运行结果,就在任务队列之中放置一个事件。 执行栈中的宏任务执行完毕,引擎会先读取微任务,推入执行栈。执行完成之后,继续读取下一个微任务。如果执行过中产生新的微任务,就会把这个微任务推入微任务队列。如果主线程执行完所有微任务队列中的任务中时,就会去读取宏任务队列,推入执行栈。 主线程不断重复上面的第三步。 常见的宏任务: setTimeout setInterval postMessage ... 常见的微任务: Promise MutationObserver 而Event Loop和UI渲染的关系呢?其实是在执行完微任务队列里所有微任务的之后,由浏览器决定是否进行渲染更新。 // demo1// 渲染发生在微任务之后const con = document.getElementById('con');con.onclick = function () { Promise.resolve().then(function Promise1 () { con.textContext = 0; })}; // demo2// 两次EventLoop中间没有渲染const con = document.getElementById('con');con.onclick = function () { setTimeout(function setTimeout1() { con.textContent = 0; Promise.resolve().then(function Promise1 () { console.log('Promise1') }) }, 0) setTimeout(function setTimeout2() { con.textContent = 1; Promise.resolve().then(function Promise2 () { console.log('Promise2') }) }, 0)}; 我们知道浏览器正常情况下的帧率是60fps,即一帧的时间大约为16.66ms。如果在一帧里对Dom进行了两次修改,那么浏览器只会取最后一次的修改值去渲染。 // demo3// 两次eventloop中有渲染const con = document.getElementById('con');con.onclick = function () { setTimeout(function setTimeout1() { con.textContent = 0; }, 0); setTimeout(function setTimeout2() { con.textContent = 1; }, 16.7);}; 尽量不要使用setInterval 由上文可知setInterval是宏任务,setInterval每隔定义的时间间隔就会往宏任务队列推入回调函数,然后主线程会读取宏任务队列里的setInterval回调函数并执行。但是如果主线程有长任务(long task)执行时,会阻塞读取,直到主线程里的任务执行完才会继续读取,但setInterval往宏任务队列添加回调函数的操作是不会停止的,这种情况下就会造成:函数执行的时间间隔远大于我们定义的时间间隔。 下面是一个例子,每次setInterval回调都需要进行大量的计算,这样阻塞主线程 // demo4const btn = document.getElementById('btn')btn.addEventListener('click', setIntervalFn)let sum = 0function setIntervalFn() { let last let countIdx = 0 const timer = setInterval(function timeFn() { countIdx++ const newTime = new Date().getTime() const gap = newTime - last last = newTime console.log('setInterval', gap, countIdx) if (countIdx >

5) clearInterval(timer) // 10000000 // 100000 for (let i = 0; i

< 100000; i++) { sum+= i } }, 100) last = new Date().getTime()} setInterval的缺点: 当主线程有代码执行时,宏任务队列会一直按照一定的时间间隔推入事件回调函数。只有当主线程空闲时,才会把回调函数执行,但是这些回调函数大多都是过时的。 如果setInterval的回调间隔比浏览器渲染一帧的时间要短,那么回调函数执行了多次,但只会用到最后一次的结果,这样也会造成浪费,甚至有可能会阻塞主线程。 所以尽量要用setTimeout去代替setInterval 使用requestAnimationFrame 如果用js去绘制动画,还是用官方推荐的requestAnimationFrame,而不是setTimeout。 window.requestAnimationFrame() 告诉浏览器--你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画 由上面的例子可知,两个宏任务之间不一定会触发浏览器渲染,这个由浏览器自己决定,并且浏览器的帧率并会一直是60fps,有时可能会下降到30fps,而setTimeout的回调时间是写死的,就有可能导致修改了多次Dom,而只触发了一次ui更新,造成掉帧。 // demo5const con = document.getElementById('con');let i = 0;function rAF(){ requestAnimationFrame(function aaaa() { con.textContent = i; Promise.resolve().then(function bbbb(){ if(i < 5) {rAF(); i++;} }); });}con.onclick = function () { rAF();}; 可以看到渲染了5次(五条竖直虚线) 小程序上的动画优化 小程序是双线程架构 好处是:ui渲染和js主线程是分开的,我们知道在浏览器中这两者是互斥的,所以当主线程有阻塞时,页面交互就会失去响应,而小程序中不会出现这样的情况。 坏处是:逻辑层、渲染层有通信延时,大量的通信也会造成性能瓶颈。 小程序提供了wxs用来处理渲染层的逻辑。 购物车抛物线动画优化 所以我们不应该用setInterval去执行动画,我们修改成,当点击加购时,把点击坐标与目标坐标传入wxs,然后计算运行轨迹点的坐标计算,接着用requestAnimationFrame执行动画帧 // wxsfunction executeCartAnimation () { curCoordIdx = coordArr.length - 1 ins.requestAnimationFrame(setStyleByFrame)}function setStyleByFrame() { if (curCoordIdx >

= 0) { ins.selectComponent('.cart-animation').setStyle({ display: 'block', left: coordArr[curCoordIdx].x + 'px', top: coordArr[curCoordIdx].y + 'px' }) curCoordIdx -= 1 ins.requestAnimationFrame(setStyleByFrame) } else { ins.selectComponent('.cart-animation').setStyle({ display: 'none' }) }}

The effect is very obvious on the real machine, and the animation on the low-end Android machine is also very smooth. But the screen recording effect is not good, so I won't put it here.

About "Mini programs shopping cart animation how to optimize" this article is shared here, I hope the above content can be of some help to everyone, so that you can learn more knowledge, if you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report