摘要:难度系数普通关键词前言看到网站做的很炫,想要借鉴,发现主要是用的实现的,兼容不好,因此想着用实现下。实现思路根据参考网站的代码,动物图案是用实现的,第一时间想到了的另外对于转场动画,过渡动画,找个自己熟悉的动画库实现就行了。
难度系数:普通前言关键词:GSAP SVG
看到species网站做的很炫,想要借鉴,发现主要是用css3的clip-path实现的,兼容不好,因此想着用js实现下。下面作简单介绍,需要详细代码见github库。
基础知识SVG基本知识,重点viewBox,polygon;
GSAP动画平台,重点TimelineMax,TweenMax;
parcel构建工具的基本使用,parcel。
实现思路根据参考网站的代码,动物图案是用clip-path: polygon()实现的,第一时间想到了SVG的polygon;另外对于转场动画,过渡动画,找个自己熟悉的动画库实现就行了。需要特别说明的是:
css的clip-path用的用的百分比数值,svg的polygon的points值不能用百分比数值,知道viewBox概念的应该清楚,其实points的值也不是一般认为的绝对像素值,因此写了个工具函数parsePolygonStr。
因为图案是分动物和场景(树枝,石头等)两部分,并且希望先绘制动物再绘制场景,因此HTML部分用g标签分成extra和anis。
主要的代码如下: 入口文件HTML主要js脚本species
// 导入一个 SCSS module import "../css/main.scss"; import { data, preData } from "./data" import { TweenMax, TweenLite, TimelineMax } from "gsap" // NodeList转换Array function NodeList2Array(nodelist) { let arr = []; if (nodelist.length) { arr = Array.prototype.slice.call(nodelist, 0); } return arr; } // 把"clip-path"值转成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动画 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完之后的一系列动画 // 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); // 动物图案切换 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是因为属性对象中没法用获得index,如下实现不了 // 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 () => { };
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94346.html
摘要:非常的庞大,而且它是完全为设计而生的动效库。它运行于纯粹的之上,是目前最强健的动画资源库之一。可能是创建滚动特效最好用的工具,它支持大量的浏览器,只要它们支持和特性。可以通过安装吊炸天了,接近现实生活中的物理运动碰撞惯性动画库。 收集日期为2019-02-28,★代表当时的该项目在github的star数量 Animate.css 56401 ★ 一个跨浏览器的动效基础库,是许多基础动...
摘要:可以绘制动态效果,除了常用的规则动画之外,还可以采用粒子的概念来实现较复杂的动效,本文分别采用普通动效与粒子特效实现了一个简单的时钟。普通时钟普通动效即利用的,实现有规则的图案动画。表示保存当前环境的状态,在此基础上进行绘制。 canvas用于在网页上绘制图像、动画,可以将其理解为画布,在这个画布上构建想要的效果。 canvas可以绘制动态效果,除了常用的规则动画之外,还可以采用粒子的...
阅读 7637·2023-04-25 14:36
阅读 1754·2021-11-22 09:34
阅读 2149·2019-08-30 15:55
阅读 3146·2019-08-30 11:19
阅读 1306·2019-08-29 15:17
阅读 550·2019-08-29 12:47
阅读 2990·2019-08-26 13:38
阅读 2626·2019-08-26 11:00