前端人工智能:canvas 绘制黑白棋子

3,652 阅读6分钟

上一节中,我们带大家简单介绍了 canvas 和它的一些很容易被忽略的特性,并且利用 canvas 绘制出了线条。但是在五子棋中,最重要的就是我们还得有棋子。我们的棋子是有黑、白两种样式的,而且还是圆的。但是 canvas 其实是并没有直接提供方法给我们去画圆的,那我们怎么去画呢?

使用 canvas 画圆

首先我们都知道,圆是由弧去组成的,只有弧度到达指定的数值,才会形成圆这个形状。所以,在 canvas 中,所有的圆都是由弧度去组成的。那么接下来我们就来看看到底应该怎么去画一个圆:

首先我们还是得跟context说一声,我们要开始画了(context.beginPath()),然后用它提供的 arc 方法去画,而 arc 的英文意思就是弧:

context.beginPath()
context.arc(圆心x轴的位置,圆心y轴的位置,半径,起始角度,终点角度,是否逆时针)

arc 会接收圆心x轴的位置跟圆心y轴的位置,意思就是要告诉 canvas 我们要从哪里开始画。而半径我们都知道,圆是有直径跟半径的。那么接下来第四个参数就是起始角度,那么什么叫做起始角度呢?其实就是我们这个东西呢,本来就是这个弧,而不是一个圆。是弧的话,就必须有一个起始角。

那第五个参数我们也很好理解了,有起始角度,就肯定会有终点角度。第六个参数,是否是逆时针。因为我们画画也知道,你可以按顺时针的方向去画,同样也可以反其道而行之,通过逆时针去画。

那接下来我们就利用 arc 方法去进行绘制,我们先告诉 canvas 我们要从x轴200,y轴200的地方开始画圆,然后画一个半径是50的圆,然后终点角度我们先不给,是否逆时针默认就是个false值,也就是默认就是顺时针:

context.beginPath()
context.arc(200,200,50,0,终点角度,false)

那为什么终点角度我们先不给呢?因为在 canvas 中,终点角度跟我们所认为的是不太一样的。比如你想画圆,圆是 360 度的对吧,这时候你可以起始角度定 0,然后终点角度给 360 度。这时候 canvas 的理解跟我们的理解是不一致的,这时候我们就需要数学函数Math

我们先来打印一下Math这个函数,看下它都有些什么:

它提供了很多东西,那我们来猜一下哪个是跟圆有关的。大家有没有发现一个很熟悉的东西,3.1415926....

没错了,就是我们数学中最熟悉的圆周率(π)。我们这个数学函数所理解的呢,就是0.5乘以圆周率(π)就是90度,那我们想要一个圆的话,是不是得等于 2 乘以圆周率(π),也就是 360 度:

Math.PI * 2 = 360

我们把终点角度的代码补齐:

context.beginPath()
context.arc(200, 200, 50, 0, 2 * Math.PI, false)

然后我们收笔(context.stroke()),刷新一下页面看看效果:

这时候你可以看到我们的圆就出来了,那我们接下来再熟悉一下 arc 的几个参数,比如我们现在不要 360 度,想要 270 度,那就是 1.5 乘以圆周率(π)就是 270 度,这时候其实就构不成一个圆了,我们来看看效果:

context.beginPath()
context.arc(200, 200, 50, 0, 1.5 * Math.PI, false)
context.stroke()

我们再来看看,如果是直径是100,然后逆时针,看看是什么效果:

context.beginPath()
context.arc(200, 200, 100, 0, 1.5 * Math.PI, true)
context.stroke()

我们可以明显地看到圆变大了,因为直径改成了 100,而且逆时针的效果也出来了。那也希望大家多熟悉这些效果,便于今后可以用来实现更多效果。

使用 canvas 完成会反光的黑棋

那白棋我们已经画完了对吧,那黑棋怎么画呢?是不是我们填充一个黑色的背景色,我们这个黑棋就完成了:

context.beginPath()
context.arc(200, 200, 100, 0, 2 * Math.PI, true)
context.fill()
context.stroke()

上面的代码中,我们利用了context大兄弟提供的fill方法去对当前的路径内容进行填充,默认就是黑色:

但是我们下过五子棋的都知道,黑棋的颜色其实并不是纯黑色,是一个稍微比较明亮点的黑色,搁在桌面上,其实是会有一定的反光的(如下图)。那我们要做反光的效果要怎么做呢?在 canvas 中,提供了一个叫做createRadiaGradient圆形渐变填充的方法,这个方法说白了其实就是帮我们实现反光的效果的。

它一共提供了几个参数,首先是x0和y0,分别代表渐变开始圆的 x 坐标以及渐变开始圆的 y 坐标。怎么理解呢?我们来看下面这张图片。

我们可以很清楚地看到在下面这个渐变圆形中,其实是有两个圆形的,一个比较深色的,一个比较渐变浅色的。那么x0和y0呢就可以理解为是这个深色圆的圆心位置;r0也比较好理解,就是这个深色圆的半径。

那么相对的x1、y1、r1就分别是渐变结束圆的x坐标、渐变结束圆的y坐标、渐变结束圆的半径。

context.createRadialGradient(x0,y0,r0,x1,y1,r1)

那这个时候就会有同学有疑问了,我们的五子棋是白色的反光,上图是红色的。但是这个方法好像没有参数是设置颜色的呀?别急,是有提供了一个名为addColorStop的方法的。它接受两个值,分别是stopcolor

color比较好理解,就是我们要设置的颜色;stop则表示渐变中开始与结束之间的位置。

addColorStop(stop,color);

下面我们先做一个棋子看看效果,也可以让大家更理解这些方法。我们先改一下圆的位置和半径,先改小一点。然后创建一个径向渐变对象 grd,它的中心点坐标跟圆的保持一致 (100, 100),起始半径也保持为 60,渐变的终点坐标 (125, 75) 其实就是比原本圆心的位置再偏右一点,结束半径为 1。

context.arc(100, 100, 60, 0, 2 * Math.PI)
// 制作反光效果
var grd = context.createRadialGradient(100, 100, 60, 125, 75, 1)

然后我们定义一下它的颜色。通过 addColorStop() 方法设置了两个颜色停止点,一个是 0,表示渐变的起点,颜色为黑色;另一个是 1,表示渐变的终点,颜色为白色。然后,将设置好的径向渐变对象 grd 赋值给填充样式 fillStyle

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
      body { background: #000; }
      canvas { background: #fff }
    </style>
  </head>
  <body>
    <canvas id="canvas" width=800 height=800></canvas>
  </body>
  <script type="text/javascript">
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    context.beginPath()
    // 画圆
    context.arc(100, 100, 60, 0, 2 * Math.PI)
    // 设置反光
    var grd = context.createRadialGradient(100, 100, 60, 125, 75, 1)
    // 设置反光的颜色
    grd.addColorStop(0, 'black')
    grd.addColorStop(1, 'white')
    context.fillStyle = grd
    context.fill()
    context.stroke()
  </script>
</html>

我们保存一下代码,运行看看效果。

我们可以看到这个棋子就比较贴合我们现实生活中的棋子了,那我们的黑白棋子也做完了。目前来说还算是比较简单的,也是给大家一个慢慢适应的过程。

在下一节中,我们需要利用这两节中学的知识,把整个棋盘调整完毕,然后正式进入逻辑算法的世界。