時間:2023-05-18 22:36:02 | 來源:網(wǎng)站運營
時間:2023-05-18 22:36:02 來源:網(wǎng)站運營
彈指間,網(wǎng)頁灰飛煙滅——Google滅霸彩蛋實現(xiàn):這是之前在公眾號寫的一篇文章,我覺得蠻有意思,這里再回顧下。
閱讀本文大概需要 12 分鐘。不知道大家有沒有看這段時間最火的一部電影《復(fù)仇者聯(lián)盟4:終局之戰(zhàn)》,作為漫威迷的我還沒看,為什么呢?因為太貴了,剛上映的那周,一張IMAX廳的票價已經(jīng)達到了299的天價,作為搬磚民工是舍不得花這么高的錢來看一場電影的,太奢侈了,當然也可能我是個假漫威迷吧,哈哈哈哈逃~
<div class="box"> <div class="bomb">啪嗒!</div> <ul> <li class="item"> <h3>襟三江而帶五湖,控蠻荊而引甌越。</h3> </li> <li class="item"> <h3>潦水盡而寒潭清,煙光凝而暮山紫。</h3> </li> <li class="item"> <h3>落霞與孤鶩齊飛,秋水共長天一色。</h3> </li> <li class="item"> <img src="./1.jpg" /> </li> </ul></div>
樣式就不貼了,后面會給出源碼。<script src="./html2canvas.js"></script>
接著將元素轉(zhuǎn)化為32個canvas。html2canvas(ele).then(dom => { const { width, height } = dom; // canvas寬高 let ctx = dom.getContext('2d'); // canvas繪圖對象 // 返回一個ImageData對象,用來描述canvas區(qū)域隱含的像素數(shù)據(jù),這個區(qū)域通過矩形表示,起始點為(sx, sy)、寬為sw、高為sh。 let originalFrame = ctx.getImageData(0, 0, width, height); // 創(chuàng)建一個32個新的、空白的、指定大小的 ImageData 對象。 所有的像素在新對象中都是透明的。 let frames = []; for (let i = 0; i < COUNT; i++) { frames[i] = ctx.createImageData(width, height); } // 將canvas所有的數(shù)據(jù)隨機復(fù)制到32個frames上面 for (x = 0; x < width; ++x) { for (y = 0; y < height; ++y) { // frames 的下表索引值。 // 不是一般的(從0到COUNT的)隨機值,而是遞增的隨機數(shù),為了將像素點先集中在前幾個frame,然后再往后集中,否則32個frames鐘的像素太分散。 var frameIndex = Math.floor((COUNT * (Math.random() + (2 * x) / width)) / 3); // imageData.data:描述一個一維數(shù)組,包含以 RGBA 順序的數(shù)據(jù),數(shù)據(jù)使用 0 至 255(包含)的整數(shù)表示。 // 數(shù)組的個數(shù)為 width*height*4,所以除了寬乘高以外還要乘以4 var pixelIndex = 4 * (y * width + x); // 之所以要循環(huán)4次是因為上面乘了4,得到的 pixelIndex 在 width*height*4 范圍內(nèi)會有一些空缺,所以要補上這些空缺,保證所有的canvas像素全部復(fù)制到32個frames上面 for (offset = 0; offset < 4; offset++) { frames[frameIndex].data[pixelIndex + offset] = originalFrame.data[pixelIndex + offset]; } } }});
然后將這32個分布了不同像素點的 ImageData 對象轉(zhuǎn)換成原始li元素大小的dom元素,用一個容器container來容納,然后將容器覆蓋到原始li元素的位置,現(xiàn)在就相當于每個li元素的位置是一個container元素,這個container元素內(nèi)容是32個dom元素,這32個dom重疊起來的樣子和原始li元素是一樣的。// 創(chuàng)建一個div容納frameslet container = document.createElement('div');container.classList.add('container');container.style.width = `${width}px`;container.style.height = `${height}px`;// 將所有包含RGBA數(shù)據(jù)的frames繪制到繪圖中,生成32份和原始dom一樣的元素,只是內(nèi)容不同,最后將這些元素放入container中。let frames2doms = frames.map((frameData, i) => { let domCopy = dom.cloneNode(true); domCopy.getContext('2d').putImageData(frameData, 0, 0); // 將數(shù)據(jù)從已有的 ImageData 對象繪制到位圖的方法。 domCopy.style.transitionDelay = `${(1.35 * i) / frames.length}s`; //過渡效果開始前的delay時間(可自行調(diào)整),使得frames先從下標小的開始運動。 container.appendChild(domCopy); return domCopy;});
現(xiàn)在我們看到的效果和原始的是一樣的,但是所有的li元素被隱藏了起來,顯示的是由許許多多零散的元素拼湊出來的假象。// 讓所有的canvas動起來// 原始dom相對定位,container絕對定位ele.classList.add('disintegrated');ele.appendChild(container);ele.style.border = '0';container.offsetLeft; // 沒有該句,則無法實現(xiàn)動畫效果// 為32份不同內(nèi)容的dom元素添加過渡效果(可自行調(diào)整)frames2doms.map(item => { let random = 2 * Math.PI * (Math.random() - 0.5); item.style.transform = ` rotate(${15 * (Math.random() - 0.5)}deg) translate(${60 * Math.cos(random)}px, ${30 * Math.sin(random)}px) rotate(${-15 * (Math.random() - 0.5)}deg) `; item.style.opacity = 0;});
三、實驗效果關(guān)鍵詞:實現(xiàn)
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。