您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“如何使用JS前端技術實現靜態圖片局部流動效果”,內容詳細,步驟清晰,細節處理妥當,希望這篇“如何使用JS前端技術實現靜態圖片局部流動效果”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
頁面主要由 2
部分構成,頂部用于加載圖片 ,并且可以通過按住鼠標劃動的方式繪制熱點路徑,給圖片添加流動效果;底部是控制區域,點擊按鈕 清除畫布,可以清除繪制的流動動畫效果、點擊按鈕 切換圖片可以加載本地的圖片。
注意,還有一個隱形的功能,當你繪制完成時,可以點擊鼠標右鍵,然后選擇保存圖片,保存的這張圖片就是我們繪制流體動畫路徑的熱點圖,利用這張熱點圖,使用本文的 CSS
知識,就能把靜態圖片轉化成動態圖啦!
#sketch
元素主要是用于繪制和加載流動效果熱點圖的畫板;#button_container
是頁面底部的按鈕控制區域;svg
元素用于利用其 filter
濾鏡實現液態流動動畫效果,包括 feTurbulence
和 feDisplacementMap
濾鏡。
<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
:濾鏡利用 Perlin
噪聲函數創建了一個圖像,利用它可以實現人造紋理比如說云紋、大理石紋等模擬濾鏡效果。
feDisplacementMap
:映射置換濾鏡,該濾鏡用來自圖像中從 in2
到空間的像素值置換圖像從 in
到空間的像素值。即它可以改變元素和圖形的像素位置,通過遍歷原圖形的所有像素點,feDisplacementMap
重新映射替換一個新的位置,形成一個新的圖形。該濾鏡在業界的主流應用是對圖形進行形變,扭曲,液化。
接著看看樣式的實現,main
元素作為主容器并將主圖案作為背景圖片;canvas
作為畫布占據 100%
的空間位置;.mask
和 .mask-inner
用于生成如下圖所示熱點路徑與背景圖相溶的效果,這種效果是借助 mask-image
實現的。最后,為了生成動態流動效果,.mask-inner
通過 filter: url(#heat)
將前面生成的 svg
作為濾鏡來源,后續即將在 JavaScript
中通過不間斷修改 svg
濾鏡的屬性,來生成液態流動動畫。
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') }
mask-image
CSS
屬性用于設置元素上遮罩層的圖像。
語法:
// 默認值,透明的黑色圖像層,也就是沒有遮罩層。 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;
兼容性:
?
此功能某些瀏覽器尚在開發中,需要使用瀏覽器前綴以兼容不同瀏覽器。
監聽鼠標移動和點擊事件,在 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
中,就能給喜歡的圖片添加局部波動效果了,下面這張圖片就是本示例頁面使用的波動的熱點路徑圖。
為了生成實時更新的波動效果,本文使用了 TweenMax
來通過改變 feTurbulence
的 baseFrequency
屬性值來實現,使用其他動畫庫或使用 requestAnimationFrame
也是可以實現相同的功能。
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);
點擊清除畫布按鈕,可以清空已經繪制的波動路徑,主要是通過清除頁面元素 mask-image
的屬性值以及清 canvas
畫布來實現的。
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]
來實現圖片資源的獲取,然后通過修改 CSS
將它設置成新的畫布背景。
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; `; };
讀到這里,這篇“如何使用JS前端技術實現靜態圖片局部流動效果”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。