前端每日實戰 167# 視頻演示如何用 1 個 dom 元素創作兩顆愛心,祝大家 520 節日快樂!

圖片描述

效果預覽

按下右側的“點擊預覽”按鈕可以在當前頁面預覽,點擊鏈接可以全屏預覽。

https://codepen.io/comehope/pen/KLvENb

可交互視頻

此視頻是可以交互的,你可以隨時暫停視頻,編輯視頻中的代碼。

請用 chrome, safari, edge 打開觀看。

https://scrimba.com/p/pEgDAM/cJ8vrMt2

源代碼下載

每日前端實戰系列的全部源代碼請從 github 下載:

https://github.com/comehope/front-end-daily-challenges

代碼解讀

一、繪製一個圓點

定義 dom 結構,只有一個 dom 元素,名爲 .heart

<figure class="heart"></figure>

讓元素居中顯示,設置頁面背景色爲淺粉紅漸變色:

body {
    margin: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(lightpink, white);
}

畫出一個紅色圓點:

.heart {
    font-size: 30px;
    width: 1em;
    height: 1em;
    background-color: red;
    border-radius: 50%;

二、製作一個點陣圖形和它的投影

我們要製作一個點陣圖形,這個手法在第 67 號作品中曾有應用。原理是利用 box-shadow 的特性,如果你已經瞭解了這個手法,可以直接滾屏到下一節,如果還不瞭解,做下面這幾個小實驗就明白了。

.heart 設置下面的陰影,則在紅色圓點的右側會出現一個等大的黑點:

.heart {
    box-shadow:
        1.1em 0;
}

繼續在紅點左側畫一個黑點:

.heart {
    box-shadow:
        1.1em 0,
        -1.1em 0;
}

再繼續,在紅點的下方畫一個黑點:

.heart {
    box-shadow:
        1.1em 0,
        -1.1em 0,
        0 1.1em;
}

再在紅點的上方畫一個黑點:

.heart {
    box-shadow:
        1.1em 0,
        -1.1em 0,
        0 1.1em,
        0 -1.1em;
}

現在你可以看到,4 個黑點組成一個十字形,而紅點在這個十字形交叉點的位置。這個技巧就是把屏幕當作一個以紅點爲原點的平面座標系,水平方向右側爲正,垂直方向下方爲正,與瀏覽器的座標體系一致。每一個陰影屬性值就可以繪製出一個圓點,因爲 box-shadow 可以接收多個屬性性,所以就可以用多個圓點來畫點陣圖了。

爲了讓代碼更直觀,我們可以把代碼的佈局安排得和圖案的形狀一樣,下面 box-shadow 的 4 個屬性值用來畫出一個十字形:

.heart {
    box-shadow: 
                    0 -1.1em,




        -1.1em 0,               1.1em 0,




                    0 1.1em;
}

因爲沒有給陰影指定顏色,所以它默認是黑色,要把它改成紅色,並不需要在 box-shadow 賦值,基於 CSS 的繼承原理,直接給元素指定一個顏色,陰影就採用相同的顏色了:

.heart {
    color: red;
    background-color: currentColor;
}

大紅太豔了,讓它的顏色談一點:

.heart {
    color: hsla(0, 100%, 50%, 0.6);
}

接下來再用一個技巧,用 drop-shadow() 把整個圖案再複製出一份:

.heart {
    filter: drop-shadow(3.3em 2.2em dodgerblue);
}

三、繪製心形圖案

有了上面的知識儲備,繪製心形就只是一個工夫活了,花一點時間在紙上畫一畫,數一數,就可以創作點陣圖形了。這裏用到的心形是 9 * 8 點陣的:

.heart {
    --heart-shape: 
                    -3.3em -3.3em, -2.2em -3.3em,                                          2.2em -3.3em, 3.3em -3.3em,




    -4.4em -2.2em, -3.3em -2.2em, -2.2em -2.2em, -1.1em -2.2em,             1.1em -2.2em, 2.2em -2.2em, 3.3em -2.2em, 4.4em -2.2em,




    -4.4em -1.1em, -3.3em -1.1em, -2.2em -1.1em, -1.1em -1.1em, 0em -1.1em, 1.1em -1.1em, 2.2em -1.1em, 3.3em -1.1em, 4.4em -1.1em,



    
    -4.4em 0em,    -3.3em 0em,    -2.2em 0em,    -1.1em 0em,    0em 0em,    1.1em 0em,    2.2em 0em,    3.3em 0em,    4.4em 0em,



    
                    -3.3em 1.1em,  -2.2em 1.1em,  -1.1em 1.1em,  0em 1.1em,  1.1em 1.1em,  2.2em 1.1em,  3.3em 1.1em,




                                    -2.2em 2.2em,  -1.1em 2.2em,  0em 2.2em,  1.1em 2.2em,  2.2em 2.2em,




                                                    -1.1em 3.3em,  0em 3.3em,  1.1em 3.3em,




                                                                0em 4.4em;
    box-shadow: var(--heart-shape);
}

哈哈,這一大片代碼真是讓人頭暈啊,但是如果是在編輯器裏看,它就是一個心形呢,像下面這樣,這就是傳說中的所見即所得吧:

圖片描述

至此,我們得到了一顆紅心和一顆藍心。

四、設計動畫效果

定義 2 組關鍵幀,分別用於紅心和藍心,紅心的幀效果就是 box-shadow 屬性的代碼,藍心的幀效果則是 drop-shadow() 的代碼:

.heart {
    /* box-shadow: var(--heart-shape); */
    /* color: hsla(0, 100%, 50%, 0.6); */
    /* filter: drop-shadow(3.3em 2.2em dodgerblue); */
}

@keyframes heart-one {
    to {
        box-shadow: var(--heart-shape);
        color: hsla(0, 100%, 50%, 0.6);
    }
}

@keyframes heart-two {
    to {
        filter: drop-shadow(3.3em 2.2em dodgerblue);
    }
}

最後,定義動畫屬性,注意藍心有 0.3s 的延遲:

.heart {
    animation: 
        heart-one 1s infinite alternate cubic-bezier(0.5, 1.7, 0.5, 1.5),
        heart-two 1s 0.3s infinite alternate cubic-bezier(0.5, 1.7, 0.25, 1);
}

大功告成!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章