前端知识储备之Canvas篇

前言

前端Canvas开发应该属于图形开发技术了,不少前端小伙伴在Canvas开发上都有些困难。

其实我想说,会Canvas开发的更难,实现些功能想破头,难呀!整理下之前写Canvas用到的一些基础操作,方便后面查阅。

基础概念

Canvas元素

和其他普通元素一样,可以直接插入文档,也可以通过JavaScript创建欻

<canvas id="canvas" width="500" height="400">
  Sorry, canvas tag is not supported.
</canvas>
const canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.insertBefore(canvas, document.body.firstChild);

画布

<canvas> 提供了绘制2D 的图形接口和上下文。 了解画布的概念有助于解决类似图片模糊的问题,处理精度。

canvas元素大小

直接给<canvas>元素设置样式只会改变<canvas>在DOM里面的大小,而不会改变像素点的多少。

document.getElemntById("canvas").style.width=300
document.getElemntById("canvas").style.height=400

使用这种方式来进行修改,最直观的感受就是会导致canvas里面的内容拉伸变形。

const canvas = document.getElemntById('canvas');
// 既可以读取也可以修改该元素的大小
canvas.style.width = 100;
canvas.style.height = 100;

canvas画布大小

<canvas>绘图画布的大小。当他的style大小固定,画布里面的尺寸越大,精度越高。举例来讲,比如你展示一幅3440x1660的图片在300x400<canvas>元素上时,出现模糊的时,提高画布的大小则可以改善模糊的问题。

<canvas id="canvas" width="300" height="500"></canvas>
const canvas = document.getElementById("canvas")

// 当然你也可以直接在这儿赋值进行改变,应该是这样不行用下面的方法
console.log(canvas.width); // 300
console.log(canvas.height); // 500

通过 <canvas width="500" height="300" /> 在元素上设置widthheight 时,他同时设置了该元素的元素大小画布大小

document.getElemntById("canvas").setAttribute("width", 300)
document.getElemntById("canvas").setAttribute("height", 500)

上下文

获取
const canvas = document.getElementById('canvasid');
const context = canvas.getContext('2d');

基础操作

直线

// 填充三角形
ctx.beginPath();
ctx.moveTo(25, 25);
ctx.lineTo(105, 25);
ctx.lineTo(25, 105);
ctx.fill(); // 自动闭合路径

// 描边三角形
ctx.beginPath();
ctx.moveTo(125, 25);
ctx.lineTo(125, 105);
ctx.lineTo(205, 25);
ctx.closePath(); // 手动闭合路径
ctx.stroke();

圆和弧线 参考

arc

arc(x, y, radius, startAngle, endAngle, anticlockwise);
  • x 圆弧中心(圆心)的x轴坐标
  • y 圆弧中心(圆心)的y轴坐标
  • r 圆弧半径
  • startAngle 圆弧的起始点,x轴方向开始计算,单位以弧度表示
  • endAngle 圆弧的重点,单位以弧度表示
  • anticlockwise 可选Boolean值,如果为true,逆时针绘制圆弧,反之顺时针绘制。

示例

HTML
<canvas id="canvas"></canvas>
JavaScript
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.arc(75, 75, 50, 0, 2 * Math.PI);
ctx.stroke();

其中到startAngle为0 ,endAngle2 * Math.PI时,圆弧封闭变成一个圆形。

不同形状展示
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Draw shapes
for (i=0;i<4;i++){
  for(j=0;j<3;j++){
    ctx.beginPath();
    var x          = 25+j*50;               // x coordinate
    var y          = 25+i*50;               // y coordinate
    var radius     = 20;                    // Arc radius
    var startAngle = 0;                     // Starting point on circle
    var endAngle   = Math.PI+(Math.PI*j)/2; // End point on circle
    var clockwise  = i%2==0 ? false : true; // clockwise or anticlockwise

    ctx.arc(x,y,radius,startAngle,endAngle, clockwise);

    if (i>1){
      ctx.fill();
    } else {
      ctx.stroke();
    }
  }
}
运行结果

arcTo

arcTo(x1, y1, x2, y2, radius);
  • x1第一个控制点的 x 轴坐标。
  • y1第一个控制点的 y 轴坐标。
  • x2第二个控制点的 x 轴坐标。
  • y2第二个控制点的 y 轴坐标。
示例

这是一段绘制圆弧的简单的代码片段。 基础点是蓝色的,两个控制点是红色的。

