<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>

          使用前端技術(shù)實現(xiàn)靜態(tài)圖片局部流動效果

          共 8352字,需瀏覽 17分鐘

           ·

          2022-11-29 15:00

          大廠技術(shù) ?? 高級前端 ?? Node進階

          點擊上方? 程序員成長指北 ,關(guān)注公眾號

          回復 1 ,加入高級Node交流群


          聲明: 本文涉及圖文和模型素材僅用于個人學習、研究和欣賞,請勿二次修改、非法傳播、轉(zhuǎn)載、出版、商用、及進行其他獲利行為。

          背景

          如果你有玩過 ?? 《王者榮耀》《陰陽師》 等手游,一定注意到過它的啟動動畫、皮膚立繪卡片等場景,經(jīng)常采用靜態(tài)底圖加局部液態(tài)流動效果的簡單動畫,這些流動動畫可能出現(xiàn)在緩緩流動的水流 ??、迎風飄動的旗幟 ??、游戲角色衣袖 ??♀?、隨著時間緩動的云、雨、霧天氣效果 ? 等。這種過渡效果不僅節(jié)省了開發(fā)全量動畫的成本,而且使得游戲畫面更加熱血、冒險、奧德賽、高級,也更加容易吸引玩家氪金 ??

          本文使用前端開發(fā)技術(shù),結(jié)合 SVGCSS 來實現(xiàn)類似的液化流動效果。本文包含的知識點主要包括:mask-image 遮罩、feTurbulencefeDisplacementMap 濾鏡、filter 屬性、canvas 繪制方法、TimelineMax 動畫以及input[type=file] 本地圖片資源加載等。

          效果

          先來看看實現(xiàn)效果,下面幾個示例以及 ?? 文章 Banner 圖都是應(yīng)用了由本文內(nèi)容生成的液態(tài)流動動畫效果。由于GIF 圖壓縮比較嚴重,動畫效果看起來不是很流暢 ??,大家不妨通過以下演示頁面鏈接,親自體驗一下效果,生成自己的 傳說典藏 皮膚立繪吧 ??

          ???? 在線體驗:dragonir.github.io/paint-heat-…[1]

          ?? 霧氣擴散 塞爾達傳說:曠野之息

          88503240ec359fdcbdf644bde852ba5f.webp

          ?? 衣袖飄動 貂蟬:貓影幻舞

          f79804e2cd4370a6b872a4cebef82ac3.webp

          ?? 湖光波動

          be2cd7d94c4963cef98d131cce20be19.webp

          ?? 文字液化

          e8a40411e8c3dabe7804f470f2058547.webp

          ?? ps:體驗頁面部署在 Gitpage 上傳圖片功能不是真正上傳到服務(wù)器,而是只會加載到瀏覽器本地,頁面不會獲取任何信息,大家可以放心體驗,不用擔心隱私泄漏問題。

          實現(xiàn)

          頁面主要由 2 部分構(gòu)成,頂部用于加載圖片 ,并且可以通過按住 ?? 鼠標劃動的方式繪制熱點路徑,給圖片添加流動效果;底部是控制區(qū)域,點擊按鈕 ?? 清除畫布,可以清除繪制的流動動畫效果、點擊按鈕 ?? 切換圖片可以加載本地的圖片。

          42f347fb73496d417477c7d8fb002034.webp

          ?? 注意,還有一個隱形的功能,當你繪制完成時,可以點擊 ?? 鼠標右鍵,然后選擇保存圖片,保存的這張圖片就是我們繪制流體動畫路徑的熱點圖,利用這張熱點圖,使用本文的 CSS 知識,就能把靜態(tài)圖片轉(zhuǎn)化成動態(tài)圖啦!

          HTML 頁面結(jié)構(gòu)

          #sketch 元素主要是用于繪制和加載流動效果熱點圖的畫板;#button_container 是頁面底部的按鈕控制區(qū)域;svg 元素用于利用其 filter 濾鏡實現(xiàn)液態(tài)流動動畫效果,包括 feTurbulencefeDisplacementMap 濾鏡。

                
                <main?id="sketch">
          ??<canvas?id="canvas"?data-img=""></canvas>
          ??<div?class="mask">
          ????<div?id="maskInner"?class="mask-inner"></div>
          ??</div>
          </main>
          <section?class="button_container">
          ??<button?class="button">清除畫布</button>
          ??<button?class="button"><input?class="input"?type="file"?id="upload">上傳圖片</button>
          </section>
          <svg>
          ??<filter?id="heat"?filterUnits="objectBoundingBox"?x="0"?y="0"?width="100%"?height="100%">
          ????<feTurbulence?id="heatturb"?type="fractalNoise"?numOctaves="1"?seed="2"?/>
          ????<feDisplacementMap?xChannelSelector="G"?yChannelSelector="B"?scale="22"?in="SourceGraphic"?/>
          ??</filter>
          </svg>
          復制代碼

          ?? feTurbulence 和 feDisplacementMap

          • feTurbulence:濾鏡利用 Perlin 噪聲函數(shù)創(chuàng)建了一個圖像,利用它可以實現(xiàn)人造紋理比如說云紋、大理石紋等模擬濾鏡效果。
          • feDisplacementMap:映射置換濾鏡,該濾鏡用來自圖像中從 in2 到空間的像素值置換圖像從 in 到空間的像素值。即它可以改變元素和圖形的像素位置,通過遍歷原圖形的所有像素點,feDisplacementMap 重新映射替換一個新的位置,形成一個新的圖形。該濾鏡在業(yè)界的主流應(yīng)用是對圖形進行形變,扭曲,液化。

          CSS 樣式

          接著看看樣式的實現(xiàn),main 元素作為主容器并將主圖案作為背景圖片;canvas 作為畫布占據(jù) 100% 的空間位置;.mask.mask-inner 用于生成如下圖所示熱點路徑與背景圖相溶的效果,這種效果是借助 mask-image 實現(xiàn)的。最后,為了生成動態(tài)流動效果,.mask-inner 通過 filter: url(#heat) 將前面生成的 svg 作為濾鏡來源,后續(xù)即將在 JavaScript 中通過不間斷修改 svg 濾鏡的屬性,來生成液態(tài)流動動畫。

                
                main?{
          ??position:?relative;
          ??background-image:?url("bg.jpg");
          ??background-size:?cover;
          ??background-position:?100%?50%;
          }
          canvas?{
          ??opacity:?0;
          ??position:?absolute;
          ??top:?0;
          ??left:?0;
          ??width:?100%;
          ??height:?100%;
          }
          .mask?{
          ??display:?none;
          ??position:?absolute;
          ??top:?0;
          ??left:?0;
          ??width:?100%;
          ??height:?100%;
          ??mask-mode:?luminance;
          ??mask-size:?100%?100%;
          ??backdrop-filter:?hard-light;
          ??mask-image:?url("mask.png");
          }
          .mask-inner?{
          ??position:?absolute;
          ??top:?0;
          ??left:?0;
          ??width:?100%;
          ??height:?100%;
          ??background:?url("bg.jpg")?0%?0%?repeat;
          ??background-size:?cover;
          ??background-position:?100%?50%;
          ??filter:?url(#heat);
          ??mask-image:?url("mask.png")
          }
          復制代碼
          905b1d3ac14115efc7b6a5212104ed2e.webp

          ?? mask-image

          mask-image CSS 屬性用于設(shè)置元素上遮罩層的圖像。

          語法

                
                //?默認值,透明的黑色圖像層,也就是沒有遮罩層。
          mask-image:?none;
          //?<mask-source><mask>或CSS圖像的url的值
          mask-image:?url(masks.svg#mask1);
          //?<image>?圖片作為遮罩層
          mask-image:?linear-gradient(rgba(0,?0,?0,?1.0),?transparent);
          mask-image:?image(url(mask.png),?skyblue);
          //?多個值
          mask-image:?image(url(mask.png),?skyblue),?linear-gradient(rgba(0,?0,?0,?1.0),?transparent);
          //?全局值
          mask-image:?inherit;
          mask-image:?initial;
          mask-image:?unset;
          復制代碼

          兼容性

          41f04c460cb40bf51665c5b96e9ae078.webp

          ? 此功能某些瀏覽器尚在開發(fā)中,需要使用瀏覽器前綴以兼容不同瀏覽器。

          JavaScript 方法

          ① 繪制熱點圖

          監(jiān)聽鼠標移動和點擊事件,在 canvas 上繪制波動路徑熱點。

                
                var?canvas?=?document.getElementById('canvas');
          var?ctx?=?canvas.getContext('2d');
          var?sketch?=?document.getElementById('sketch');
          var?sketchStyle?=?window.getComputedStyle(sketch);
          var?mouse?=?{?x:?0,?y:?0?};

          canvas.width?=?parseInt(sketchStyle.getPropertyValue('width'));
          canvas.height?=?parseInt(sketchStyle.getPropertyValue('height'));
          canvas.addEventListener('mousemove',?e?=>?{
          ??mouse.x?=?e.pageX?-?canvas.getBoundingClientRect().left;
          ??mouse.y?=?e.pageY?-?canvas.getBoundingClientRect().top;
          },?false);

          ctx.lineWidth?=?40;
          ctx.lineJoin?=?'round';
          ctx.lineCap?=?'round';
          ctx.strokeStyle?=?'black';

          canvas.addEventListener('mousedown',?()?=>?{
          ??ctx.beginPath();
          ??ctx.moveTo(mouse.x,?mouse.y);
          ??canvas.addEventListener('mousemove',?onPaint,?false);
          },?false);

          canvas.addEventListener('mouseup',?()?=>?{
          ??canvas.removeEventListener('mousemove',?onPaint,?false);
          },?false);

          var?onPaint?=?()?=>?{
          ??ctx.lineTo(mouse.x,?mouse.y);
          ??ctx.stroke();
          ??var?url?=?canvas.toDataURL();
          ??document.querySelectorAll('div').forEach(item?=>?{
          ????item.style.cssText?+=?`
          ??????display:?initial;
          ??????-webkit-mask-image:?url(${url});
          ??????mask-image:?url(${url});
          ????`;
          ??});
          };
          復制代碼

          繪制完成后,可以在頁面中右鍵保存生成的波動路徑熱點圖,直接將繪制滿意的熱點圖放到 CSS 中,就能給喜歡的圖片添加局部波動效果了,下面這張圖片就是本示例頁面使用的波動的熱點路徑圖。

          1d8e1cf7465a474223298edccced45ba.webp

          ② 生成動畫

          為了生成實時更新的波動效果,本文使用了 TweenMax 來通過改變 feTurbulencebaseFrequency 屬性值來實現(xiàn),使用其他動畫庫或使用 requestAnimationFrame 也是可以實現(xiàn)相同的功能。

                
                feTurb?=?document.querySelector('#heatturb');
          var?timeline?=?new?TimelineMax({
          ??repeat:?-1,
          ??yoyo:?true
          }),
          timeline.add(
          ??new?TweenMax.to(feTurb,?8,?{
          ????onUpdate:?()?=>?{
          ??????var?bfX?=?this.progress()?*?0.01?+?0.025,
          ????????bfY?=?this.progress()?*?0.003?+?0.01,
          ????????bfStr?=?bfX.toString()?+?'?'?+?bfY.toString();
          ??????feTurb.setAttribute('baseFrequency',?bfStr);
          ????}
          ??}),
          0);
          復制代碼

          ③ 清除畫布

          點擊清除畫布按鈕,可以清空已經(jīng)繪制的波動路徑,主要是通過清除頁面元素 mask-image 的屬性值以及清 canvas 畫布來實現(xiàn)的。

                
                function?clear()?{
          ??document.querySelectorAll('div').forEach(item?=>?{
          ????item.style.cssText?+=?`
          ??????display:?none;
          ??????-webkit-mask-image:?none;
          ??????mask-image:?none;
          ????`;
          ??});
          }

          document.querySelectorAll('.button').forEach(item?=>?{
          ??item.addEventListener('click',?()?=>?{
          ????ctx.clearRect(0,?0,?canvas.width,?canvas.height);
          ????clear();
          ??})
          });
          復制代碼

          ④ 切換圖片

          點擊切換圖片,可以加載本地的一張圖片作為繪制底圖,該功能是通過 input[type=file] 來實現(xiàn)圖片資源的獲取,然后通過修改 CSS 將它設(shè)置成新的畫布背景。

                
                document.getElementById('upload').onchange?=?function?()?{
          ??var?imageFile?=?this.files[0];
          ??var?newImg?=?window.URL.createObjectURL(imageFile);
          ??clear();
          ??document.getElementById('sketch').style.cssText?+=?`
          ????background:?url(${newImg});
          ????background-size:?cover;
          ????background-position:?center;
          ??`;
          ??document.getElementById('maskInner').style.cssText?+=?`
          ????background:?url(${newImg});
          ????background-size:?cover;
          ????background-position:?center;
          ??`;
          };
          復制代碼

          到這里,全部功能都實現(xiàn)完畢了,大家趕快制作一張自己喜歡的 史詩皮膚奧德賽小游戲 的啟動頁面吧 ??

          e81c8cfa1bac06ec80b0529f40f4e3a7.webp

          ?? 源碼地址:github.com/dragonir/pa…[2]

          總結(jié)

          本文包含的新知識點主要包括:

          • mask-image 遮罩元素
          • feTurbulencefeDisplacementMap svg濾鏡
          • filter 屬性
          • Canvas 繪制方法
          • TimelineMax 動畫
          • input[type=file] 本地圖片資源加載

          參考資料

          [1]

          https://dragonir.github.io/paint-heat-map/: https://link.juejin.cn/?target=https%3A%2F%2Fdragonir.github.io%2Fpaint-heat-map%2F

          [2]

          https://github.com/dragonir/paint-heat-map: https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fdragonir%2Fpaint-heat-map

              Node 社群
                    


          我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學習感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學習、共建。下方加 考拉 好友回復「Node」即可。



          如果你覺得這篇內(nèi)容對你有幫助,我想請你幫我2個小忙:

          1. 點個 「在看」 ,讓更多人也能看到這篇文章 2. 訂閱官方博客? www.inode.club? 讓我們一起成長

          點贊和在看就是最大的支持 ??

          瀏覽 101
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  男女www | 额去撸在线 | 青娱乐最新官网 | 精品无码一区二区三区天香 | 91传媒在线观看网站 |