目录
  1. 1. Canvas
    1. 1.1. 体验Canvas
      1. 1.1.1. 什么是Canvas?
      2. 1.1.2. 创建Canvas元素
      3. 1.1.3. Canvas坐标系
      4. 1.1.4. 通过JavaScript来绘制
    2. 1.2. Canvas的基本使用
      1. 1.2.1. 图形绘制
      2. 1.2.2. 设置样式
      3. 1.2.3. 参考文档
    3. 1.3. Canvas图形绘制
      1. 1.3.1. 矩形绘制
      2. 1.3.2. 圆弧绘制
      3. 1.3.3. 绘制文本
      4. 1.3.4. 实例练习
        1. 1.3.4.1. 绘制3个不同颜色的平行线
        2. 1.3.4.2. 绘制一个填充三角形
        3. 1.3.4.3. 绘制一个镂空正方形
        4. 1.3.4.4. 绘制渐变矩形1
        5. 1.3.4.5. 绘制渐变矩形2
          1. 1.3.4.5.1. createLinearGradient
          2. 1.3.4.5.2. createRadialGradient
          3. 1.3.4.5.3. addColorStop
    4. 1.4. canvas坐标的转换
canvas基础绘制

Canvas

canvas 最早由Apple引入WebKit,用于Mac OS X 的 Dashboard,后来又在Safari和Google Chrome被实现。
基于 Gecko 1.8的浏览器,比如 Firefox 1.5, 同样支持这个元素。
<canvas> 元素是WhatWG Web applications 1.0规范的一部分,也包含于HTML 5中。

体验Canvas

什么是Canvas?

HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。
画布是一个矩形区域,您可以控制其每一像素。
canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

创建Canvas元素

向 HTML5 页面添加 canvas 元素。
规定元素的 id、宽度和高度:

<canvas id="myCanvas" width="200" height="100"></canvas>

Canvas坐标系

通过JavaScript来绘制

/*获取元素*/
var myCanvas = document.querySelector('#myCanvas');
/*获取绘图工具*/
var context = myCanvas.getContext('2d');
/*设置绘图的起始位置*/
context.moveTo(100,100);
/*绘制路径*/
context.lineTo(200,200);
/*描边*/
context.stroke();

Canvas的基本使用

图形绘制

需要理解些概念:

  • 路径的概念
  • 路径的绘制
    • 描边 stroke()
    • 填充 fill()

  • 闭合路径
    • 手动闭合
    • 程序闭合 closePath()
  • 填充规则(非零环绕)

  • 开启新的路径 beginPath()

设置样式

  • 画笔的状态
    • lineWidth 线宽,默认1px
    • lineCap 线末端类型:(butt默认)、round、square
    • lineJoin 相交线的拐点 miter(默认)、round、bevel
    • strokeStyle 线的颜色
    • fillStyle 填充颜色
    • setLineDash() 设置虚线
    • getLineDash() 获取虚线宽度集合
    • lineDashOffset 设置虚线偏移量(负值向右偏移)

参考文档

Canvas图形绘制

矩形绘制

  • rect(x,y,w,h) 没有独立路径
  • strokeRect(x,y,w,h) 有独立路径,不影响别的绘制
  • fillRect(x,y,w,h) 有独立路径,不影响别的绘制
  • clearRect(x,y,w,h) 擦除矩形区域

圆弧绘制

  • 弧度概念
  • arc()
    • x 圆心横坐标
    • y 圆心纵坐标
    • r 半径
    • startAngle 开始角度
    • endAngle 结束角度
    • anticlockwise 是否逆时针方向绘制(默认false表示顺时针;true表示逆时针)

绘制文本

  • ctx.font = ‘微软雅黑’ 设置字体
  • strokeText()
  • fillText(text,x,y,maxWidth)
    • text 要绘制的文本
    • x,y 文本绘制的坐标(文本左下角)
    • maxWidth 设置文本最大宽度,可选参数
  • ctx.textAlign文本水平对齐方式,相对绘制坐标来说的
    • left
    • center
    • right
    • start 默认
    • end
  • ctx.direction属性css(rtl ltr) start和end于此相关
    • 如果是ltr,start和left表现一致
    • 如果是rtl,start和right表现一致
  • ctx.textBaseline 设置基线(垂直对齐方式 )
    • top 文本的基线处于文本的正上方,并且有一段距离
    • middle 文本的基线处于文本的正中间
    • bottom 文本的基线处于文本的证下方,并且有一段距离
    • hanging 文本的基线处于文本的正上方,并且和文本粘合
    • alphabetic 默认值,基线处于文本的下方,并且穿过文字
    • ideographic 和bottom相似,但是不一样
  • measureText() 获取文本宽度obj.width

实例练习

绘制3个不同颜色的平行线

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

/*画平行线*/
ctx.beginPath(); /*开启新的路径*/
/*蓝色 10px*/
ctx.moveTo(100, 100);
ctx.lineTo(300, 100);
ctx.strokeStyle = 'blue';
ctx.lineWidth = 10;
/*描边*/
ctx.stroke();

ctx.beginPath(); /*开启新的路径*/
/*红色 20px*/
ctx.moveTo(100, 200);
ctx.lineTo(300, 200);
ctx.strokeStyle = 'red';
ctx.lineWidth = 20;
/*描边*/
ctx.stroke();

ctx.beginPath(); /*开启新的路径*/
/*绿色 30px*/
ctx.moveTo(100, 300);
ctx.lineTo(300, 300);
ctx.strokeStyle = 'green';
ctx.lineWidth = 30;
/*描边*/
ctx.stroke();
</script>
</body>
</html>

