使用JavaScriptCanvasAPI绘制形状

来自菜鸟教程
跳转至:导航、​搜索

在本文中,我们将研究 HTML 画布元素和 JavaScript 画布 API,以将复杂的形状呈现到我们的网页上。

设置

我们只需要一个带有画布标签的 HTML 页面和一个用于操作它的 JavaScript 文件即可开始。

索引.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>HTML Canvas</title>
  </head>
  <body>

    <canvas></canvas>

  </body>
  <script src="./canvas.js"></script>
</html>

有了画布元素,我们现在需要用它和画布上下文创建一个新变量,这会在画布上添加一堆功能。 为简单起见,我们将坚持使用 2D 形状,但使用 webgl 上下文,3D 也是可能的。

对于我们的示例,我们需要我们的画布是全屏的,但是使用 CSS 设置大小会产生一种奇怪的模糊效果,这显然是我们不想要的,所以我们必须在这里设置它。

画布.js

// getting a reference to our HTML element
const canvas = document.querySelector('canvas')

// initiating 2D context on it
const c = canvas.getContext('2d')

addEventListener('resize', () => {
  canvas.width = innerWidth
  canvas.height = innerHeight
})

矩形

为了绘制矩形,在我们的上下文变量(c)上,我们可以开始添加我们想要的东西,以像素为单位:

  • rect(x-axis, y-axis, width, height):设置我们矩形的位置和尺寸,需要在stroke或者fill之前调用。
  • stroke:渲染其前面所有内容的轮廓。
  • fill:将整个形状渲染为纯色。
  • strokeStylefillStyle:设置轮廓和形状颜色。 它们不像其他函数,需要分配一个字符串。
  • strokeRectfillRect:与 strokefill 相同,但仅适用于该项目,与 rect 相同。
  • clearRect(x-axis, y-axis, width, height):清除特定区域内的所有内容。 当我们进入不断渲染新元素并且不希望旧元素停留的动画时非常有用。

画布.js

c.strokeStyle = 'white'
c.fillStyle = 'blue'
c.rect(100, 20, 150, 100)
c.stroke()
c.fill()

c.fillStyle = 'red'
c.fillRect(400, 500, 300, 250)

// Uncomment to remove the first two blocks
// c.clearRect(0, 0, canvas.width, canvas.height)
c.fillStyle = 'green'
c.fillRect(1500, 500, 300, 250)

线条

  • beginPath:开始新行
  • stroke:渲染线条
  • moveTo(x-axis, y-axis):设置起点
  • lineTo(x-axis, y-axis):从上一个端点渲染一条线
  • lineWidth:设置线条的粗细

下面是一些我们画线的例子:

// Just a basic line
c.beginPath()
c.moveTo(40, 250)
c.lineTo(200, 500)
c.strokeStyle = 'red'
c.stroke()

// Draw the letter M
c.beginPath()
c.moveTo(1500, 700)
c.lineTo(1600, 450)
c.lineTo(1700, 700)
c.lineTo(1800, 450)
c.lineTo(1900, 700)
c.strokeStyle = 'blue'
c.stroke()

// Let's now draw a house
c.lineWidth = 10
c.strokeStyle = 'red'
c.fillStyle = 'red'

// Walls 
c.strokeRect(800, 500, 300, 200)

// Door
c.fillRect(925, 600, 50, 100)

// Roof 
c.beginPath()
c.moveTo(700, 500)
c.lineTo(1200, 500)
c.lineTo(950, 300)
c.lineTo(700, 500)
c.stroke()

我们真正需要的绘制圆的唯一方法是 arc。 角度采用弧度而不是度数,因此对于我们的结束角度,我们可以只使用 Math.PI * 2,因为它等于 360 度,起始角度可以保留为 0。 我们不需要为 counterclockwise 指定值,因此我们可以将其关闭,因为它默认为 false。

  • arc(x, y, radius, starting-angle, end-angle, counterclockwise (boolean))

画布.js

c.lineWidth = 5
c.beginPath()
c.arc(400, 400, 50, 0, Math.PI * 2)
c.stroke()

二次曲线和贝塞尔曲线

如果您曾经使用过 Photoshop 或 Affinity Designer 等图形设计工具,这些工具看起来与他们的一些线条工具非常相似。

本质上,二次曲线和贝塞尔曲线只是具有不同控制方法的自由曲线。 二次曲线更简单,因为它们只有一个起点、终点和所谓的控制点,它充当弯曲线的句柄。 你可以在这里看到一个精彩的交互示例。 另一方面,贝塞尔曲线在曲线的每一端都有两个控制点,用于更复杂的形状。 另一个很好的例子 这里

  • quadraticCurveTo(controlPoint-x, controlPoint-y, endpoint-x, endpoint-y)
  • bezierCurveTo(startControlPoint-x, startControlPoint-y, endControlPoint-x, endControlPoint-y, endpoint-x, endpoint-y)

还有一些例子:

画布.js

c.lineWidth = 5
c.strokeStyle = 'white'

c.beginPath()
c.moveTo(400, 400)
c.lineTo(400, 300)
c.quadraticCurveTo(450, 250, 500, 300)
c.lineTo(500, 400)
c.stroke()

c.beginPath()
c.moveTo(800, 400);
c.bezierCurveTo(800, 150, 1200, 700, 1200, 400);
c.stroke()

文本

文本的工作方式与带有一些类似 CSS 的样式选项的矩形非常相似:

  • fillText(text, x, y)
  • strokeText(text, x, y)
  • font: 采用像素大小和字体系列的字符串; 像'60px Times-New-Roman'。
  • textAlign:采用与 CSS 对应选项相同的字符串; startendleftrightcenter

画布.js

c.font = '60px Times-New-Roman'
c.fillText("Hello World", 600, 500)
c.strokeText('Hello World', 1200, 500)

结论

虽然仍然可以使用 HTML 画布(如动画和交互性)完成大量工作,但希望这是对它的一些可能性的一个很好的第一次介绍。