《前端每日實戰》第177號做品:多張圖片的鼠標懸停和滑動特效

image

一種引發瀏覽者探索興趣的方法是,頁面打開以後並不立刻把全部內容都呈現給用戶,而是隱藏其中的一部份內容,其餘內容則須要用戶交互以後才展現出來。這種方式很合適那些小衆的、要營造藝術氛圍的網站,經過特效來展示後續內容,有一種與用戶對話的感受。本做品就是採用這樣的方式,當頁面加載以後先把圖片遮住,而後當鼠標移動到元素之上時,圖片才展示出來。css

效果預覽

按下右側的「點擊預覽」按鈕能夠在當前頁面預覽,點擊連接能夠全屏預覽。html

https://codepen.io/comehope/pen/MWejLqY前端

源代碼下載

每日前端實戰系列的所有源代碼請從 github 下載:git

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

代碼解讀

1、DOM 結構

容器名爲 .container,其中包含一個名爲 .item 的元素。
.item 元素則包含 3 個子元素,.picture 表示圖片自己,.title 是圖片上的文字,.mask 是用來製做遮罩效果的元素。
做品完成時,會有多個 .item 元素,但此時咱們先只展現 1 張圖片,待效果完成以後,再增長其餘圖片。segmentfault

<div class="container">
    <div class="item">
        <img class="picture" src="images/toggle.png">
        <span class="title">Toggle</span>
        <div class="mask"></div>
    </div>
</div>

本做品用到的4張圖片可從下列地址下載。
https://assets.codepen.io/947...
https://assets.codepen.io/947...
https://assets.codepen.io/947...
https://assets.codepen.io/947...網絡

2、基礎佈局

設置頁面背景色爲深灰色,令容器居中。佈局

