JavaScript實現爆炸碎片的 圖片切換 效果

說明

和你們分享一個看上去很酷的效果,先來看效果圖吧!javascript

圖片未加載

解釋

實現這個效果的思路就是,一個大的div元素,設置好一個背景,生成必定數量小的div元素,背景設置成一樣的圖片,可是每一個小div元素的 background-position 屬性值不一樣,整齊的覆蓋在大的div元素上,這樣就能拼成一張完整的背景圖,鼠標移入時,讓全部小的div元素移動和變形。
總的來講就是兩步:
一、生成小的div元素,整齊的覆蓋在大的div元素上,像下圖這樣(爲了方便看,把每一個小div元素,分開了些)。css

圖片未加載

二、鼠標移入時,讓全部小div元素動起來,主要是改變小div元素的left、top、opacity、transform屬性的值html

具體實現的代碼也並很少,下面是註釋很詳細的代碼。前端

完整代碼

<!doctype html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style>
        body {
            overflow: hidden;
        }

        #container {
            width: 400px;
            height: 300px;
            margin: 150px auto 0 auto;
            position: relative;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <script type="text/javascript">
        window.onload = burst;
        function burst() {
            // ready 用來避免高頻率的產生動畫效果
            var ready = true;
            // 容器
            var img = document.querySelector('#container');
            // 動畫時間,單位是s
            var S = 1;
            // 每行 R 個 碎片
            var R = 4;
            // 每列 C 個 碎片
            var C = 7;
            // 容器寬度
            var W = parseInt(window.getComputedStyle(img)['width']);
            // 容器高度
            var H = parseInt(window.getComputedStyle(img)['height']);
            // 控制碎片的範圍
            var N = 2;
            // 碎片分散時,整個活動範圍的寬
            var maxW = N * W;
            // 碎片分散時,整個活動範圍的高
            var maxH = N * H;
            // 控制顯示第 now 張圖片
            var now = 0;
            // 保存圖片路徑的數組
            var imgArr = [
                'https://kkkk1000.com/images/ExplosionPictureSwitching/1.jpg',
                'https://kkkk1000.com/images/ExplosionPictureSwitching/2.jpg',
                'https://kkkk1000.com/images/ExplosionPictureSwitching/3.jpg',
            ];
            img.style.background = 'url(' + imgArr[0] + ') no-repeat';
            var next = function () {
                return (now + 1) % imgArr.length;
            }

            img.onmouseover = function () {
                // 若是ready 爲false 不產生動畫效果
                if (!ready) return;
                ready = false;
                // 建立文檔片斷
                var html = document.createDocumentFragment();

                // 修改容器背景圖
                if (now + 1 >= imgArr.length) {
                    img.style.background = 'url(' + imgArr[0] + ') no-repeat';
                } else {
                    img.style.background = 'url(' + imgArr[now + 1] + ') no-repeat';
                }
                // posArr 用來保存每一個碎片的初始位置和結束位置,
                var posArr = [];
                var k = 0;
                
                // 生成必定數量的小div元素,覆蓋在容器上
                for (var i = 0; i < R; i++) {
                    for (var j = 0; j < C; j++) {
                        posArr[k] = {
                            // left 表明碎片初始時的 left 值
                            left: W * j / C,
                            // top 表明碎片初始時的 top 值
                            top: H * i / R,
                            // endLeft 表明動畫結束時的 left 值
                            endLeft: maxW * j / C - (maxW - (maxW - W) / C - W) / 2,
                            // endTop 表明動畫結束時的 top 值
                            endTop: maxH * i / R - (maxH - (maxH - H) / R - H) / 2,
                            // (maxW-(maxW-W)/C-W)/2 和 (maxH-(maxH-H)/R-H)/2 是爲了讓碎片能在容器的周圍散開
                        };

                        // 建立一個div,一個div就是一個碎片
                        var debris = document.createElement("div");
                        // url 用來表示碎片的背景圖的路徑
                        var url = imgArr[now];
                        // 初始時,碎片的樣式
                        debris.style.cssText = `
                            position: absolute;
                            width: ${Math.ceil(W / C)}px;
                            height: ${Math.ceil(H / R)}px;
                            background: url(${url}) -${posArr[k].left}px -${posArr[k].top}px  no-repeat;
                            left: ${posArr[k].left}px;
                            top: ${posArr[k].top}px;
                            opacity:1;
                            transition:${randomNum(0.1, S)}s ease;
                            `;
                        // 把建立的每一個div,添加到文檔片斷中
                        html.appendChild(debris);
                        k++;
                    }
                }
                // 把文檔片斷 加到DOM樹中
                img.appendChild(html);

                // 獲取容器的全部子元素,也就是全部的碎片
                var debrisAll = img.children;
                // 改變每一個碎片樣式,實現動畫效果
                setTimeout(function () {
                    for (var i = 0; i < debrisAll.length; i++) {
                        var l = posArr[i].endLeft;
                        var t = posArr[i].endTop;
                        debrisAll[i].style.cssText += `
                            left : ${l}px;
                            top : ${t}px;
                            opacity :0;
                            transform:perspective(500px) rotateX(${randomNum(-180, 180)}deg) rotateY(${randomNum(-180, 180)}deg) rotateZ(${randomNum(-180, 180)}deg) scale(${randomNum(1.5, 3)});
                        `;
                    }
                    // 動畫效果完成後
                    // 刪除碎片
                    // 把ready 設置爲true,能夠再次產生動畫效果
                    // 改變 now的值,也就是改變當前要顯示的圖片
                    setTimeout(function () {
                        img.innerHTML = '';
                        ready = true;
                        now = next();
                    }, S * 1000);

                }, 100);
            }

            // 產生一個 n - m 之間的隨機數
            function randomNum(n, m) {
                return Math.random() * (m - n) + n;
            }
        }
    </script>
</body>
</html>

總結

這個效果其實和上次實現的一個雪花效果很相似,
簡單說 JavaScript實現雪花飄落效果 都是利用定時器實現的動畫,定時器應該算是這個效果的重點了,該好好理解下。 java

這個效果,代碼中設置的是讓碎片在容器周圍散開,固然你也能夠在代碼中修改 碎片的 endLeft 和 endTop 的值,來改變方向,好比若是改爲這樣segmentfault

endLeft: maxW * j / C - (maxW - W),
endTop: maxH * i / R - (maxH- H),

產生的效果就是向左上方移動數組

圖片未加載

前端簡單說

相關文章
相關標籤/搜索