Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

青灯夜游
Lepaskan: 2021-12-28 10:21:49
ke hadapan
2316 orang telah melayarinya

Artikel ini akan berkongsi dengan anda amalan pengoptimuman animasi program mini untuk melihat cara mengoptimumkan animasi troli beli-belah program mini Saya harap ia akan membantu semua orang.

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

Pengoptimuman animasi troli beli-belah program mini

Apabila program mini syarikat mengklik untuk menambah pembelian, animasi parabola akan dilukis animasi dikira Koordinat setiap titik pada lengkung Bezier dilalui oleh js, dan kemudian gaya titik ditetapkan secara dinamik untuk mencapai animasi. Tetapi ini akan membawa masalah bingkai tersekat dan terjatuh

this.goodBoxTimer = setInterval(() => {
  index--
  this.setData({
    'movingBallInfo.posX': linePos[index][0],
    'movingBallInfo.posY': linePos[index][1],
  })
  if (index < 1) {
    this.resetGoodBoxStatus()
  }
}, 30)
Salin selepas log masuk

Pengetahuan prasyarat: Gelung Acara, Tugasan, Tugasan mikro, Rendering UI

Javascript ialah bahasa satu-utas, yang bermaksud semua tugasan mesti beratur. Terdapat dua jenis tugasan: satu tugas segerak (synchronous) dan satu lagi ialah tugas tak segerak (asynchronous). Tugasan segerak merujuk kepada tugasan yang beratur untuk pelaksanaan pada utas utama Tugas seterusnya hanya boleh dilaksanakan selepas tugasan sebelumnya telah dilaksanakan merujuk kepada tugasan yang tidak memasuki utas utama tetapi memasuki "tugasan tugasan". hanya apabila "baris gilir tugas" memberitahu utas utama bahawa tugas tak segerak boleh dilaksanakan, tugas itu akan memasuki utas utama untuk dilaksanakan.

Tugas tak segerak dibahagikan kepada tugasan makro dan tugasan mikro. Begitu juga, baris gilir tugasan juga dibahagikan kepada baris gilir tugasan makro dan baris gilir tugasan mikro.

Langkah kasar gelung peristiwa:

  • Semua tugas penyegerakan dilaksanakan pada urutan utama, membentuk tindanan konteks pelaksanaan.

  • Selagi tugas tak segerak mempunyai hasil larian, acara diletakkan dalam baris gilir tugas.

  • Selepas tugasan makro dalam tindanan pelaksanaan dilaksanakan, enjin akan membaca tugas mikro terlebih dahulu dan menolaknya ke dalam tindanan pelaksanaan. Selepas pelaksanaan selesai, teruskan membaca microtask seterusnya. Jika microtask baharu dijana semasa pelaksanaan, microtask ini akan ditolak ke dalam baris gilir microtask. Jika utas utama selesai melaksanakan semua tugas dalam baris gilir microtask, ia akan membaca baris gilir macrotask dan menolaknya ke dalam timbunan pelaksanaan.

  • Urut utama terus mengulangi langkah ketiga di atas.

Tugas makro biasa:

  • setTimeout
  • setInterval
  • postMessage
  • ...

Microtasks biasa:

  • Promise
  • MutationObserver

Apakah hubungan antara Event Loop dan rendering UI? Malah, selepas semua tugasan mikro dalam baris gilir microtask dilaksanakan, penyemak imbas memutuskan sama ada untuk melakukan kemas kini pemaparan.

