Canvas
什么是canvas
canvas 是一个可以使用脚本(通常为Javascript) 在其中绘制图形的HTML元素,canvas标签只有两个 非通用属性width和height,canvas的默认大小是300*150,注意:如果你绘制出来的图像是扭曲的,尝试在<canvas>的属性中明确规定宽度和高度,而不是使用css,canvas 元素和普通元素一样,有margin.border,bakcground等样式属性
基本用法
元素引入
<canvas id='cav width='800' height='500'>
浏览器不支持canvas
</canvas>
渲染上下文
canvas本身不具备画图形的功能,一切由canvas内部的CanvasRenderingContext2D对象来做
var canvas=document.getElementById('cav');
var ctx=canvas.getContext('2d');
绘制图形
绘制矩形
HTML中的元素canvas只支持一种原生的图形绘制,矩形,所有其他的图形的绘制,都至少需要生成一条路径,canvas提供了三种绘制矩形的方法
/*
fillRect(x,y,width,height) 绘制一个填充的矩形
clearRect(x,y,width,height) 清除指定矩形区域,让清除部分完全透明
strokeRect(x,y,width,height) 绘制一个矩形的边框
绘制线段
/*
1. 开始路径 ctx.beginPath()
2. 设置起点 ctx.moveTo(x,y)
3. 设置重点(经过点) ctx.lineTo(x,y)
4. 绘制 ctx.stroke()
5. 结束路径 ctx.closePath()
绘制三角形
利用绘制线段的原理绘制三角形
绘制弧形
绘制弧形的参数分别是:弧形圆心x坐标,y坐标,半径,起始角(以三点钟的位置开始),结束角,方向(true表示逆时针,false表示顺时针)ctx.arc(600,200,100,0,Math.PI*2,false)
绘制赛贝尔曲线
二次赛贝尔曲线,三次赛贝尔曲线
/*
1. 开始路径 ctx.begingPath()
2. 设置起点 ctx.moveTo(x,y)
3. 设置贝塞尔曲线
1. 二次赛贝尔曲线
1. ctx.quadraticCurveTo(cpx,cpy,x,y) 参数是控制点x坐标,控制点y坐标,结束点x坐标,结束点y坐标
2. 三次贝塞尔曲线
1. ctx.bezieCurveTo(cpx,cpy,cpx2,cpy2,x,y) 参数是控制点1的x坐标,控制点1的y坐标,控制点2的x坐标,控制点2的y坐标,结束点x坐标,结束点y坐标
4. 绘制 ctx.stroke()
5. 结束路径 ctx.closePath()
canvas 第三方库
实际举例
实例 - 矩形
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
//设置填充颜色
ctx.fillStyle='blue';
//绘制一个矩形
ctx.fillRect(100,100,200,200);
//清空矩形范围
ctx.clearRect(150,150,100,100);
//线宽
ctx.lineWidth=20;
//绘制边框矩形
ctx.strokeRect(75,75,250,250);
实例 - 绘制三角形
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath(); //开始绘画
ctx.moveTo(20,20); //第一个起始点
ctx.lineTo(20,100); //第二个点
ctx.lineTo(70,100); //第三个点
ctx.closePath(); //方法创建从当前点到开始点的路径
ctx.stroke(); //方法在画布上绘制确切的路径
实例 - 填充三角形
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath(); //开始绘画
ctx.moveTo(20,20); //第一个起始点
ctx.lineTo(20,100); //第二个点
ctx.lineTo(70,100); //第三个点
ctx.closePath(); //方法创建从当前点到开始点的路径
ctx.stroke(); //方法在画布上绘制确切的路径
ctx.fillStyle="green"; // 设置填充颜色
ctx.fill(); // 填充绘制的这部分图形
实例 - 圆
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath(); //开始绘画
ctx.arc(100,75,50,0,2*Math.PI); //画圆
ctx.stroke(); //结束绘画
实例 - 二次贝塞尔曲线
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath(); //开始绘画
ctx.moveTo(20,20); //设置起始点
ctx.quadraticCurveTo(20,100,200,20); //绘制二次贝塞尔曲线 参数分别是控制点xy,结束点xy
ctx.stroke(); //结束绘画
实例 - 三次贝塞尔曲线
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath(); //开始绘画
ctx.moveTo(20,20); //设置起始点
ctx.bezierCurveTo(800,250,900,300,950,100); //绘制三次贝塞尔曲线 参数分别是控制点1,xy, 控制点2,xy,结束点xy
ctx.stroke(); //结束绘画
canvas裁剪
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{ margin: 0; padding: 0;}
table{ width: 1000px; height: 500px;box-shadow: 10px 10px 10px black}
table td{ border:1px dotted gray;}
canvas{ top: 0; left: 0; position: absolute;}
</style>
</head>
<body>
<table border="1" cellpadding="0" cellspacing="0">
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
<canvas id="canvas" width="1000" height="500"></canvas>
<script>
//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
//设置填充颜色
ctx.fillStyle='blue';
//使用save方法可以把当前的场景保存下来
ctx.save();
//指定一个裁剪区域
ctx.rect(0,0,200,200);
//根据指定的裁剪区域进行裁剪,使用ctx的clip方法进行裁剪,裁剪的原理:根据指定的裁剪区域进行裁剪后,在canvas上无论画什么图形最终能在裁剪的区域内部才显示;
ctx.clip();
//第一个圆弧
ctx.beginPath();
ctx.arc(200,200,100,0,Math.PI*2,false);
ctx.strokeStyle='deepskyblue';
ctx.lineWidth=10;
ctx.stroke();
ctx.closePath();
//因为使用了clip方法,所以在clip方法之后画的图形如果不在裁剪区域,就都不会显示出来,我们想要正常像是以后画的图形,我们可以利用restore方法来还原裁剪前通过save保存下来的场景即可
ctx.restore();
//第二个圆弧
ctx.beginPath();
ctx.arc(220,220,100,0,Math.PI*2,false);
ctx.strokeStyle='orangered';
ctx.stroke();
ctx.closePath();
</script>
</body>
</html>
你画我猜
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{margin: 0; padding: 0; }
#box{width: 600px; height: 500px; margin: 100px auto; border: 1px solid black; }
#box .control{height: 100px; }
#box .control div{height: 50px; line-height: 50px; }
#box .control .changeColor{padding-left: 15px; }
#box .control .changeColor input{width: 30px; height: 30px; margin: 0 15px; font-size: 0; /*background-color: orange;*/ vertical-align: middle; }
#box .control .changeColor input:nth-of-type(1){background-color: black; }
#box .control .changeColor input:nth-of-type(2){background-color: pink; }
#box .control .changeColor input:nth-of-type(3){background-color: red; }
#box .control .changeColor input:nth-of-type(4){background-color: orange; }
#box .control .changeColor input:nth-of-type(5){background-color: brown; }
#box .control .changeColor input:nth-of-type(6){background-color: purple; }
#box .control .clear{height: 50px; }
#box .control .clear input{width: 100px; height: 50px; margin: 0 15px; font-size: 20px; background-color: #FDF5E5; }
#canvas{background-color: #FFEBCB; }
b{font-size: 20px; }
</style> </head> <body> <div id="box"> <div class="control"> <div class="changeColor"> 选择画笔颜色: <input type="button" value="黑色" /> <input type="button" value="粉色" /> <input type="button" value="红色"/> <input type="button" value="橘色"/> <input type="button" value="棕色" /> <input type="button" value="紫色" /> </div> <div class="clear"> <input type="button" value="清空画布" id="clearAllBtn" /> 当前选中的颜色:<b>黑色</b> <input type="button" value="橡皮擦" id="rubberBtn" /> </div> </div> <canvas id="canvas" width="600" height="400"></canvas> </div>
<script type="text/javascript">
var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
//记录坐标的对象用来给move使用
var pointerObj={}
//切换橡皮檫的状态
var isRubber=false;
//按下事件
canvas.addEventListener('mousedown',function (ev) {
var x=ev.offsetX;
var y=ev.offsetY;
console.log(x+" "+y);
pointerObj.x=x;
pointerObj.y=y;
if(isRubber){
//橡皮擦
rubberFn(x,y);
}else{
//画画
draw(x,y);
}
this.addEventListener('mousemove',move);
this.addEventListener('mouseup',up);
})
function move(e){
var x=e.offsetX;
var y=e.offsetY;
if(isRubber){
rubberFn(x,y);
}
else{
draw(x,y);
}
//移动的时候把之前的点存储起来
pointerObj.x=x;
pointerObj.y=y;
}
function up(){
canvas.removeEventListener('mousemove',move);
// removeEventListener('mouse',up);
}
//画画
function draw(x,y) {
ctx.beginPath();
// ctx.lineWidth=5;
ctx.lineCap='round';
ctx.moveTo(x,y);
ctx.lineTo(pointerObj.x,pointerObj.y);
ctx.stroke();
ctx.closePath();
}
var colorBtns=document.querySelectorAll('.changeColor input');
for(var i=0;i<colorBtns.length;i++){
colorBtns[i].onclick=changeColor;
}
function changeColor() {
ctx.strokeStyle=getComputedStyle(this,null).backgroundColor;
var b=document.querySelector('b');
b.style.color=ctx.strokeStyle;
b.innerHTML=this.value;
//改变橡皮擦的状态
isRubber=false;
}
var clearAllBtn=document.querySelector('#clearAllBtn');
var rubberBtn=document.querySelector('#rubberBtn');
//清空画布
clearAllBtn.onclick=function () {
ctx.clearRect(0,0,canvas.width,canvas.height);
}
//橡皮擦
rubberBtn.onclick=function(){
//开启橡皮擦功能
isRubber=true;
}
function rubberFn(x,y){
ctx.beginPath();
//保存之前先把当前场景保存下来
ctx.save();
//创建裁剪区域
ctx.arc(x,y,20,0,Math.PI*2,false);
//进行裁剪
ctx.clip();
//裁剪之后创建一个清空矩形,但根据裁剪的原理,只有在裁剪区域内部有效
ctx.clearRect(0,0,canvas.width,canvas.height);
//还原之前的场景
ctx.restore();
// ctx.stroke();
ctx.closePath();
}
</script>
</body>
</html>