🏂抢不到冰墩墩?快用canvas画一个谁也抢不走的冰墩墩吧!

您所在的位置:网站首页 冰墩墩电脑绘画 🏂抢不到冰墩墩?快用canvas画一个谁也抢不走的冰墩墩吧!

🏂抢不到冰墩墩?快用canvas画一个谁也抢不走的冰墩墩吧!

2023-03-28 08:20| 来源: 网络整理| 查看: 265

冬奥会正在如火如荼的进行,从第一天的冰壶到👦短道速滑队惊心动魄的金牌再到前几天看到🏂谷爱凌做出第一个偏轴1620我直接激动地跳起来,今年冬奥看点十足!不得不提的就是今年冬奥的吉祥物冰墩墩也是成了新网红,网络上全是他的身影,前两天开启的购买我也是一个都没抢到…真是要气死了。

image.png

于是我决定自己画一个,作为一个前端人,曾经也是学生会宣传部骨干成员,怎么说也是有点美术功底在的(自我感觉良好)。

本篇文章会通过画冰墩墩的方式帮助大家复习一下canvas基本的使用及相关方法。

实现效果

image.png

绘制步骤 身体

身体部分我们利用canvas的椭圆和canvas填充未闭合路径的特点来绘制。我们需要两个半椭圆来生成如下图所示的形状

image.png

ctx.beginPath() ctx.ellipse(400, 400, 150, 160, 0, 0, Math.PI) ctx.ellipse(400, 310, 160, 150, 0, Math.PI, Math.PI * 2) ctx.fillStyle = '#fff' ctx.fill() ctx.closePath() 复制代码

椭圆方法:ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)

对应参数:起点x.起点y,半径x,半径y,旋转的角度,起始角,结果角,顺时针或逆时针

耳朵

耳朵很简单,这里用一个半圆和一个矩形组成:

image.png

ctx.beginPath() ctx.fillStyle = '#000' ctx.arc(300, 190, 20, Math.PI, Math.PI * 2) ctx.fillRect(280, 190, 40, 40) ctx.arc(500, 190, 20, Math.PI, Math.PI * 2) ctx.fillRect(480, 190, 40, 40) ctx.fill() ctx.closePath() 复制代码

绘圆方法:arc(x,y,r,sAngle,eAngle,counterclockwise)

对应参数:圆心x,圆心y,半径,起始角,结束角,顺时针或逆时针

耳朵要先于身体绘制,这样身体就会将耳朵多余部分覆盖

手与脚

手脚为了做的生动形象,这里使用贝塞尔曲线来构造对应的形状,首先先来简单了解一下canvas中二阶、三阶贝塞尔曲线的生成方式和对应方法。

贝塞尔曲线图片来自www.jianshu.com/p/afccc4642…

quadraticCurveTo(二阶贝塞尔曲线)

quadraticCurveTo(cpx,cpy,x,y)

参数:控制点的x,控制点的y,结束点x,结束点y

16075459-cf42c00869beb95e.gif

bezierCurveTo(三阶贝塞尔曲线)

bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)

参数:控制点1的x,控制点1的y,控制点2的x,控制点2的y,结束点x,结束点y

16075459-c505dd7f784accfa.gif

贝塞尔曲线原理在动图中已经体现的很明显了,控制点能够使两点之间的折线变得圆滑。接下来我们利用它画手脚,每画完一部分记得closePath()关闭当前路径。

// 脚 ctx.beginPath() ctx.moveTo(300, 523) ctx.bezierCurveTo(315, 523, 290, 583, 300, 603) ctx.quadraticCurveTo(325, 613, 370, 603) ctx.quadraticCurveTo(360, 584, 370, 556) ctx.quadraticCurveTo(325, 523, 300, 520) ctx.stroke() ctx.fillStyle = '#000' ctx.fill() ctx.closePath() ctx.beginPath() ctx.moveTo(440, 554) ctx.quadraticCurveTo(445, 575, 438, 600) ctx.quadraticCurveTo(465, 610, 510, 600) ctx.bezierCurveTo(495, 575, 515, 545, 505, 514) ctx.quadraticCurveTo(470, 546, 440, 553) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() // 手 // 左手 ctx.beginPath() ctx.moveTo(250, 400) ctx.quadraticCurveTo(245, 330, 241, 300) ctx.quadraticCurveTo(200, 320, 160, 420) ctx.lineTo(230, 420) ctx.quadraticCurveTo(245, 400, 250, 400) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(195, 420, 35, 0, Math.PI) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() // 右手 ctx.beginPath() ctx.moveTo(559, 300) ctx.quadraticCurveTo(575, 295, 600, 250) ctx.quadraticCurveTo(625, 230, 655, 250) ctx.quadraticCurveTo(680, 330, 550, 400) ctx.quadraticCurveTo(556, 340, 559, 300) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() 复制代码

image.png

爱心及肚肚上的冬奥会logo

爱心我利用掘友已经实现了的代码添加,而logo则利用canvas导入图片的方法实现。logo网上一搜就有。

drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

参数:要使用的图像,裁剪x,裁剪y,图像宽度,图像高度,放置点x,放置点y,使用图像宽度,使用图像高度

