<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          圖片碎片化渲染特效實現(xiàn)

          共 7671字,需瀏覽 16分鐘

           ·

          2024-07-09 09:10

              


          寫在開頭

          最近,小編從玩了兩年多的游戲中退游了??,本來以為會一直就這么玩下去,和隊友們相處很融洽,收獲了很多開心快樂的時光??。可惜,游戲的一波更新......準備要開始收割韭菜了,只能無奈選擇棄坑了。

          小編屬于貧民玩家,靠著硬肝與白嫖也將游戲號整得還不錯,這兩天把號給賣了??。玩了兩年多,竟然還能賺一點小錢,很開心??。只是...多少有點舍不得的一起組隊的隊友們,唉。??

          記錄一下,希望未來還有重逢一日吧,也希望各位一切安好!??

          好,回到正題,本文將分享一個圖片碎片化展示的效果,具體效果如下,請諸君按需食用。

          原理

          這種特效早在幾年前就已經(jīng)出現(xiàn),屬于老演員了??,它最早是經(jīng)常在輪播圖(banner)上應(yīng)用的,那會追求各種花里胡哨的特效,而現(xiàn)在感覺有點返璞歸真了,簡潔實用就行。

          今天咱們來看看它的具體實現(xiàn)原理是如何的,且看圖:

          一圖勝千言,不知道聰明的你是否看明白了???

          大概原理是:通過容器/圖片大小生成一定數(shù)量的小塊,然后每個小塊背景也使用相同圖片,再使用 background-sizebackground-position 屬性調(diào)整背景圖片的大小與位置,使小塊又合成一整張大圖片,這操作和使用"精靈圖"的操作是一樣的,最后,我們再給每個小塊增加動畫效果,就大功告成。

          簡單樸實??,你可以根據(jù)這個原理自個嘗試一下,應(yīng)該能整出來吧。??

          具體實現(xiàn)

          布局與樣式:


          <!DOCTYPE html>
          <html>
          <head>
          <style>
          body{
          width: 100%;
          height: 100vh;
          padding: 0;
          margin: 0;
          display: flex;
          justify-content: center;
          align-items: center;
          }
          .box {
          width: var(--width);
          height: var(--height);
          display: flex;
          /* 小塊自動換行排列 */
          flex-wrap: wrap;
          justify-content: center;
          }
          .small-box {
          background-image: url('https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/99b070fcb1de471d9af4f4d5d3f71909~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1120&h=1680&s=2088096&e=png&b=d098d0');
          box-sizing: border-box;
          background-repeat: no-repeat;
          }
          </style>
          </head>
          <body>
          <div id="box" class="box"></div>
          </body>
          </html>

          生成無數(shù)小塊填充:


          <script>
          document.addEventListener('DOMContentLoaded', () => {
          const box = document.getElementById('box');
          const { width, height } = box.getBoundingClientRect();
          // 定義多少個小塊,由多少行和列決定
          const row = 14;
          const col = 10;
          // 計算小塊的寬高
          const smallBoxWidth = width / col;
          const smallBoxHeight = height / row;
          /** @name 創(chuàng)建小塊 **/
          function createSmallBox() {
          for (let i = 0; i < row; i++) {
          for (let j = 0; j < col; j++) {
          const smallBox = document.createElement('div');
          smallBox.classList.add('small-box');
          smallBox.style.width = smallBoxWidth + 'px';
          smallBox.style.height = smallBoxHeight + 'px';
          smallBox.style.border = '1px solid red';
          // 插入小塊
          box.appendChild(smallBox);
          }
          }
          }
          createSmallBox();
          });
          </script>

          上面,生成多少個小塊是由人為規(guī)定行(row)與列(col)來決定。可能有的場景想用小塊固定的寬高來決定個數(shù),這也是可以的,只是需要注意處理一下"邊界"的情況。??

          調(diào)整小塊背景圖片的大小與位置:


          <script>
          document.addEventListener('DOMContentLoaded', () => {
          // ...
          function createSmallBox() {
          for (let i = 0; i < row; i++) {
          for (let j = 0; j < col; j++) {
          // ...
          smallBox.style.border = '1px solid red';

          // 設(shè)置背景偏移量,讓小塊的背景顯示對應(yīng)圖片的位置,和以前那種精靈圖一樣
          const offsetX = j * smallBoxWidth * -1;
          const offsetY = i * smallBoxHeight * -1;
          smallBox.style.backgroundPosition = `${offsetX}px ${offsetY}px`;
          smallBox.style.backgroundSize = `${width}px ${height}px`;

          box.appendChild(smallBox);
          }
          }
          }
          createSmallBox();
          });
          </script>

          女神拼接成功,到這里就已經(jīng)完成一大步了,是不是沒什么難度!??

          小塊樣式整好后,接下來,我們需要來給小塊增加動畫,讓它們動起來,并且是有規(guī)律的動起來。

          先來整個簡單的透明度動畫,且看:


          <!DOCTYPE html>
          <html>
          <head>
          <style>
          /* ... */
          .small-box {
          /* ... */
          opacity: 0;
          animation: smallBoxAnimate 2000ms linear forwards;
          }
          @keyframes smallBoxAnimate {
          0% {
          opacity: 0;
          }
          40% {
          opacity: 0;
          }
          70% {
          opacity: 1;
          }
          100% {
          opacity: 1;
          }
          }
          </style>
          </head>
          <body>
          <script>
          document.addEventListener('DOMContentLoaded', () => {
          // ...
          function createSmallBox() {
          for (let i = 0; i < row; i++) {
          for (let j = 0; j < col; j++) {
          // ...
          // smallBox.style.border = '1px solid red';

          // 給每個小塊增加不同的延時,讓動畫不同時間執(zhí)行
          const delay = i * 100; // 延遲時間為毫秒(ms),注意不要太小了
          smallBox.style.animationDelay = `${delay}ms`;

          box.appendChild(smallBox);
          }
          }
          }
          createSmallBox();
          });
          </script>
          </body>
          </html>

          嘿嘿??,稍微有點意思了吧?


          Em...等等,你發(fā)現(xiàn)沒有?怎么有一些小白條?這可不是小編添加的,小塊的邊框(border)已經(jīng)是注釋了的。??

          一開始小編以為是常見的"圖片底部白邊"問題,直接設(shè)置一下 display: block 或者 vertical-align : middle 就能解決,結(jié)果還不是,折騰了很久都沒有搞掉這個小白條。??

          最后,竟然通過設(shè)置 will-change 屬性能解決這個問題?我所知道的 will-change 應(yīng)該是應(yīng)用在性能優(yōu)化上,解決動畫流暢度問題上的,想不到這里竟然也能用。

          看來得去深度學(xué)習(xí)一下?? will-change 屬性的原理過程才行,這里也推薦倔友寫得一篇文章:傳送門。

          解決相鄰背景圖片白條/白邊間隙問題:


          <script>
          document.addEventListener('DOMContentLoaded', () => {
          // ...
          function createSmallBox() {
          for (let i = 0; i < row; i++) {
          for (let j = 0; j < col; j++) {
          // ...

          smallBox.style.willChange = 'transform';
          // 在動畫執(zhí)行后,需要重置will-change
          const timer = setTimeout(() => {
          smallBox.style.willChange = 'initial';
          clearTimeout(timer);
          }, 2000);

          box.appendChild(smallBox);
          }
          }
          }
          createSmallBox();
          });
          </script>

          一定要注意 will-change 不可能被濫用,注意重置回來?

          這下女神在動畫執(zhí)行后,也清晰可見了,這是全部小塊拼接組成的圖片。

          在上述代碼中,咱們看到,通過 animation-delay 去延遲動畫的執(zhí)行,就能制造一個從上到下的漸變效果。

          那么,咱們再改改延遲時間,如:


          // const delay = i * 100;
          // 改成 ?
          const delay = j * 100;

          效果:

          這...好像有那么點意思吧。。。

          但是,這漸變...好像還達不到我們開頭 gif 的碎片化效果吧?

          那么,碎片化安排上:


          .small-box {
          /* ... */
          --rotateX: rotateX(0);
          --rotateY: rotateY(0);
          transform: var(--rotateX) var(--rotateY) scale(0.8);
          }
          @keyframes smallBoxAnimate {
          0% {
          opacity: 0;
          transform: var(--rotateX) var(--rotateY) scale(0.8);
          }
          40% {
          opacity: 0;
          transform: var(--rotateX) var(--rotateY) scale(0.8);
          }
          70% {
          opacity: 1;
          transform: rotateX(0) rotateY(0) scale(0.8);
          }
          100% {
          opacity: 1;
          transform: rotateX(0) rotateY(0) scale(1);
          }
          }

          其實就是增加小塊的樣式動畫而已,再加點旋轉(zhuǎn),再加點縮放,都整上,整上。??

          效果:

          是不是稍微高級一點?有那味了???

          看到上面旋轉(zhuǎn)所用的"樣式變量"沒有?


          --rotateX: rotateX(0);
          --rotateY: rotateY(0);

          不可能無緣無故突然使用,必然是有深意啦。??

          現(xiàn)在效果還不夠炫,咱們將樣式變量利用起來,讓"相鄰兩個小塊旋轉(zhuǎn)相反":


          <script>
          document.addEventListener('DOMContentLoaded', () => {
          // ...
          function createSmallBox() {
          for (let i = 0; i < row; i++) {
          for (let j = 0; j < col; j++) {
          // ...

          // 相鄰兩個小塊旋轉(zhuǎn)相反
          const contrary = (i + j) % 2 === 0;
          smallBox.style.setProperty('--rotateX', `rotateX(${contrary ? -180 : 0}deg)`);
          smallBox.style.setProperty('--rotateY', `rotateY(${contrary ? 0 : -180}deg)`);

          box.appendChild(smallBox);
          }
          }
          }
          createSmallBox();
          });
          </script>

          效果:

          這下對味了。??

          總的來說,我們可以通過"延遲"執(zhí)行動畫與改變"旋轉(zhuǎn)"行為,讓小塊們呈現(xiàn)不同的動畫效果,或者你只要有足夠多的設(shè)想,你可以給小塊添加不同的動畫效果,相信也能制造出不錯的整體效果。

          更多效果

          下面列舉一些通過"延遲"執(zhí)行動畫產(chǎn)生的效果,可以瞧瞧哈。

          隨機:


          const getRandom = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
          const delay = getRandom(0, col + row) * 100;

          從左上角到右下角:


          const delay = (i + j) * 100;

          其他的從"右上角到左下角"或者"左下角到右上角"等等的,只要反向調(diào)整一下變量就行了,就靠你自己悟啦,Come On!??

          從中心向四周擴散:


          const delay = ((Math.abs(col / 2 - j) + Math.abs(row / 2 - i))) * 100;

          從四周向中心聚齊:


          const delay = (col / 2 - Math.abs(col / 2 - j) + (col / 2 - Math.abs(row / 2 - i))) * 100;

          那么,到這里就差不多了?

          但還有最后一個問題,那就是圖片的大量使用與加載時長的情況可能會導(dǎo)致效果展示不佳,這里你最好進行一些防范措施,如:

          • 圖片鏈接設(shè)置緩存,讓瀏覽器緩存到內(nèi)存或硬盤中。

          • 通過 JS 手動將圖片緩存到內(nèi)存,主要就是創(chuàng)建 Image 對象。

          • 將圖片轉(zhuǎn)成 base64 使用。

          • 直接將圖片放到代碼本地使用。

          • ...

          以上等等吧,反正最好就是要等圖片完整加載后再進行效果展示。

          至此,本篇文章就寫完啦,撒花撒花。

          原文鏈接:https://juejin.cn/post/7379856289487831074
          作者:橙某人

          瀏覽 183
          1點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          1點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码精品在线观看 | 少妇无码青娱乐 | 五月天婷婷影院影院 | 欧美三级电影在线 | 日日奸日日射日日舔日日干APP |