body {
    background-color: #222;
    margin: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

設置圖片尺寸,用相對單位 em學習

.item {
    width: 18em;
    height: 12em;
}

.item .picture {
    width: 100%;
}

效果以下圖:
image測試

3、圖片遮罩特效

由於先處理遮罩效果,因此把暫時用不到的文字隱藏起來,避免干擾。

.item .title {
    display: none;
}

利用 .mask 元素爲圖片增長遮罩。遮罩大小是 20em * 20em 的一個大圓,背景色先暫用半透明的醒目的黃色,便於在開發過程當中觀察。

.item {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
}

.item .mask {
    position: absolute;
    width: 20em;
    height: 20em;
    background-color: hsla(60, 100%, 50%, 0.7);
    border-radius: 50%;
}

效果以下圖:
image

上面只是測試了遮罩的大小,把剛纔的代碼註釋掉,改用 box-shadow 實現咱們真正須要的遮罩效果。這個遮罩層尺寸是 50em * 50em,遠遠大於圖片自己,但它的大部分區域是內陰影,在內陰影以內才透出遮罩下方的圖片來。
內陰影的尺寸是 15em,這是內陰影的半徑,因此內陰影的直徑是 30em,用遮罩元素的寬高 50em 減去遮罩的 30em,剩下的就是 20em,和剛纔測試的遮罩大小是同樣的。

.item .mask {
    /*width: 20em;*/
    /*height: 20em;*/
    /*background-color: hsla(60, 100%, 50%, 0.7);*/
    width: 50em;
    height: 50em;
    color: hsla(60, 100%, 50%, 0.7);
    box-shadow: inset 0 0 0 15em;
}

效果以下圖:
image

加上鼠標懸停效果試一下。注意,這裏元素上的內陰影尺寸設置爲 25em,這是內陰影的半徑尺寸,那麼陰影的直徑就是 50em,和遮罩自己的尺寸是同樣大的,這表示在默認狀況下,整張圖片都被內陰影遮住了;而鼠標懸停時,內陰影變小,就顯示出了遮罩下方的圖片。另外爲遮罩層增長了 pointer-events: none 屬性,它的做用是避免遮罩層響應鼠標事件。

.item .mask {
    box-shadow: inset 0 0 0 25em;
    transition: box-shadow 0.3s;
    pointer-events: none;
}

.item:hover .mask {
    box-shadow: inset 0 0 0 15em;
}

再下來製做鼠標滑動時遮罩跟隨的效果。
先把遮罩移到圖片的左上方。遮罩的高是 50emtop: -25em 就是令遮罩的水平中線與圖片頂邊對齊;同理,left: -25em 則是令遮罩的垂直中線與圖片的左邊對齊,二者疊加,就是遮罩的中心與圖片的左上角對齊。

.item .mask {
    top: -25em;
    left: -25em;
}

增長腳本,爲 .item 元素綁定 mousemove 事件,令鼠標在 .item 元素上滑動時,帶動 .mask 元素滑動。

window.onload = init

function init() {
    let items = document.querySelectorAll('.item')
    items.forEach((item) => {
        item.addEventListener('mousemove', e => {
            let mask = item.querySelector('.mask')
            mask.style.transform = 'translate(' + e.offsetX + 'px, ' + e.offsetY + 'px)'
        })
    })
}

至此,主要的效果已經完成了,接下來再加強一下效果。
稍加大圖片的原始尺寸,在鼠標懸停時恢復圖片大小,這樣的效果是在鼠標進入圖片區域時,圖片能「扭曲抖動」一下,增強互動的效果。

.item .picture {
    transform: scale(1.1);
    transition: 0.3s;
}

.item:hover .picture {
    transform: scale(1);
}

鼠標懸停和滑動效果完成,下面這幾行代碼是一些收尾工做。
經過 overflow: hidden 屬性隱藏掉圖片以外的部分、容器加一點圓角、遮罩的顏色改用不透明的灰色。

.container {
    border-radius: 0.3em;
}

.item {
    overflow: hidden;
}

.item .mask {
    /*color: hsla(60, 100%, 50%, 0.7);*/
    color: #333;
}

效果以下圖:
image

4、文字佈局和特效

接下來處理文字。
先把文字顯示出來,除了註釋掉 display: none 以外,還要設置它的 z-index,令它顯示在遮罩層的上方,再有也要取消它的鼠標事件,防止它影響鼠標滑動效果。

.item .title {
    /*display: none;*/
    position: absolute;
    color: #777;
    z-index: 1;
    pointer-events: none;
}

設置文字樣式。

.item .title {
    font-family: sans-serif;
    font-weight: bold;
    text-transform: uppercase;
}

增長文字特效,當鼠標滑入圖片時,隱藏文字。

.item .title {
    transition: 0.2s;
}

.item:hover .title {
    opacity: 0;
}

效果以下圖:
image

至此,單圖圖片的效果都完成了。

5、將特效應用到多張圖片

增長多個 .item 元素。

<div class="container">
    <div class="item">
        <img class="picture" src="images/toggle.png">
        <span class="title">Toggle</span>
        <div class="mask"></div>
    </div>
    <!-- 此處再增長3個 .item 元素,代碼略 -->
</div>

grid 佈局把圖片排列成田字格形狀。

.container {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-gap: 1em;
}

效果以下圖:
image

大功告成!

關於做者

張偶,網絡筆名 @comehope,20世紀末觸網,被 Web 的無窮魅力所俘獲,自此始終戰鬥在 Web 開發第一線。

《前端每日實戰》專欄是我近年來實踐項目式學習的筆記,以項目驅動學習,展示從靈感閃現到代碼實現的完整過程,亦可做爲前端開發的練手習題和開發參考。

拙做《CSS3 藝術》一書已由人民郵電出版社出版,全綵印刷,用100多個生動美觀的實例,系統地剖析了 CSS 與視覺效果相關的重要語法,並含有近10小時的視頻演示講解。京東/天貓/噹噹有售。

相關文章
相關標籤/搜索