Canvas 都坐下,基本操作

3,637 阅读8分钟

前言

从最开始小白使用canvas采坑无数,让自己也积累了些还不错的想法,这期内容也是给自己做了些canvas api整理,以及需要注意的地方

参考网站

MDN

文章链接

微信H5实现网页长按保存图片及识别二维码(canvas转换)

前端学习笔记----canvas实现画板及定制画笔(画笔错位,撤回,粗细,颜色)

前端学习笔记----多张图片生成canvas思路

替换内容

在比较老的不支持 canvas 的浏览器中(尤其是IE9之前的IE浏览器), canvas 会被标签中的内容替换(可用于提示不兼容canvas)

<canvas width="150" height="150">
  该浏览器不兼容canvas
</canvas>

<canvas width="150" height="150">
  <img src="images/clock.png" width="150" height="150" alt=""/>
</canvas> 

渲染上下文 getContext('2d')

获得渲染上下文和它的绘画功能。比如说用来定义画笔样式以及进行绘画的所有操作。getContext()只有一个参数

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ctx 即为 id为canvas的标签的上下文

画布栅格(canvas grid)

Canvas 画布其实就是像一个坐标系,使用内置的Api在画板上进行绘制,通常来说坐标上的一个单位相当于canvas的一个像素, 栅格就像一个坐标系,不过是从左上角开始的,你可以更具坐标系来进行绘画等操作

友情提醒:最好不要使用style 以及 class去定义canvas长宽样式,画布中的小格会被style等样式压缩或拉伸,这样你画的东西就会变形了

那怎么办呢

<canvas id="canvas" width="200" height="200"></canvas>
// 直接标签中设置或者使用canvas上下文
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.width = 200
ctx.height = 200

图形

绘制矩形

canvas是按照路径生成图形,canvas只支持一种原生的图形绘制:矩形,不给过通过路径绘画使得绘制各种图形变成了可能

fillRect(x, y, width, height)  //绘制一个填充的矩形
strokeRect(x, y, width, height) //绘制一个矩形的边框
clearRect(x, y, width, height) //清除指定矩形区域,让清除部分完全透明。

x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。width和height设置矩形的尺寸。

  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  ctx.fillRect(25, 25, 100, 100);
  ctx.clearRect(45, 45, 60, 60); // 用来挖空上个图形
  ctx.strokeRect(150, 50, 50, 50);

绘制路径

路径的组合使你能画出任何你想要绘制的图形,就像你在纸上画画一样

beginPath()
// 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
// 相当于你拿起铅笔准备画画了
closePath()
// 闭合路径之后图形绘制命令又重新指向到上下文中。
// 不是每次都需要closePath 来结束绘画 这个接口功能就相当于 你画出两笔后形成一个直角,但你想画出一个封闭的直接三角形使用这个接口,即可把终点和气垫自动连上
stroke()
// 通过线条来绘制图形轮廓。
fill()
// 通过填充路径的内容区域生成实心的图形。
closePath()
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(20,100);
ctx.lineTo(70,100);

ctx.stroke();

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(20,100);
ctx.lineTo(70,100);
ctx.closePath();
ctx.stroke();

moveTo(x,y)

从哪开始下笔

你的铅笔尖从哪个点按到画板上

当然也能使用moveTo 绘制不连续的点

lineTo(x,y)

绘制一条从当前位置到指定x以及y位置的直线。

开始点和之前的绘制路径有关,之前路径的结束点就是接下来的开始点,等等。。。开始点也可以通过moveTo()函数改变。

圆弧

arc(x, y, radius, startAngle, endAngle, anticlockwise)`

画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。

x,y为绘制圆弧所在圆上的圆心坐标。radius为半径。startAngle以及endAngle参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准。参数anticlockwise`为一个布尔值。为true时,是逆时针方向,否则顺时针方向。

友情提醒:arc()函数中表示角的单位是弧度。角度与弧度的js表达式: 弧度=(Math.PI/180)/角度

arcTo(x1, y1, x2, y2, radius)

根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。

矩形

rect(x, y, width, height)

绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。

上色

fillStyle = color

设置图形的填充颜色。

strokeStyle = color

设置图形轮廓的颜色。