// 爱心 let get_arr = function (a, len) { let arr = [] for (let i = 0; i < len; i++) { let step = (i / len) * (Math.PI * 2) //递增的θ let vector = { x: a * (16 * Math.pow(Math.sin(step), 3)) + 625, y: -a * (13 * Math.cos(step) - 5 * Math.cos(2 * step) - 2 * Math.cos(3 * step) - Math.cos(4 * step)) + 275, } arr.push(vector) } return arr } ctx.beginPath() ctx.strokeStyle = 'red' ctx.lineWidth = 1 let len = 50 let arr = get_arr(1, 50) for (let i = 0; i < len; i++) { ctx.lineTo(arr[i].x, arr[i].y) //心形的点一一被描绘出来 } ctx.fillStyle = '#f00' ctx.fill() ctx.closePath() // logo var img = new Image() img.onload = () => { ctx.drawImage(img, 0, 0, 900, 900, 360, 440, 100, 100) } img.src = './logo.jpg' 复制代码

image.png

面部

面部相对就比较简单了,都是规则图形或曲线,新知识点就是canvas的渐变填充方法。

线性渐变:createLinearGradient(x0,y0,x1,y1)

参数:渐变开始点x,渐变开始点y,渐变结束点x,渐变结束点y

径向渐变:createRadialGradient(x0,y0,r0,x1,y1,r1)

参数:渐变开始圆心x,渐变开始圆心y,半径,渐变结束圆心x,渐变结束圆心y,半径

// 彩虹🌈圈 ctx.beginPath() ctx.ellipse(400, 300, 125, 95, -0.06, 0, Math.PI * 2) var grd = ctx.createRadialGradient(400, 300, 95, 400, 300, 130) grd.addColorStop(0, '#dddddd20') grd.addColorStop(1, '#0000FF') ctx.strokeStyle = grd ctx.lineWidth = 6 ctx.stroke() ctx.closePath() ctx.beginPath() ctx.ellipse(400, 300, 130, 95, -0.12, 0, Math.PI * 2) var grd = ctx.createRadialGradient(400, 300, 95, 400, 300, 130) grd.addColorStop(0, '#dddddd20') grd.addColorStop(1, '#00FFFF66') ctx.strokeStyle = grd ctx.lineWidth = 2 ctx.stroke() ctx.closePath() ctx.beginPath() ctx.ellipse(400, 300, 130, 95, 0.06, 0, Math.PI * 2) var grd = ctx.createRadialGradient(400, 300, 95, 400, 300, 130) grd.addColorStop(0, '#dddddd20') grd.addColorStop(1, '#FFFF0066') ctx.strokeStyle = grd ctx.lineWidth = 3 ctx.stroke() ctx.closePath() ctx.beginPath() ctx.ellipse(400, 300, 130, 95, 0, 0, Math.PI * 2) var grd = ctx.createRadialGradient(400, 300, 95, 400, 300, 130) grd.addColorStop(0, '#dddddd20') grd.addColorStop(1, '#00FF0066') ctx.strokeStyle = grd ctx.lineWidth = 3 ctx.stroke() ctx.closePath() ctx.beginPath() ctx.ellipse(400, 300, 130, 95, 0.1, 0, Math.PI * 2) var grd = ctx.createRadialGradient(400, 300, 95, 400, 300, 130) grd.addColorStop(0, '#dddddd20') grd.addColorStop(1, '#8B00FF66') ctx.strokeStyle = grd ctx.lineWidth = 4 ctx.stroke() ctx.closePath() 复制代码

image.png

眼鼻嘴

btw:眼鼻嘴这个标题一写出来我就没忍住开始唱

미안해 미안해 하지마

내가 초라해지잖아

好了收!

// 眼 ctx.beginPath() ctx.ellipse(465, 275, 38, 26, 1, 0, Math.PI * 2) ctx.ellipse(335, 275, 43, 29, -0.8, 0, Math.PI * 2) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(344, 272, 22, 0, Math.PI * 2) ctx.arc(458, 270, 20, 0, Math.PI * 2) ctx.fillStyle = '#fff' ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(344, 272, 17, 0, Math.PI * 2) ctx.arc(458, 270, 15, 0, Math.PI * 2) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(344, 272, 16, 0, Math.PI * 2) var grd = ctx.createRadialGradient(344, 272, 0, 344, 272, 20) grd.addColorStop(0, '#444') grd.addColorStop(1, '#111') ctx.fillStyle = grd ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(458, 270, 14, 0, Math.PI * 2) var grd = ctx.createRadialGradient(458, 270, 0, 458, 270, 20) grd.addColorStop(0, '#444') grd.addColorStop(1, '#111') ctx.fillStyle = grd ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(344, 272, 12, 0, Math.PI * 2) ctx.arc(458, 270, 10, 0, Math.PI * 2) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() ctx.beginPath() ctx.arc(350, 266, 4, 0, Math.PI * 2) ctx.arc(452, 266, 3, 0, Math.PI * 2) ctx.fillStyle = '#fff' ctx.fill() ctx.closePath() // 鼻子 ctx.beginPath() ctx.moveTo(380, 280) ctx.lineTo(420, 280) ctx.lineTo(400, 295) ctx.lineTo(380, 280) ctx.fillStyle = '#000' ctx.fill() ctx.closePath() // 嘴 ctx.beginPath() ctx.moveTo(370, 323) ctx.lineTo(400, 335) ctx.lineTo(430, 323) ctx.quadraticCurveTo(400, 330, 370, 323) ctx.strokeStyle = '#000' ctx.lineWidth = 2 ctx.fillStyle = '#f00' ctx.fill() ctx.stroke() ctx.closePath() 复制代码

image.png

最后

我本来想要给整个冰墩墩描个黑边,画出透明外套的感觉,因为觉得透明外套是冰墩墩的灵魂,但是我一直没找到一个好的方式来绘,如果有大神能够指导或提点一下老弟的话我实在是感激不尽!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3