// demo1
// 渲染发生在微任务之后
const con = document.getElementById(&#39;con&#39;);
con.onclick = function () {
  Promise.resolve().then(function Promise1 () {
    con.textContext = 0;
  })
};
Salin selepas log masuk

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

// demo2
// 两次EventLoop中间没有渲染
const con = document.getElementById(&#39;con&#39;);
con.onclick = function () {
  setTimeout(function setTimeout1() {
      con.textContent = 0;
      Promise.resolve().then(function Promise1 () {
          console.log(&#39;Promise1&#39;)
    })
  }, 0)
  setTimeout(function setTimeout2() {
    con.textContent = 1;
    Promise.resolve().then(function Promise2 () {
        console.log(&#39;Promise2&#39;)
    })
  }, 0)
};
Salin selepas log masuk

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

Kami tahu bahawa kadar bingkai penyemak imbas dalam keadaan biasa ialah 60fps, iaitu masa satu bingkai adalah lebih kurang 16.66ms. Jika Dom diubah suai dua kali dalam satu bingkai, penyemak imbas hanya akan menggunakan nilai diubah suai terakhir untuk dipaparkan.

// demo3
// 两次eventloop中有渲染
const con = document.getElementById(&#39;con&#39;);
con.onclick = function () {
  setTimeout(function  setTimeout1() {
    con.textContent = 0;
  }, 0);
  setTimeout(function  setTimeout2() {
    con.textContent = 1;
  }, 16.7);
};
Salin selepas log masuk

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

Cuba jangan gunakan setInterval

Seperti yang dapat dilihat dari atas, setInterval ialah tugas makro, setInterval Fungsi panggil balik ditolak ke dalam baris gilir tugas makro pada setiap selang masa yang ditentukan, dan kemudian utas utama membaca fungsi panggil balik setInterval dalam baris gilir tugas makro dan melaksanakannya. Walau bagaimanapun, jika utas utama mempunyai pelaksanaan tugas yang panjang, ia akan menyekat bacaan dan tidak akan meneruskan bacaan sehingga tugas dalam utas utama dilaksanakan Walau bagaimanapun, operasi setInterval untuk menambah fungsi panggil balik pada baris gilir tugasan makro tidak akan berhenti. Dalam kes ini, ia akan menyebabkan: selang masa antara pelaksanaan fungsi adalah lebih besar daripada selang masa yang kami tetapkan.

Berikut ialah contoh. Setiap panggilan balik setInterval memerlukan banyak pengiraan, yang menyekat urutan utama

// demo4
const btn = document.getElementById(&#39;btn&#39;)
btn.addEventListener(&#39;click&#39;, setIntervalFn)
let sum = 0
function 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(&#39;setInterval&#39;, gap, countIdx)
    if (countIdx > 5) clearInterval(timer)
    // 10000000
    // 100000
    for (let i = 0; i < 100000; i++) {
      sum+= i
    }
  }, 100)
  last = new Date().getTime()
}
Salin selepas log masuk

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

Kelemahan setInterval:

  • Apabila urutan utama mempunyai pelaksanaan kod, baris gilir tugas makro akan sentiasa menolak fungsi panggil balik acara pada selang masa tertentu. Fungsi panggil balik hanya akan dilaksanakan apabila utas utama melahu, tetapi kebanyakan fungsi panggil balik ini sudah lapuk.
  • Jika selang panggilan balik setInterval adalah lebih pendek daripada masa yang diambil oleh penyemak imbas untuk memaparkan bingkai, maka fungsi panggil balik dilaksanakan beberapa kali, tetapi hanya hasil terakhir yang akan digunakan, yang juga akan menyebabkan pembaziran malah boleh menyebabkan Sekat benang utama.

Jadi cuba gunakan setTimeout dan bukannya setInterval

Gunakan requestAnimationFrame

Jika anda menggunakan js untuk melukis animasi , Masih menggunakan requestAnimationFrame yang disyorkan secara rasmi dan bukannya setTimeout.

window.requestAnimationFrame() Beritahu penyemak imbas bahawa anda ingin melakukan animasi dan minta penyemak imbas memanggil fungsi panggil balik yang ditentukan untuk mengemas kini animasi sebelum lukisan semula seterusnya

由上面的例子可知,两个宏任务之间不一定会触发浏览器渲染,这个由浏览器自己决定,并且浏览器的帧率并会一直是60fps,有时可能会下降到30fps,而setTimeout的回调时间是写死的,就有可能导致修改了多次Dom,而只触发了一次ui更新,造成掉帧。

// demo5
const con = document.getElementById(&#39;con&#39;);
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();
};
Salin selepas log masuk

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

可以看到渲染了5次(五条竖直虚线)

小程序上的动画优化

小程序是双线程架构

Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini

好处是:ui渲染和js主线程是分开的,我们知道在浏览器中这两者是互斥的,所以当主线程有阻塞时,页面交互就会失去响应,而小程序中不会出现这样的情况。

坏处是:逻辑层、渲染层有通信延时,大量的通信也会造成性能瓶颈。

小程序提供了wxs用来处理渲染层的逻辑。

购物车抛物线动画优化

所以我们不应该用setInterval去执行动画,我们修改成,当点击加购时,把点击坐标与目标坐标传入wxs,然后计算运行轨迹点的坐标计算,接着用requestAnimationFrame执行动画帧

// wxs
function executeCartAnimation () {
  curCoordIdx = coordArr.length - 1
  ins.requestAnimationFrame(setStyleByFrame)
}

function setStyleByFrame() {
  if (curCoordIdx >= 0) {
    ins.selectComponent(&#39;.cart-animation&#39;).setStyle({
      display: &#39;block&#39;,
      left: coordArr[curCoordIdx].x + &#39;px&#39;, 
      top: coordArr[curCoordIdx].y + &#39;px&#39;
    })
    curCoordIdx -= 1
    ins.requestAnimationFrame(setStyleByFrame)
  } else {
    ins.selectComponent(&#39;.cart-animation&#39;).setStyle({
      display: &#39;none&#39;
    })
  }
}
Salin selepas log masuk

在真机上效果非常明显,低端安卓机上的动画也非常丝滑。但是录屏效果不好,这里就不放了。

【相关学习推荐:小程序开发教程

Atas ialah kandungan terperinci Rakam amalan dan lihat cara mengoptimumkan animasi troli beli-belah program mini. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan