canvas绘制网易云logo

最近在看《HTML5 Canvas核心技术 图形、动画与游戏开发》,顺便做点东西熟悉。
图形分解参考:https://www.ui.cn/detail/282301.html

简单讲下思路,按照上面文章的分解,网易云的logo可以拆分成几个圆,直径分别为:外围最大的圆400px、300px,偏右的中圆290px、190px,中间的小圆170px、70px,尾部的小圆150px、50px。还有一个宽50px*高度240的矩形。

另外头尾需要处理为圆形。

首先我们做一些准备工作。
HTML中我们需要搞一个画布,我懒得算比例,所以之后的编程全部按文章数据来,设置一个540*540的画布。
html:

 

<canvas id='canvas' width='540' height='540'>
      Canvas not supported
</canvas>

 

还有一些js:

     //获取画布
        var canvas=document.getElementById("canvas"),
            context = canvas.getContext("2d");

        var CAN_CENTER={
                x:canvas.width/2,
                y:canvas.height/2
            },//图像中点
            LINEWIDTH=50,//线段粗细
            center={x:0,y:0};//用于之后计算圆心位置    

第一步我们绘制背景:填充一个和画布一样大的矩形。

        //背景
        context.fillStyle="#cc100f";
        context.fillRect(0,0,canvas.width,canvas.height);

 

二、画最大圈的圆弧(如图)

  

canvas的arc按角度算,且默认为顺时针,所以这个圆弧的角度是0~1.35PI。

还需要在起点加上一个半径25的白色小圆,此处需要计算小圆圆心位置。

根据图片式子可以列出小圆圆心位置。填充一个半径为25的圆。 

        //大圆及终点
        context.lineWidth=LINEWIDTH;
        context.fillStyle="#fff";
        context.strokeStyle="#fff";
        context.beginPath();
        context.arc(CAN_CENTER.x,CAN_CENTER.y,175,0,Math.PI*1.35);
        context.stroke();

        center.x=CAN_CENTER.x-(Math.cos(Math.PI*0.35)*175);
        center.y=CAN_CENTER.y-(Math.sin(Math.PI*0.35)*175)
        context.beginPath();
        context.arc(center.x,center.y,25,0,Math.PI*2);
        context.fill();

 

 

三、画中间偏离的圆弧

同样需要计算圆心位置,分析图片两个圆在右侧相切,中圆的圆心x为中点x加上大圆半径减去小圆半径。
因为绘制上半圆,所以我这边设置为逆时针绘制,角度0~PI。 

center.x=CAN_CENTER.x+175-(290-LINEWIDTH)/2;
        center.y=CAN_CENTER.y;
        context.beginPath();
        context.arc(center.x,center.y,(290-LINEWIDTH)/2,0,Math.PI,true);
        context.stroke();

 


四、接下来绘制中心小圆弧,直线和尾部小圆弧。
一起绘制是因为在canvas中,如果添加圆弧子路径时已经有路径,会自动在之前子路径的尾部到新圆弧路径的起点绘制直线,完美省去我们一大堆计算。
中心圆弧圆心计算同偏移圆弧,不多说。
尾部圆弧的圆心在大圆边缘上,计算如图:

x为中心加上sin a,y为中心y减去cos a。

        // //中间小圆、直线、尾巴小圆
        center.x=center.x-50;
        context.beginPath();
        context.arc(center.x,center.y,(190-LINEWIDTH)/2,Math.PI,Math.PI*1.88,true);
        center.x=CAN_CENTER.x+Math.sin(Math.PI/8)*175;
        center.y=CAN_CENTER.y-Math.cos(Math.PI/8)*175;
        context.arc(center.x,center.y,50,Math.PI*0.88,Math.PI*1.75);
        context.stroke();

题外话:1.88、0.88为调整后找到的比较圆滑的值,一开始用2和1代入有点生硬,对比:

  

五、最后在尾部圆弧圆心的基础上计算尾部小圆圆心位置,并填充一个25的圆。

 

全部js代码:

 

       //获取画布
        var canvas=document.getElementById("canvas"),
            context = canvas.getContext("2d");

        var CAN_CENTER={
                x:canvas.width/2,
                y:canvas.height/2
            },//图像中点
            LINEWIDTH=50,//线段粗细
            center={x:0,y:0};//用于之后计算圆心位置

        //背景
        context.fillStyle="#cc100f";
        context.fillRect(0,0,canvas.width,canvas.height);
        //大圆及终点
        context.lineWidth=LINEWIDTH;
        context.fillStyle="#fff";
        context.strokeStyle="#fff";
        context.beginPath();
        context.arc(CAN_CENTER.x,CAN_CENTER.y,175,0,Math.PI*1.35);
        context.stroke();

        center.x=CAN_CENTER.x-(Math.cos(Math.PI*0.35)*175);
        center.y=CAN_CENTER.y-(Math.sin(Math.PI*0.35)*175)
        context.beginPath();
        context.arc(center.x,center.y,25,0,Math.PI*2);
        context.fill();
        //中间偏离圆
        center.x=CAN_CENTER.x+175-(290-LINEWIDTH)/2;
        center.y=CAN_CENTER.y;
        context.beginPath();
        context.arc(center.x,center.y,(290-LINEWIDTH)/2,0,Math.PI,true);
        context.stroke();
        // //中间小圆、直线、尾巴小圆
        center.x=center.x-50;
        context.beginPath();
        context.arc(center.x,center.y,(190-LINEWIDTH)/2,Math.PI,Math.PI*1.88,true);
        center.x=CAN_CENTER.x+Math.sin(Math.PI/8)*175;
        center.y=CAN_CENTER.y-Math.cos(Math.PI/8)*175;
        context.arc(center.x,center.y,50,Math.PI*0.88,Math.PI*1.75);
        context.stroke();
        // //尾巴终点
        context.beginPath();
        center.x=center.x+(Math.cos(Math.PI*0.25)*50);
        center.y=center.y-(Math.sin(Math.PI*0.25)*50);
        context.arc(center.x,center.y,25,0,Math.PI*2);
        context.fill();

 

posted @ 2019-06-12 13:43  落雪无音  阅读(640)  评论(0编辑  收藏  举报