如果不在每条平行线绘制前添加ctx.beginPath();,那么每一次新的绘制都会覆盖上面的绘制

绘制一个填充三角形

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

/*1.绘制一个三角形*/
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(200,200);
/*起始点和lineTo的结束点无法完全闭合缺角*/
/*使用canvas的自动闭合 */
//ctx.lineTo(100,100);
/*关闭路径*/
ctx.closePath();

ctx.lineWidth = 10;
/*2.描边*/
ctx.stroke();
/*3.填充*/
//ctx.fill();

</script>
</body>
</html>

没有使用closePath()

使用closePath()

绘制一个镂空正方形

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

/*1.绘制两个正方形 一大200一小100 套在一起*/
ctx.moveTo(100,100);
ctx.lineTo(300,100);
ctx.lineTo(300,300);
ctx.lineTo(100,300);
ctx.closePath();

ctx.moveTo(150,150);
ctx.lineTo(150,250);
ctx.lineTo(250,250);
ctx.lineTo(250,150);
ctx.closePath();

/*2.去填充*/
//ctx.stroke();
ctx.fillStyle = 'red';
ctx.fill();
</script>
</body>
</html>

可以发现,此处正方形并没有镂空,而是完全的填充了,因此并没有达到目的,那么镂空填充要遵循一个原则:非零环绕规则

什么是非零环绕规则?

从填充区域拉一根线到外部,相交的线,如果是顺时针环绕的,则+1,反之-1,最后判断得到数字是否为0,如果非零则填充,为0则不填充

此图可以判断出,内部的正方形计算结果为+2,则填充,同样外部正方形判断以后也填充,所以得到的才会是一个大的完整填充的正方形

因此:

通过此方式,内部的正方形就不会填充,仅填充外部的正方形,即可做到正方形镂空

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

/*1.绘制两个正方形 一大200一小100 套在一起*/
ctx.moveTo(100,100);
ctx.lineTo(300,100);
ctx.lineTo(300,300);
ctx.lineTo(100,300);
ctx.closePath();

ctx.moveTo(150,150);
ctx.lineTo(150,250)
ctx.lineTo(250,250)
ctx.lineTo(250,150)
ctx.closePath();

/*2.去填充*/
ctx.fillStyle = 'red';
ctx.fill();

</script>
</body>
</html>

绘制渐变矩形1

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

/*线是由点构成的*/
ctx.lineWidth = 30;
for (var i = 0; i < 255; i++) {
ctx.beginPath();
ctx.moveTo(100+i-1,100);
ctx.lineTo(100+i,100); // 构建每一个点
ctx.strokeStyle = 'rgb('+i+','+i+','+i+')';
ctx.stroke();
}

</script>
</body>
</html>

绘制渐变矩形2

普及下线性渐变的两种API

createLinearGradient

createLinearGradient(x1, y1, x2, y2)

创建一个线性渐变对象,其起点为(x1,y1),终点为(x2,y2)。

例如:

var lineargradient = ctx.createLinearGradient(0, 0, 150, 150);
createRadialGradient

createRadialGradient(x1, y1, r1, x2, y2, r2)

创建一个径向渐变。参数代表两个圆,一个圆的中心为(x1,y1),半径为r1,另一个圆的中心为(x2,y2),半径为r2。

var radialgradient = ctx.createRadialGradient(75, 75, 0, 75, 75, 100);

创建CanvasGradient对象后,可以使用addColorStop()方法为对象分配颜色。

addColorStop

gradient.addColorStop(position, color)

gradient对象上创建一个新的色标。的position是在0.0和1.0之间的数,并且限定在渐变中的颜色的相对位置,并且所述color参数必须是表示CSS一个字符串color,表示颜色的梯度应该偏移处的过渡达到。

可以根据需要向渐变添加尽可能多的色标。

例如:

var lineargradient = ctx.createLinearGradient(0, 0, 150, 150);
lineargradient.addColorStop(0, 'white');
lineargradient.addColorStop(0.3, 'blue');
lineargradient.addColorStop(1, 'black');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="linearGradient"></div>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

var linearGradient = ctx.createLinearGradient(100,100,500,400);
linearGradient.addColorStop(0,'pink');
linearGradient.addColorStop(0.5,'red');
linearGradient.addColorStop(1,'blue');

ctx.fillStyle = linearGradient;

ctx.fillRect(100,100,400,100);

/*pink---->blue*/
/*回想线性渐变---->要素 方向 起始颜色 结束颜色 */
/*通过两个点的坐标可以控制 渐变方向*/
</script>
</body>
</html>

canvas坐标的转换

  • 平移 移动画布的原点
    • translate(x,y) 参数表示移动目标点的坐标
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>

<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*将坐标原点变为150,150*/
ctx.translate(150, 150);
ctx.strokeRect(0, 0, 100, 100);

</script>
</body>

</html>

  • 缩放
    • scale(x,y) 参数表示宽高的缩放比例
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>

<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*宽缩短一半,高不变*/
ctx.scale(0.5, 1);
ctx.strokeRect(150, 150, 100, 100);

</script>
</body>

</html>

  • 旋转
    • rotate(angle) 参数表示旋转角度
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>

<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');

ctx.rotate(Math.PI / 6);
ctx.strokeRect(150, 150, 100, 100);

</script>
</body>

</html>

文章作者: Jachie Xie
文章链接: https://xjc5772.github.io/2020-07/30/%E5%AD%A6%E4%B9%A0/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0/H5/canvas%E5%9F%BA%E7%A1%80%E7%BB%98%E5%88%B6/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 XJC&Blog
打赏
  • 微信
  • 支付宝

评论