摘要:難度系數(shù)普通關(guān)鍵詞前言看到網(wǎng)站做的很炫,想要借鑒,發(fā)現(xiàn)主要是用的實(shí)現(xiàn)的,兼容不好,因此想著用實(shí)現(xiàn)下。實(shí)現(xiàn)思路根據(jù)參考網(wǎng)站的代碼,動(dòng)物圖案是用實(shí)現(xiàn)的,第一時(shí)間想到了的另外對(duì)于轉(zhuǎn)場(chǎng)動(dòng)畫,過渡動(dòng)畫,找個(gè)自己熟悉的動(dòng)畫庫(kù)實(shí)現(xiàn)就行了。
難度系數(shù):普通前言關(guān)鍵詞:GSAP SVG
看到species網(wǎng)站做的很炫,想要借鑒,發(fā)現(xiàn)主要是用css3的clip-path實(shí)現(xiàn)的,兼容不好,因此想著用js實(shí)現(xiàn)下。下面作簡(jiǎn)單介紹,需要詳細(xì)代碼見github庫(kù)。
基礎(chǔ)知識(shí)SVG基本知識(shí),重點(diǎn)viewBox,polygon;
GSAP動(dòng)畫平臺(tái),重點(diǎn)TimelineMax,TweenMax;
parcel構(gòu)建工具的基本使用,parcel。
實(shí)現(xiàn)思路根據(jù)參考網(wǎng)站的代碼,動(dòng)物圖案是用clip-path: polygon()實(shí)現(xiàn)的,第一時(shí)間想到了SVG的polygon;另外對(duì)于轉(zhuǎn)場(chǎng)動(dòng)畫,過渡動(dòng)畫,找個(gè)自己熟悉的動(dòng)畫庫(kù)實(shí)現(xiàn)就行了。需要特別說明的是:
css的clip-path用的用的百分比數(shù)值,svg的polygon的points值不能用百分比數(shù)值,知道viewBox概念的應(yīng)該清楚,其實(shí)points的值也不是一般認(rèn)為的絕對(duì)像素值,因此寫了個(gè)工具函數(shù)parsePolygonStr。
因?yàn)閳D案是分動(dòng)物和場(chǎng)景(樹枝,石頭等)兩部分,并且希望先繪制動(dòng)物再繪制場(chǎng)景,因此HTML部分用g標(biāo)簽分成extra和anis。
主要的代碼如下: 入口文件HTML主要js腳本species
// 導(dǎo)入一個(gè) SCSS module import "../css/main.scss"; import { data, preData } from "./data" import { TweenMax, TweenLite, TimelineMax } from "gsap" // NodeList轉(zhuǎn)換Array function NodeList2Array(nodelist) { let arr = []; if (nodelist.length) { arr = Array.prototype.slice.call(nodelist, 0); } return arr; } // 把"clip-path"值轉(zhuǎn)成svg polygon可用的值 function parsePolygonStr(polygonStr, width, height) { let pointsArr = polygonStr.split(/s+|,s/); let newPointArr = pointsArr.map(function(currentVal, index, arr) { if (index % 2 === 0) { return (parseFloat(currentVal) * width / 100).toFixed(2); } else { return (parseFloat(currentVal) * height / 100).toFixed(2); } }); return newPointArr; } let body = document.querySelector("body"), wrap = document.querySelector("#wrap"), name = wrap.querySelector(".name"), desc = wrap.querySelector(".desc"), stage = wrap.querySelector(".stage"), anis = document.querySelector("#anis"), extra = document.querySelector("#extra"), goBtn = document.querySelector("#go_btn"), anisPolygons = null, extraPolygons = null; let currentSpeciesIndex = 0, width = 1000, height = 700; function init() { let initSpecies = preData.preload; name.innerHTML = initSpecies.name; desc.innerHTML = initSpecies.desc; body.style.background = initSpecies.background; let polygonArr = initSpecies.polygon; if (Object.prototype.toString.call(polygonArr) === "[object Array]") { let polygonHtml = ""; polygonArr.forEach(function(element, index) { let pointsVal = parsePolygonStr(element[0], width, height); polygonHtml += ""; }); anis.innerHTML = polygonHtml; } } init(); anisPolygons = anis.querySelectorAll("polygon"); extraPolygons = extra.querySelectorAll("polygon"); let tl = new TimelineMax({ delay: 0.2 }); // 初始的loading動(dòng)畫 NodeList2Array(anisPolygons).forEach(function(target, index) { let tm = TweenMax.fromTo(target, 0.9, { attr: { fill: "rgba(0, 0, 0, .7)" } }, { attr: { fill: "rgba(200, 20, 20, .45)" }, ease: Power0.easeNone, repeat: -1, yoyo: true }); tl.add(tm, 0.9 - 0.03 * index); }) // 模擬加載完成 setTimeout(function() { // 清除tl tl.clear(); // loading完之后的一系列動(dòng)畫 // 1,變色,放大,爆炸碎片 tl.add( [ TweenMax.to("#anis polygon", .6, { attr: { fill: function(index) { let fillVal = "#111"; if (index % 5 === 0) { fillVal = "#28282a"; } else if (index % 5 === 1) { fillVal = "#111"; } else if (index % 5 === 2) { fillVal = "#333"; } else if (index % 5 === 3) { fillVal = "#222"; } else if (index % 5 === 4) { fillVal = "#121212"; } return fillVal; } } }), TweenMax.to("#wrap .stage", .6, { scale: 1, ease: Back.easeOut.config(1.7) }), TweenMax.to("#anis polygon", .6, { attr: { points: function(index, target) { let nextSpeciesPolygon = preData.ready.polygon; // debugger return parsePolygonStr(nextSpeciesPolygon[index][0], width, height) }, fill: function(index, target) { let nextSpeciesPolygon = preData.ready.polygon; return nextSpeciesPolygon[index][1]; }, } // ease: Power2.easeInOut, }) ] ) // 2,海豚 .add( TweenLite.to("#anis polygon", .6, { attr: { points: function(index, target) { let nextSpeciesPolygon = preData.preAni.polygon; return parsePolygonStr(nextSpeciesPolygon[index][0], width, height) }, fill: function(index, target) { let nextSpeciesPolygon = preData.preAni.polygon; return nextSpeciesPolygon[index][1]; }, }, // ease: Power2.easeInOut, }) ) // 3,爆炸碎片 .add( TweenMax.to("#anis polygon", .6, { attr: { points: function(index, target) { let nextSpeciesPolygon = preData.ready.polygon; // debugger return parsePolygonStr(nextSpeciesPolygon[index][0], width, height) }, fill: function(index, target) { let nextSpeciesPolygon = preData.ready.polygon; return nextSpeciesPolygon[index][1]; }, } }), "+=0.4" ) // 4,“piece”logo .add( TweenMax.to("#anis polygon", .6, { attr: { points: function(index, target) { let nextSpeciesPolygon = preData.title.polygon; // debugger return parsePolygonStr(nextSpeciesPolygon[index][0], width, height) }, fill: function(index, target) { let nextSpeciesPolygon = preData.title.polygon; return nextSpeciesPolygon[index][1]; }, } }), "+=0.4" ); }, 3000); // 動(dòng)物圖案切換 function playHandler() { let nextSpecies = data[currentSpeciesIndex++]; if (!nextSpecies) { return false; } name.innerHTML = nextSpecies.name; desc.innerHTML = nextSpecies.desc; body.style.background = nextSpecies.background; let nextSpeciesPolygon = nextSpecies.polygon; let subTl = new TimelineMax({ pause: true }); let arr1 = NodeList2Array(anisPolygons); let arr2 = NodeList2Array(extraPolygons); // 之所以沒用TweenMax.staggerTo是因?yàn)閷傩詫?duì)象中沒法用獲得index,如下實(shí)現(xiàn)不了 // attr: { // points: pointVal.join(" "), // fill: function(index){return nextSpeciesPolygon[index][1];} // } arr1.concat(arr2).forEach(function(target, index) { let pointVal = parsePolygonStr(nextSpeciesPolygon[index][0], width, height), fillVal = nextSpeciesPolygon[index][1]; subTl.add( TweenMax.to(target, 0.5, { attr: { points: pointVal.join(" "), fill: fillVal }, ease: Back.easeOut.config(1.7) }), "-=0.47" ) }); subTl.play(); } goBtn.addEventListener("click", playHandler, false); export default () => { };
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94346.html
摘要:非常的龐大,而且它是完全為設(shè)計(jì)而生的動(dòng)效庫(kù)。它運(yùn)行于純粹的之上,是目前最強(qiáng)健的動(dòng)畫資源庫(kù)之一??赡苁莿?chuàng)建滾動(dòng)特效最好用的工具,它支持大量的瀏覽器,只要它們支持和特性。可以通過安裝吊炸天了,接近現(xiàn)實(shí)生活中的物理運(yùn)動(dòng)碰撞慣性動(dòng)畫庫(kù)。 收集日期為2019-02-28,★代表當(dāng)時(shí)的該項(xiàng)目在github的star數(shù)量 Animate.css 56401 ★ 一個(gè)跨瀏覽器的動(dòng)效基礎(chǔ)庫(kù),是許多基礎(chǔ)動(dòng)...
摘要:可以繪制動(dòng)態(tài)效果,除了常用的規(guī)則動(dòng)畫之外,還可以采用粒子的概念來實(shí)現(xiàn)較復(fù)雜的動(dòng)效,本文分別采用普通動(dòng)效與粒子特效實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的時(shí)鐘。普通時(shí)鐘普通動(dòng)效即利用的,實(shí)現(xiàn)有規(guī)則的圖案動(dòng)畫。表示保存當(dāng)前環(huán)境的狀態(tài),在此基礎(chǔ)上進(jìn)行繪制。 canvas用于在網(wǎng)頁(yè)上繪制圖像、動(dòng)畫,可以將其理解為畫布,在這個(gè)畫布上構(gòu)建想要的效果。 canvas可以繪制動(dòng)態(tài)效果,除了常用的規(guī)則動(dòng)畫之外,還可以采用粒子的...
摘要:如何用獲取虛擬鍵盤高度前端早讀課月號(hào)早讀文章由湯谷投稿分享。大殺器和把動(dòng)畫轉(zhuǎn)換成原生動(dòng)畫初來乍到,本文搬運(yùn)自我月份在知乎發(fā)的文章。 前端面試之 CSS3 新特性 除了 HTML5 的新特性,CSS3 的新特性也是面試中經(jīng)常被問到的。 如何用 js 獲取虛擬鍵盤高度?-前端早讀課 9月7號(hào)早讀文章由@湯谷投稿分享。正文從這開始~ 這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題...
閱讀 7670·2023-04-25 14:36
閱讀 1763·2021-11-22 09:34
閱讀 2155·2019-08-30 15:55
閱讀 3150·2019-08-30 11:19
閱讀 1311·2019-08-29 15:17
閱讀 553·2019-08-29 12:47
閱讀 2997·2019-08-26 13:38
閱讀 2630·2019-08-26 11:00