当前位置: 首页 > Web前端 > JavaScript

使用PIXI+GSAP模仿vanmoof刹车动力学-猿创影

时间:2023-03-26 20:20:43 JavaScript

前言事情是这样的,我上个月入职了。客户让我们模仿一个国外的网站https://www.vanmoof.com/en-NL...(需要科学上网),给他们做几个展示动画。真的很酷!本项目共有6个动画效果。客户给的工期是15天,我们实际花在写代码上的工期是一周左右。打赏是2W,可能有的同学觉得自己赚的不多……不多,打工赚钱只是一方面。更重要的是,在这个项目中,我带了很多同学去实践,获得了宝贵的项目经验。而这种动效开发,对于很多只会用vue和react写页面的前端同学来说,是很少能接触到的。想外包私活的朋友一起加v:dashuilaoyuan最终效果先看最终效果还是很接近的。接下来一步步教大家如何编写和准备基础环境https://github.com/ezshine/YC...我也给大家准备了一个空白工程,大家可以clone这个仓库来实现步骤循序渐进。空白项目非常简单。介绍两个库,一个叫PIXI,是一个性能优秀的webGL2d渲染引擎。另一个GSAP是一个非常优秀的前端动画引擎。这个库很老了,我还在做FLASH的时候就一直在用。然后在VSCode中安装实时预览插件。一定要注意是微软官方出品的,不要安装盗版。本教程视频版https://www.bilibili.com/video...创建PIXI应用classBrakeBanner{constructor(selector){//初始化PIXI应用,设置舞台为1920x1080this.app=newPIXI.Application({width:window.innerWidth,height:window.innerHeight,backgroundColor:0xffffff,resizeTo:window});document.querySelector(selector).appendChild(this.app.view);this.stage=newPIXI.Container();这个.app.stage.addChild(this.stage);}}加载图片资源//创建资源加载器this.loader=newPIXI.Loader();//添加资源键,资源加载器的路径this.loader.add('btn.png','images/btn.png');this.loader.add('btn_circle.png','images/btn_circle.png');this.loader.add('brake_bike.png','images/brake_bike.png');this.loader.add('brake_handlerbar.png','images/brake_handlerbar.png');this.loader.add('brake_lever.png','images/brake_lever.png');this.loader.load();this.loader.onComplete.add(()=>{this.show();});this.loader.resources[key];通过图片创建精灵元素constbtnImage=newPIXI.Sprite(this.loader.resources['btn.png'].texture);btnContainer.addChild(btnImage);constbtnCircleImage=newPIXI.Sprite(this.loader.resources['btn_circle.png'].texture);btnContainer.addChild(btnCircleImage);变换枢轴点集btnImage.pivot.x=btnImage.pivot.y=btnImage.width/2;btnCircleImage.pivot.x=btnCircleImage.pivot.y=btnCircleImage.width/2;btnContainer.x=200;btnContainer.y=200;初尝运动GSAPbtnCircleImage.scale.x=btnCircleImage.scale.y=.8;gsap.to(btnCircleImage,{duration:1,alpha:0,repeat:-1})gsap.to(btnCircleImage.scale,{duration:1,x:1.1,y:1.1,repeat:-1})整合将按钮相关的代码放入createActionButton函数框架和刹车手柄constbikeContainer=newPIXI.Container();this.stage.addChild(bikeContainer);//整体缩放bikeContainer.scale.x=bikeContainer.scale.y=.3;constbikeImage=newPIXI.Sprite(this.loader.resources['brake_bike.png'].texture);bikeContainer。addChild(bikeImage);constbikeHandlerImage=newPIXI.Sprite(this.loader.resources['brake_handlerbar.png'].texture);bikeContainer.addChild(bikeHandler图像);handlebarconstbikeLeverImage=newPIXI.Sprite(this.loader.resources['brake_lever.png'].texture);bikeContainer.addChild(bikeLeverImage);bikeLeverImage.x=255+454;bikeLeverImage.y=450+462;bikeLeverImage。pivot.x=454;bikeLeverImage.pivot.y=462;bikeLeverImage.rotation=Math.PI/180*-35;现在我们刹车的旋转角度就可以了添加按钮交互actionBtn.on("mousedown",()=>{bikeLeverImage.rotation=Math.PI/180*-35;})actionBtn.on("mouseup",()=>{bikeLeverImage.rotation=0;})添加GSAPactionBtn.on("mousedown",()=>{gsap.to(bikeLeverImage,{duration:.6,rotation:Math.PI/180*-35});})actionBtn.on("mouseup",()=>{gsap.to(bikeLeverImage,{duration:.6,rotation:0});})是不是感觉好多了?OK,到这里大家已经对PIXI和GSAP有了一个初步的了解,接下来我们就来实现速度线粒子效果。永远将车身放在画布的右下角letresize=()=>{bikeContainer.x=window.innerWidth-bikeContainer.width;bikeContainer.y=window.innerHeight-bikeContainer.height;}window.addEventListener('resize',resize);调整大小();速度粒子效果怎么做?让我们仔细看看参考案例。首先要有粒子,也就是小点的颜色。小点有几种颜色。回到顶部继续移动。按住鼠标停止。鼠标停止时还有一点回弹效果。松开鼠标继续OK。一个一个创建粒子容器和对象数组。letparticleZoneSize=window.innerWidth;letparticlesContainer=newPIXI.Container();this.stage.addChild(particlesContainer);letparticles=[];for(leti=0;i<10;i++){letgr=newPIXI.Graphics();gr.beginFill(0xff0000);克。画圆(0,0,6);gr.endFill();letparItem={sx:Math.random()*particleZoneSize,sy:Math.random()*particleZoneSize,}gr.x=parItem.sx;克。y=parItem.sy;particlesContainer.addChild(gr);}粒子随机颜色constcolors=[0xf1cf54,0xb5cea8,0xf1cf54,0x818181,0x000000];for(leti=0;i<10;i++){//...gr.beginFill(colors[Math.floor(Math.random()*colors.length)]);//...粒子连续运动到一个角度不断运动,你知道算法吗?gr.x-=cos(角度)*1;gr.y-=sin(角度)*1;上面的方法就不过多解释了,我教大家一个更简单的旋转容器的方法,其实我们只需要控制粒子向下移动也就是,然后将容器旋转一个角度,然后就是移动的方向所有的粒子也会发生变化。particlesContainer.pivot.set(particleZoneSize/2,particleZoneSize/2);particlesContainer.rotation=(35*Math.PI)/180;particlesContainer.x=particleZoneSize/2;particlesContainer.y=particleZoneSize/2;在旋转的时候,我们还需要注意将旋转的中心设置为粒子容器的中心点。好的,现在让我们让粒子通过gsap.ticker.add()移动;为屏幕渲染计时添加一个钩子,即requestAnimationFrame事件。functionloop(){for(leti=0;iinnerWidth)gr.y=0;}}gsap.ticker.add(循环);这个速度显然不够快,我们可以调整每个动作的距离看看效果。感觉有点吧?那么我们也希望速度由慢变快,所以我们定义一个速度变量,让它从0开始递增,直到达到一个固定值。让speed=0;functionloop(){speed+=.5;速度=Math.min(速度,20);for(leti=0;iinnerWidth)gr.y=0;}}感觉舒服多了,但还是不行好吧,现在我来教大家一些魔术师的眼睛观察一个直线运动的球体时,球体会发生什么变化?它会慢慢被拉伸和变薄,对吧?所以我们用代码来模拟这种拉长变细的效果。如果(速度>=20){gr.scale.y=40;gr.scale.x=0.03}OK,那我们写stop,stop的时候,有反弹的效果。有停止就有开始。将之前的代码定义为start函数,loop函数不变。功能开始(){速度=0;gsap.ticker.add(loop);}停止粒子运动函数pause(){//先移除requestAnimationFrame监听gsap.ticker.remove(loop);for(leti=0;i