本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫
前言
很早之前就看到國外很多酷炫的網站在實踐"故障藝術", 或者錯位動畫", 感覺非常有意思, 現在APP端的抖音啟動界面有著這種設計的影子, 作為一名用於探索未知的前端工程師, 有必要好好實踐一下這一設計.
正文
接下來筆者將帶大家使用純Css3來實現"故障動畫", 並將這一特效封裝成React/vue組件, 供大家學習和使用. 先來看看實現的效果:
當然在下面的文章中筆者還會介紹其他風格的"故障動畫".
實現原理
該效果的實現依賴於Css3的新特性mix-blend-mode和background-blend-mode.接下來筆者簡單介紹一下:
1. mix-blend-mode
該屬性描述了元素的內容應該與元素的直系父元素的內容和元素的背景如何混合. 具體的屬性值介紹如下:
mix-blend-mode: normal;(正常)mix-blend-mode: multiply(正片疊底)mix-blend-mode: screen;(濾色)mix-blend-mode: overlay;(疊加)mix-blend-mode: darken; (變暗)mix-blend-mode: lighten; (變亮)mix-blend-mode: color-dodge; (顏色減淡)mix-blend-mode: color-burn; (顏色加深)mix-blend-mode: hard-light; (強光)mix-blend-mode: soft-light;(柔光)mix-blend-mode: difference; (差值)mix-blend-mode: exclusion; (排除)mix-blend-mode: hue;(色相)mix-blend-mode: saturation; (飽和度)mix-blend-mode: color; (顏色)mix-blend-mode: luminosity; (亮度)mix-blend-mode: initial;(初始)mix-blend-mode: inherit; (繼承)mix-blend-mode: unset; (復原)
有點類似於PS裡面的圖層疊加模式.另一個css屬性background-blend-mode和mix-blend-mode類似, 主要針對背景的混合模式, 這裡我們主要採用mix-blend-mode來實現我們的故障效果.
2. 動畫結構分析
由上圖我們可以分析出, "故障動畫"包含4個元素: 背景, 前置文字, 後置文字, 故障線. 具體分解如下:
通過以上分析我們大致可以寫出基本的dom結構來了, 有經驗的朋友可能會想到使用偽元素來實現前置/後置文字/故障線, 雖然這種方式可以節省很多dom結構, 但是缺點就是封裝的靈活度會降低, 所以筆者採用如下結構:
<div className="blink-item"><div className="text text-front">趣談前端</div> <div className="text text-back">趣談前端</div></div>複製代碼
這裡故障線我們採用偽元素來實現. 所以在文章開頭的動畫實現就變得很簡單了,我們只需要設置一個畫布背景,然後用內容混合讓文字疊加, 最後設計文字和故障線的動畫即可. 接下來我們看看具體的實現步驟.
實現方案
我們先來實現文字的混合效果, 故障線和畫布背景, css代碼如下:
.blink {// ... background-color: #000; .blink-item { &::after { content: ''; position: absolute; z-index: 3; left: 0; top: 30px; width: 100%; height: 4px; background-color: #000; } .text-front { color: #74fcfd; } .text-back { position: absolute; transform: translate(-5px, -100%); color: #ea3448; mix-blend-mode: lighten; } }}複製代碼
由以上代碼可知我們在後置文字的css樣式中採用了mix-blend-mode並設置成lighten, 當然我們也可以設置成其他模式的值. 我們接下來就來實現故障的文字動畫和故障線動畫, 這塊也很簡單, 我們採用css3的@keyframe動畫即可, 代碼如下:
@keyframes shakeFront {0% { transform: translate(1px, 1px); } 20% { transform: translate(-1px, 0); } 60% { transform: translate(-1px, 0); } 100% { transform: translate(1px, -1px); }}@keyframes shake { 0% { transform: translate(-5px, -100%); } 20% { transform: translate(-3px, -100%); } 60% { transform: translate(1px, calc(-100% - 1px)); } 100% { transform: translate(2px, calc(-100% + 1px)); }}@keyframes lineShake { 0% { top: 10%; } 20% { top: 60%; } 40% { top: 35%; } 60% { top: 2%; } 80% { top: 80%; } 100% { top: 99%; }}複製代碼
shakeFront和shake分別為後置文字和前置文字的動畫, lineShake為故障線的動畫. 最後, 我們只需要藉助css3的animation讓動畫循環播放即可.
封裝成react/vue組件
為了實現故障動畫更大的自由度以及降低工程師的使用成本, 筆者將其封裝成了react組件, vue組件的封裝思路類似, 感興趣的朋友可以自己試試. 這裡我們來拆解故障動畫組件設計的模型:
組件的設計思想往往是設計的複雜性和使用的便捷性的博弈, 為了讓使用者有更大的自由度, 往往會通過增加組件內部複雜度來彌補. 我們先來看看實現後的效果:
為了實現以上這種自定義配置, 我們需要進一步對已有的代碼進行封裝, 比如故障線我們使用偽元素來實現的, 那麼如何保證切換背景色之後能保證偽元素的背景色也響應的變化呢? 這裡筆者採用的是背景繼承, 即:
.blink {.blink-item { background-color: inherit; &::after { // ... background-color: inherit; animation: lineShake .5s infinite; }複製代碼
這樣我們只需要在.blink容器中動態傳入背景顏色, 即可實現我們想要的效果. React組件代碼如下:
import React from 'react'import './index.less'export default function Blink(props) {const { text = '趣談前端', fontSize = '48px', themeColor = '#000', textColor = ['#74fcfd', '#ea3448'] } = props return ( <div className='blink' style={{backgroundColor: themeColor}}> <div className="blink-item" data-text={text} style={{fontSize: fontSize}}> <div className="text text-front" style={{color: textColor[0]}}>{text}</div> <div className="text text-back" style={{color: textColor[1]}}>{text}</div> </div> </div> )}複製代碼
怎麼樣,是不是很簡單呢? 筆者已將組件代碼上傳到github, 大家可以安裝使用或者在其基礎上進一步完善, 比如基於背景圖片的故障動畫等等, 以上css3特性在現代瀏覽器中支持相對穩定, 在做H5開發中可以一試.