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

简单的画布翻转效果

时间:2023-03-30 18:23:54 CSS

由于工作需要,需要写一个翻转效果;演示链接右上角需要撕一个无状态的标记,有动画过程。上图是实现的效果图。这种翻转效果的难点在于没有翻转。打开后,dom下的内容就暴露出来了。从实现的角度来看,纯dom+css动画的设计方案并没有很好的解决方案;于是拿起很久以前学的入门级canvas;先说一下实现思路:AnimationSplit:把这个动画分解成两部分,一部分是翻页时出现的黑色三角形区域,另一部分是露出来的橙色显示内容。橙色显示内容区域相对好一些,因为是规则图形,而黑色区域相对比较难;从最基本的canvas使用方法开始:我踩过的坑。必须设置画布的宽度和高度。这不是CSS中的宽度和高度;是写在dom上的属性;因为dom上的宽高是标示画布的分辨率的(个人理解);所以canvas分辨率为100*100,显示大小可以通过css控制;在js中首先要做的就是获取canvas对象,varcanvas=document.querySelector('.myCanvas');//获取domvar对应的canvasctx=canvas.getContext('2d');//这个方法比较基础,就是获取在canvas上绘制2d内容的工具(context)varcw=100;//解析,其实直接从dom中获取可能更好varch=100;//解析,其实直接从dom中获取可能会更好ctx绘图上下文在本教程中起着非常重要的作用;它提供了一个非常强大的api,比如用来画线,填充,写文字等等,这样理解成画笔好像更简洁;这里的效果需要用到的API如下(不详细解释,可以通过w3c查询);ctx.save()//保存上下文状态(如画笔大小、颜色、旋转角度)ctx.restore()//返回上次保存的上下文状态ctx.moveTo(x,y)//上下文移动到特定位置ctx.lineTo(x,y)//上下文移动到表单中的特定位置一行ctx。stroke()//画线动作ctx.quadraticCurveTo()//上下文(画笔)按照贝塞尔曲线移动(简单理解可以是可控曲线)ctx.arc()//画圆ctx.beginPath()//开启新的画笔路径ctx.closePath()//关闭当前画笔路径ctx.createLinearGradient()//创建画布渐变对象ctx.fill()//填充闭合区域ctx.globalCompositeOperation//画笔重叠模式也许是方法列表不够详尽,请原谅。先画出变成黑色的部分,图形分解成以下几个部分(请按上图补):左上角到右下角的半弧╮然后垂直向下的竖线|然后向右有一个半圆╰,然后向右有一个水平线,再向右下方有一个半圆弧╮最后就是把线连到起点,所以第一步是把画笔移到起始位置ctx.moveTo(50,0);然后ctx.quadraticCurveTo(55,5,55,25);//可以理解为从虚线(50,0)到点(55,25),中间会有(55,5))这个点把直线“吸引”成曲线就像a磁铁;那么右下的第一个半弧就完成了。向下只是移动ctx.lineTo(55,40);这个时候我们应该向右画一个半圆,这个时候用贝塞尔曲线画是不合适的,因为从图片上看,完全是一个1/4的圆,所以用apictx。canvas提供的arc(60,40,5,Math.PI,Math.PI/2,true)画圆;上面画圆的代码意思是:(60,40)是圆心,5是半径,从180度逆时针画到90度,180度是圆的水平向左到达点(55,40)圆心,与上一步相连,然后因为屏幕向下为Positive,90度在圆心正下方,所以画出这个半圆,步骤相同水平向右ctx.lineTo(75,45);然后再次使用贝塞尔曲线,按照第一步的思路向右下方画圆弧;ctx.quadraticCurveTo(95,45,100,50);Seer曲线可以理解为从(75,45)到(100,50)的一条线被(95,45)“吸收”成一条曲线,最终连接起点并关闭绘图区域ctx.lineTo(50),0);此时黑色区域的翻页完成,然后在此时填充颜色;vargradient=ctx.createLinearGradient(50,50,75,75);gradient.addColorStop(0,'#ccc');gradient.addColorStop(0.7,'#111');gradient.addColorStop(1,'#000');我们通过上面的代码创建了一个从(50,50)点到(75,75)点的线性渐变,颜色从#ccc到#111到#000;打造高光效果;然后填充:ctx.fillStyle=gradient;ctx.填充();这样翻页效果就完成了一半。至此,我想说说我所学的布面绘画“套路”;对于上面的教程,我们使用了一个词,叫做一步到位。闭包的概念确实存在于canvas中。对于fill方法,填充的区间只有在有空间大小的情况下才有可能,比如我们画的黑色三角形,补充一下我们最后没有把终点和起点连起来,canvas会自动帮忙我们把上次画的位置和起点联系起来,强制描边闭合空间,如果再画几个新的闭合空间会很麻烦,所以canvas提供了如下的api来创建新的闭合路径:ctx.beginPath();//创建一个新路径ctx.closePath();//closedpathsoforus接下来要绘制右上角的橙色区域,绘制黑色区域之前首先要做的就是ctx.beginPath();...那么我们应该ctx.closePath()填充前;也就是说,从beginPath到closePath标志着我们自己一个完整的绘画阶段。然后画出右上角的橙色区域就容易多了:ctx.beginPath();ctx.moveTo(50,0);ctx.lineTo(100,50);ctx.lineTo(100,0);ctx.lineTo(50,0);ctx.closePath();ctx.fillStyle='#ff6600';ctx.填充();这样我们就完成了右上角橙色区域的绘制;在绘制“new”旁边绘制文字,其实就是使用canvas进行简单的文字绘制,代码如下:vardeg=Math.PI/180;ctx.globalCompositeOperation='source-atop';//画布层叠模式ctx.beginPath();ctx.font='14pxArial';//设置字体大小fontctx.textAlign='center';//字体对齐ctx.translate(78,22);//移动画布点ctx.rotate(45*deg);//旋转画布ctx.fillStyle='#fff';//设置文字颜色ctx.fillText('NEW',0,0);//文字绘制动作ctx.closePath();上面的代码,文本相关的API并不难,只是设置而已,需要理解的部分在于translate和rotate,这两个方法中translate的意思是移动画布的点(0,0)到(78,22),然后旋转45度,然后在原点渲染文字,其实就是点(78,22)。这个时候我们对画布的笔刷做了非常大的修改,比如修改了旋转角度,修改了画布点。这个操作可能只有在我们需要画一个倾斜的new的时候才需要,后面可能就不需要了。好吧,画布画笔有一个“状态”,通过ctx.save();可以保存当前画笔状态,通过ctx.restore();可以恢复上次刷机保存的状态。所以个人理解在开发canvas动画的时候,一个好的习惯是在beginPath之前ctx.save();保存画笔状态,closePath后ctx.restore();恢复之前的刷机状态,这样我们的每一个绘图阶段都不会影响笔刷的修改。(个人经验)ctx.globalCompositeOperation='source-atop';//这部分画布堆叠模式代码是指我们绘制的文字new和橙色三角形区域的重叠关系。该方法取值较多,这里不做过多介绍。source-atop值可以保留重叠区域,新绘制的内容会在重叠区域外消失,从而达到newin里面的效果。到这里我们就开发出了转角效果的完全展示状态,那么如何让这个区域动起来呢?这里需要使用h5提供的函数requestAnimationFrame来刷新帧;这种方法可以简单理解为16毫秒的定时器,但神奇的是它可以自动匹配各种环境下都能达到的相对流畅的帧率。其实不是定时器~我们需要在这个循环执行的函数中使用上面提到的绘制内容重复绘制,例如:functiondraw(){drawMethod();//绘制三角形等内容window.requestAnimationFrame(function(){draw();})}functiondrawMethod(){//...}这样我们就可以达到刷框的效果了,所以接下来我们需要做的是在绘制时控制每个值的参数。比如我们以(50,0)为起点,以(100,50)为终点,这样的两个移动点作为绘图标记是的,如果我们存储两个点,每次更新点的位置我们执行drawMethod,然后清空画布,再画一个新的点,就可以达到移动画布的目的;实际效果链接在上面的demo链接中,我定义了一个速度和加速度的关系。比如每次绘制画布后,存储的点坐标都会增加一个速度值,然后速度值也会增加,这样速度对应的概念就是速度,速度增加的值对应的就是加速度。所以它呈现出一种加速运动的状态;以上内容纯属个人理解,如有理解有误欢迎指点,如demo链接失效可私信。