假设两个红色方块儿之间的虚线是直线B,红色方块儿和蓝色方块儿的直线为A。

  • 直线A与直线B是arcTo所画圆的切线
  • 半径为radius
  • 靠下的红色方块儿为(x1,y1)坐标,靠上的红色方块儿为(x2,y2)的坐标
  • 蓝色方块儿坐标由(x1,y2)所确定。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.setLineDash([])
ctx.beginPath();
ctx.moveTo(150, 20);
ctx.arcTo(150,100,50,20,30);
ctx.stroke();

ctx.fillStyle = 'blue';
// base point
ctx.fillRect(150, 20, 10, 10);

ctx.fillStyle = 'red';
// control point one
ctx.fillRect(150, 100, 10, 10);
// control point two
ctx.fillRect(50, 20, 10, 10);
//
ctx.setLineDash([5,5])
ctx.moveTo(150, 20);
ctx.lineTo(150,100);
ctx.lineTo(50, 20);
ctx.stroke();
ctx.beginPath();
ctx.arc(120,38,30,0,2*Math.PI);
ctx.stroke();

矩形

void ctx.rect(x, y, width, height);

示例

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.rect(10, 10, 100, 100);
ctx.fill();

绘制带边框的矩形

strokeRect(x, y, width, height);

绘制填充矩形

fillRect(x, y, width, height);

清理矩形区域

clearRect(x, y, width, height);

画布也是矩形区域,所以,也可以用来清理画布。

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);

图像

基础概念

图像加载

window.onload = () => {
	let canvas = document.getElementById('demo')
	let ctx = canvas.getContext('2d')
	let image = new Image()
	image.src = './imgs/otome1.png'
	image.onload = () => {
	 ctx.fillStyle = ctx.createPattern(image, 'repeat') // 性质相当于css中的background-image
	ctx.fillRect(0, 0, 1000, 550) // 最终渲染的位置
	}
}

一般是通过Image标签进行加载,网络链接也可以通过一样的方式进行加载。 当然,也可以加载svg的图像,不过最终被转换后的图像都是8bit深度的图像。即 0~255深度的图像

对于16bit深度的图像来讲,虽然可以加载,但是在里面的表示仍然是8bit的内容。

drawImage方法

void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
drawImage
  • sx 可选:需要绘制到目标上下文中的,image的矩形(裁剪)选择框的左上角 X 轴坐标。
  • sy 可选:需要绘制到目标上下文中的,image的矩形(裁剪)选择框的左上角 Y 轴坐标。
  • sWidth 可选: 需要绘制到目标上下文中的,image的矩形(裁剪)选择框的宽度。如果不说明,整个矩形(裁剪)从坐标的sxsy开始,到image的右下角结束。
  • sHeight 可选:需要绘制到目标上下文中的,image的矩形(裁剪)选择框的高度。
  • 其他

示例

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image = document.getElementById('source');

ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);

实战:弹力小球

HTML

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>弹力小球</title>
</head>
<body>
<canvas id="canvas" style="border: 1px solid #aaa; display: block; margin: 50px auto;"></canvas>
</body>
</html>

JavaScript

var ball = { x: 512, y: 100, r: 20, g: 2, vx: -4, vy: 0, color: "#005588"}
var peg = { x: 100, y: 50, r: 10, color: "#eeeeee" }
window.onload = function () {
	var canvas = document.getElementById("canvas");

	canvas.width = 1024;
	canvas.height = 768;

	var context = canvas.getContext("2d")

	setInterval(function () {
		render(context);
		update(context);
	}, 50)
}

function drawPeg(ctx) {
	ctx.beginPath();
	ctx.fillStyle = peg.color;
	ctx.arc(peg.x, peg.y, peg.r, 0, 2 * Math.PI);
	ctx.closePath();
	ctx.fill();
}

function update(context) {
	ball.x += ball.vx;
	ball.y += ball.vy;
	ball.vy += ball.g;
	if (ball.y > context.canvas.height) {
		ball.vy = -ball.vy * 0.75
	}
}

function render(ctx) {
	ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
	ctx.fillStyle = ball.color;
	ctx.beginPath();
	ctx.arc(ball.x, ball.y, ball.r, 0, 2 * Math.PI);
	ctx.closePath();
	ctx.fill();
	drawPeg(ctx);
}

参考文献

暂无评论

发表评论

您的电子邮件地址不会被公开,必填项已用*标注。

相关推荐