var ctx = document.getElementById('canvas').getContext('2d');
for (var i=0;i<6;i++){
  for (var j=0;j<6;j++){
    ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' + 
                       Math.floor(255-42.5*j) + ',0)';
    ctx.fillRect(j*25,i*25,25,25);
  }
}

其他线条Api

lineWidth = value
// 设置线条宽度。
lineCap = type
// 设置线条末端样式。
lineJoin = type
// 设定线条与线条间接合处的样式。
miterLimit = value
// 限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
getLineDash()
// 返回一个包含当前虚线样式,长度为非负偶数的数组。
setLineDash(segments)
// 设置当前虚线样式。
lineDashOffset = value
// 设置虚线样式的起始偏移量。
lineWidth = value 线条宽度。
lineCap = type 线条末端样式。
type == butt,round ,square

友情提醒:如使用鼠标绘制路径是 使用butt会导致 起始结尾 棱角比较多 可以使用 round 达到更好的视觉效果

lineJoin = type 线条与线条间接合处的样式。
type = round,bevel,miter。默认是miter。

友情提醒:同上 使用默认值会导致绘画时棱角比较多 ,可以使用 round 达到更好的视觉效果

虚线

setLineDash 方法和 lineDashOffset 属性来制定虚线样式. setLineDash 方法接受一个数组,来指定线段与间隙的交替;lineDashOffset属性设置起始偏移量.

var ctx = document.getElementById('canvas').getContext('2d');
var offset = 0;

function draw() {
  ctx.clearRect(0,0, canvas.width, canvas.height);
  ctx.setLineDash([4, 2]);
  ctx.lineDashOffset = -offset;
  ctx.strokeRect(10,10, 100, 100);
}

function march() {
  offset++;
  if (offset > 16) {
    offset = 0;
  }
  draw();
  setTimeout(march, 20);
}

march();

图像

canvas也可以吧已经有的图片 绘制在画板上进行编辑

var img = new Image();   // 创建一个img
img.src = 'xxx.png'; // 设置图片地址

友情提醒:如需把图片通过src绘制至canvas一定一定要使用img.onload 等待img.src加载完毕再执行渲染至canvas,不然可能渲染空白

var img = new Image();   // 创建img对象
img.onload = function(){
  // 执行drawImage语句
}
img.src = 'myImage.png'; // 设置图片地址
绘制

drawImage(image, x, y)

Image 为 上面的img对象或者 canvas 对象 xy 是其在目标 canvas画布 里的起始坐标。

缩放 Scaling

drawImage(image, x, y, width, height)

这个方法多了2个参数:widthheight,这两个参数用来控制 当向canvas画入时应该缩放的大小

切片

如果只需要使用一张图像上的部分 就得使用切片

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

第一个参数和其它的是相同的,其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。

save() remote()

两个骚操作 怎么个意思呢

把配置好的 样式 一次次放入一个栈中,需要事在从栈中 取出 就像一个回文一样”12344321“


function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.fillRect(0,0,150,150);   // 使用默认设置绘制一个矩形
  ctx.save();                  // 保存默认状态

  ctx.fillStyle = '#09F'       // 在原有配置基础上对颜色做改变
  ctx.fillRect(15,15,120,120); // 使用新的设置绘制一个矩形

  ctx.save();                  // 保存当前状态
  ctx.fillStyle = '#FFF'       // 再次改变颜色配置
  ctx.globalAlpha = 0.5;    
  ctx.fillRect(30,30,90,90);   // 使用新的配置绘制一个矩形

  ctx.restore();               // 重新加载之前的颜色状态
  ctx.fillRect(45,45,60,60);   // 使用上一次的配置绘制一个矩形

  ctx.restore();               // 加载默认颜色配置
  ctx.fillRect(60,60,30,30);   // 使用加载的配置绘制一个矩形
}
移动translate
translate(x, y)

translate方法接受两个参数。x 是左右偏移量,y 是上下偏移量,如右图所示。

旋转 Rotating
rotate(angle)

这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。

缩放 Scaling

scale(x, y)

友情提醒:默认栅格一个单位为一个像素 通过scale 进行单位级别的缩放 ,每个图像所占单位不变

scale方法接受两个参数。x,y 分别是横轴和纵轴的缩放因子,它们都必须是正值。值比 1.0 小表示缩小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。