本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
大家好我是ndz,很高兴也很荣幸成为了一名稀土掘金技术社区签约作者,在这里真的很感谢平台给予的肯定和各位读者的支持,感谢 🙏 🙏 🙏。
本文为稀土掘金技术社区签约作者专栏 - 《从Canvas到PixiJs》 的第二篇文章,喜欢的小伙伴记得点赞加关注,以防需要用时回来不迷路 😂
前言
在之前的文章中其实也写过一篇Canvas的基础文章:案例+图解带你一文读懂Canvas🔥🔥(2W+字),但整体比较平铺直叙,并且因为掘金文章对字数的限制删除了很多案例,在本专栏中我会重新归纳总结,尽量让小伙伴们看着就懂、看完就会、学完就能写。人狠话不多直接上干货。
Canvas已悄悄让你不得不学它。
随着很多复杂场景的出现,前端的性能也越发值得大家的关注,尤其近几年随着在线教育、在线直播、可视化编辑、各种小游戏的火爆,前端性能的关注度疯狂的蹭蹭往上飙。
随着性能的不断优化,性能的上限和性价比却又值得大家深思,在一些特殊场景,真实DOM的性能远远比不上Canvas的渲染,毕竟Canvas的推出主打优势就是更快的渲染速度,因此在原有真实DOM渲染的基础上去做性能优化远远不如换一种方案,直接使用Canvas绘制来的实在。在如今已经有不少公司考虑采用Canvas渲染来尽可能的获得性能提升,尤其自从2021年5月11日开始Google官方更新 Google Docs 的呈现文档方式变更时声明:
We’re updating the way Google Docs renders documents. Over the course of the next several months, we’ll be migrating the underlying technical implementation of Docs from the current HTML-based rendering approach to a canvas-based approach to improve performance and improve consistency in how content appears across different platforms. 译文:我们正在更新Google文档渲染文档的方式。在接下来的几个月中,我们将迁移文档的基本技术实施,从当前基于HTML的渲染方法到基于帆布的方法,以提高性能并提高内容的一致性。
文章链接:Google文档现在将使用基于帆布的渲染:这可能会影响某些Chrome Extensions
鉴于人们对Google趋之若鹜的跟随心理,Google的每一次变革似乎都成了当下技术的趋势,当然这一次也不例外,Google Docs 决定更新为Canvas渲染以后,把Canvas推上了一个新的高度。
相关的的文章可以看这篇了解一下:The Future Web: Will Canvas Rendering Replace the DOM?
Canvas已悄悄成了web文本渲染的一种趋势,未来Canvas渲染是否会取代DOM渲染这个现在还不好断言,但Canvas的优势就放着这里,很多特定情况下如今DOM渲染已远远不如Canvas渲染,被替代已成为定局。
Canvas的创建
说了这么多下面开始我们Canvas基础的学习,首先咱们看看如何创建一个Canvas。
Canvas的创建其实就是一个HTML标签,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
</body>
</html>
效果如下:
上面的示例我们已经创建了一个完整的Canvas案例,需要重点说明的是:
属性
上面的<canvas>
标签中我们用到了四个属性,分别是:
- id:画布的唯一标识,获取画布的时候可以用它
- width:画布的宽度,这里需要说明在不设置画布宽度的时候,默认宽度为300像素
- height:画布的高度,这里需要说明在不设置画布高度的时候,默认高度为150像素
- style:画布的样式,例如正常情况下画布是没有边框或者阴影的,但上面示例中我们通过
style
属性给<canvas>
标签设置了阴影和圆角样式。
兼容
在这里直接放一张 Can I Use 的详细兼容表。
如上图所示,虽然<canvas>
最早是由 Apple 引入 WebKit,用于Mac OS X 的 Dashboard,可如今已经被所有主流的浏览器所支持。
绘制
Canvas的核心就是绘制内容,学会如何绘制元素其实整个Canvas的学习也就基本算是入门了。那么如何绘制呢?
绘制上下文
在Canvas的绘制中,Canvas本身是没有绘制能力的,它的所有绘制都是通过JavaScript来实现的,真正印证了阿特伍德定律:
any application that can be written in JavaScript, will eventually be written in JavaScript。
译文:任何可以用JavaScript来写的应用,最终都将用JavaScript来写。
言归正传,在Canvas没有绘制能力的情况下,JavaScript又如何在Canvas中实现元素的绘制呢?
这还得说到一个东西:绘制上下文。
获取Canvas 绘制上下文的方法为:getContext()
,正是这个方法让Canvas具备绘制的能力。
既然说到了这里那就补充一个方法:getWebGLContext()
,这个方法可以让Canvas具备绘制能力,但和getContext()
的区别是getWebGLContext()
是用来给WebGL提供绘制上下文的。这里咱们主要说Canvas就不过多对getWebGLContext()
方法进行展开说明了。言归正传咱们回到getContext()
方法。
语法结构
getContext()
方法的语法结构为:
canvas.getContext(contextType, contextAttributes)
参数说明:
- contextType 为绘制上下文的类型,类型参数有:
-
2d:用于创建一个 CanvasRenderingContext2D 2D绘制上下文。
-
webgl:用于创建一个 WebGLRenderingContext 3D渲染上下文对象。且该类型只支持在实现WebGL版本1的浏览器上可用也就是 OpenGL ES 2.0。
-
webgl2:用于创建一个 WebGL2RenderingContext 3D渲染上下文对象。且该类型只支持在实现WebGL版本2的浏览器上可用也就是 OpenGL ES 3.0。
-
bitmaprenderer:用于创建一个只提供将 canvas 内容替换为指定ImageBitmap功能的ImageBitmapRenderingContext。
注意📢:在同一个Canvas上,使用相同的类型参数contextType
多次调用getContext()
方法只会返回同一个绘制上下文。
- contextAttributes 为绘制上下文的属性,这些属性相对比较多,可以设置单个也可以同时设置多个,下面列一下,方便大家了解:
-
2D类型的参数有: (1)、
alpha
它的值为Boolean类型,如果设置为false, 浏览器将认Canvas背景总是不透明的,这样可以做到一些性能提效。(2)、willReadFrequently
,值也为Boolean类型,用于表明是否要重复操作,频繁调用getImageData()
方法时能节省内存,但是仅Gecko内核浏览器支持。(3)、storage
用于表明使用哪种方式存储,默认值 persisten,表示持久化存储。 -
3D类型的参数有: (1)、
alpha
值为Boolean类型,指示画布是否包含alpha缓冲区。 (2)、antialias
值为Boolean类型,指示是否开启抗锯齿。 (3)、depth
值为Boolean类型,表示绘图缓冲区的深度缓冲区至少为16位。 (4)、failIfMajorPerformanceCaveat
值为Boolean类型,指示如果系统性能较低,是否创建上下文。 (5)、powerPreference
:对用户代理的提示,指示GPU的哪种配置适合WebGL上下文。可能的值是:default
: 自动选择模式,自动决定哪种GPU配置最合适,为默认值。high-performance
: 高性能模式,优先考虑渲染性能而不是功耗。low-power
: 节能模式,优先考虑节能而不是渲染性能。 (6)、premultipliedAlpha
值为Boolean类型,表示页面合成器将假定绘图缓冲区包含具有预乘alpha的颜色。 (7)、preserveDrawingBuffer
值为Boolean类型,如果值为true,则不会清除缓冲区并保留其值,直到被清除或被使用者覆盖。 (8)、stencil
值为Boolean类型,表示绘图缓冲区具有至少8位的模板缓冲区。
了解了语法以后,咱们开始看看如何获取上下文。代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
console.log(ctx) // CanvasRenderingContext2D ...
</script>
</body>
</html>
效果如下:
从上图咱们可以看出,通过getContext()
方法我们获取到了Canvas的绘制上下文。在上图的折叠属性canvas
中,其实还有很多属性,感兴趣的小伙伴可以打印了看一下都有哪些东西。
绘制方式
想要绘制出效果,我们还需要了解一下绘制的方法,我这边把绘制分为两种,描边和填充,对应的方法为 stroke()
和 fill()
stroke()
描边
fill()
填充
具体效果我们一起举个例子看一下就清楚了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.rect(50, 50, 200,100) // 绘制矩形
ctx.stroke() // 描边一个矩形轮廓
ctx.beginPath() // 开启新路径
ctx.rect(50, 200, 200,100) // 绘制矩形
ctx.fill() // 填充一个矩形
</script>
</body>
</html>
这里咱们先不管矩形为什么这么绘制,beginPath()
方法又是用来干啥的,咱们直接看效果,看看描边stroke()
和填充fill()
绘制出来的矩形有什么不同。
如上图所示,描边就是绘制出一个矩形的轮廓,填充就是使用默认的颜色(黑色)填充一个矩形块。
那我们如何改变描边和填充的样式呢?
样式设置
描边和填充的默认样式都是黑色,下面我们可以通过两个属性设置他们的样式,分别是strokeStyle
和 fillStyle
属性
strokeStyle
描边的样式
fillStyle
填充的样式
一起举个例子看一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
ctx.rect(50, 50, 200,100) // 绘制矩形
ctx.stroke() // 描边一个矩形轮廓
ctx.beginPath() // 开启新路径
ctx.fillStyle = "#0f0" // 描边样式设置为绿色
ctx.rect(50, 200, 200,100) // 绘制矩形
ctx.fill() // 填充一个矩形
</script>
</body>
</html>
设置了样式以后的效果为:
值得注意的是,strokeStyle
和 fillStyle
属性的设置是一次设置永久有效的,想要改变必须重新设置其他值来覆盖原有的值。
举个例子看一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
// 矩形一
ctx.rect(50, 50, 200, 100) // 绘制矩形
ctx.stroke() // 描边一个矩形轮廓
// 矩形二
ctx.beginPath() // 开启新路径
ctx.rect(50, 200, 200, 100) // 绘制矩形
ctx.stroke() // 描边一个矩形轮廓
// 矩形三
ctx.beginPath() // 开启新路径
ctx.strokeStyle = "#00f" // 描边样式重新设置为蓝色
ctx.rect(50, 350, 200, 100) // 绘制矩形
ctx.stroke() // 描边一个矩形轮廓
</script>
</body>
</html>
效果如下
如上图所示,矩形一和矩形二沿用了最开始设置的 strokeStyle
属性(红色),矩形三重新设置strokeStyle
属性为蓝色以后,矩形三变成了蓝色的矩形。
这说明strokeStyle
属性一旦设置以后是一直有效的,直到被覆盖。
fillStyle
属性和strokeStyle
属性一样,一旦设置以后是一直有效的,直到被覆盖。
基本绘制形状
在Canvas的绘制中,基本绘制形状主要有:直线
、三角形
、矩形
、圆和圆弧
、椭圆
、贝塞尔曲线
。
下面我们依次介绍一下这些基本绘制形状。
直线
直线的绘制就是设置两个点,然后连接这两个点形成一条直线,那么这两个点如何设置呢?
moveTo(x, y)
设置初始位置,参数为初始位置x和y的坐标点
lineTo(x, y)
设置指定位置,参数为指定位置x和y的坐标点
举个例子看一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
// 画一条(50, 50) 到 (400, 50)的直线
ctx.moveTo(50, 50)
ctx.lineTo(400, 50)
ctx.stroke()
// 连续的直线只需要设置一个起始点
ctx.moveTo(50, 100)
ctx.lineTo(50, 400)
ctx.lineTo(400, 400)
ctx.stroke()
</script>
</body>
</html>
效果如下:
样式
直线的样式可以通过一系列属性来设置,
lineWidth
设置直线的粗细,默认值为1,且属性值必须为正数。
举个例子看一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
// 画一条(50, 50) 到 (400, 50)的直线
ctx.moveTo(50, 50)
ctx.lineTo(400, 50)
ctx.stroke()
ctx.beginPath() // 开启新路径
// 连续的直线只需要设置一个起始点
ctx.lineWidth = 10
ctx.moveTo(50, 100)
ctx.lineTo(50, 400)
ctx.lineTo(400, 400)
ctx.stroke()
</script>
</body>
</html>
效果如下:
lineCap
设置直线端点显示的样式。可选值为:butt,round 和 square。默认是 butt。
举个例子看一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
// lineCap 值为 butt
ctx.lineWidth = 20;
ctx.lineCap='butt'
ctx.moveTo(50, 50);
ctx.lineTo(400, 50);
ctx.stroke();
// lineCap 值为 round
ctx.beginPath()
ctx.lineWidth = 20;
ctx.lineCap='round'
ctx.moveTo(50, 100);
ctx.lineTo(400, 100);
ctx.stroke();
// lineCap 值为 square
ctx.beginPath()
ctx.lineWidth = 20;
ctx.lineCap='square'
ctx.moveTo(50, 150);
ctx.lineTo(400, 150);
ctx.stroke();
</script>
</body>
</html>
效果如下:
lineJoin
设置两线段连接处所显示的样子。可选值为:round, bevel 和 miter。默认是 miter。
举个例子看一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
// lineJoin 值为 miter
ctx.beginPath()
ctx.lineWidth = 10;
ctx.lineJoin='miter'
ctx.moveTo(50, 20);
ctx.lineTo(150, 140);
ctx.lineTo(250, 20);
ctx.stroke();
// lineJoin 值为 round
ctx.beginPath()
ctx.lineWidth = 10;
ctx.lineJoin='round'
ctx.moveTo(50, 100);
ctx.lineTo(150, 220);
ctx.lineTo(250, 100);
ctx.stroke();
// lineJoin 值为 bevel
ctx.beginPath()
ctx.lineWidth = 10;
ctx.lineJoin='bevel'
ctx.moveTo(50, 180);
ctx.lineTo(150, 300);
ctx.lineTo(250, 180);
ctx.stroke();
</script>
</body>
</html>
效果如下:
miterLimit
设置当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
线段之间夹角比较大时,交点不会太远,但随着夹角变小,交点距离会呈指数级增大。
如果交点距离大于miterLimit值,连接效果会变成了 lineJoin = bevel 的效果。
举个例子看一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
// miterLimit为定值,角度越大
ctx.beginPath()
ctx.lineWidth = 5;
ctx.lineJoin='miter'
ctx.miterLimit = 10
ctx.moveTo(0, 100);
for (i = 0; i < 50 ; i++) {
var dy = i % 2 == 0 ? 200 : 100;
ctx.lineTo(Math.pow(i, 1.5) * 2, dy);
}
ctx.stroke();
ctx.closePath();
</script>
</body>
</html>
效果如下:
setLineDash/getLineDash
setLineDash 设置虚线样式。
getLineDash 返回虚线设置的样式,长度为非负偶数的数组。
举个例子看一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
ctx.lineWidth = 5
// 绘制一条虚线
ctx.setLineDash([5, 10, 20]);
console.log(ctx.getLineDash()); // [5, 10, 20, 5, 10, 20]
ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(500, 100);
ctx.stroke();
// 再绘制一条虚线
ctx.setLineDash([5, 10, 20, 40]);
console.log(ctx.getLineDash()); // [5, 10, 20, 40]
ctx.beginPath();
ctx.moveTo(0,200);
ctx.lineTo(500, 200);
ctx.stroke();
</script>
</body>
</html>
效果如下:
在上图中我们发现,设置的虚线数组为:[5, 10, 20],但打印出来的却是:[5, 10, 20, 5, 10, 20],这是因为 getLineDash 返回虚线的长度为非负偶数的数组。所以如果传参长度为奇数,例如:ctx.setLineDash([5, 10, 20])时,setLineDash 会复制一份数组补全为偶数,等同于我们设置的是:ctx.setLineDash([5, 10, 20, 5, 10, 20])。
lineDashOffset
lineDashOffset 设置虚线样式的起始偏移量。例如:15
举个例子看一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 创建</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
ctx.lineWidth = 5
// 绘制一条虚线
ctx.setLineDash([5, 10, 20, 40]);
console.log(ctx.getLineDash()); // [5, 10, 20, 40]
ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.stroke();
ctx.setLineDash([5, 10, 20, 40]);
ctx.lineDashOffset = 15;
ctx.beginPath();
ctx.moveTo(0,300);
ctx.lineTo(400, 300);
ctx.stroke();
</script>
</body>
</html>
效果如下:
如图所示,虚线的总长度没有变化,但起始点向左位移了15个像素。
三角形
我们知道了直线的绘制以后,三角形的绘制也就显得格外简单,在上面的例子中其实我们已经绘制了两条直线连接在一起,那么三条直线收尾连接在一起就是我们的三角形了。举个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas - 三角形</title>
</head>
<body>
<canvas
id="canvas"
width="500"
height="500"
style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
当前浏览器不支持canvas元素,请升级或更换浏览器!
</canvas>
<script>
const canvas = document.getElementById('canvas'); // 获取Canvas
const ctx = canvas.getContext('2d'); // 获取绘制上下文
ctx.strokeStyle = "#f00" // 描边样式设置为红色
ctx.fillStyle = "#00f" // 填充样式设置为蓝色
ctx.lineWidth = 5
// 绘制一个三角形
ctx.moveTo(50, 100)
ctx.lineTo(50, 400)
ctx.lineTo(400, 400)
ctx.lineTo(50, 100)
ctx.stroke();
// 如果是填充一个三角形,则只需两条直线就行,它会默认闭合。
ctx.beginPath()
ctx.moveTo(200, 200)
ctx.lineTo(400, 200)
ctx.lineTo(400, 370)
ctx.fill();
</script>
</body>
</html>
效果如下:
直线能绘制三角形那么同样的也就能绘制四边形、五边形、六边形......等等多边形。但直线也有不能绘制的东西,比如圆、曲线等。
因此Canvas还提供了一些绘制基本形状的API,具体有哪些我们下一遍文章再仔细说。