开发者的画布
<canvas id="tutorial" width="300" height="150">
你的浏览器不支持canvas,请升级你的浏览器
</canvas>
function draw(){
const canvas = document.getElementById('tutorial')
if(!canvas.getContext) return
const ctx = canvas.getContext("2d")
//开始代码
}
基本篇
IE8以下支持canvas
https://github.com/arv/explorercanvas
引入js包
<!--[if lte IE 8]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
绘图环境宽高,效果相同
- canvas.width
- canvas.height
- ctx.canvas.width/ctx.canvas.height
绘图环境状态保存和恢复
- ctx.save();
- ctx.restore();
绘图拷贝和粘贴
let imgData=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData,10,70);
清空全部canvas的像素内容
ctx.clearRect(0, 0, canvas.width, canvas.height);
返回canvas真实坐标x,y
function windowToCanvas(canvas,x=e.clientX,y=e.clientY) {
//通过API获取DOMRect对象
let bbox = canvas.getBoundingClientRect();
return {
//扣除当前对象的left,top
x:x-bbox.left*(canvas.width/bbox.width),
y:y-bbox.top*(canvas.height/bbox.height)
}
}
图片篇
返回包含图片的data URL
- 适合小图片/同步加载/任意浏览器中使用
- 图片的类型默认为
image/png
return "data:" + mimeType + ";base64," + base64Encode(encodedImage);
let fullQuality = canvas.toDataURL('image/jpeg',1);
let lowQuality = canvas.toDataURL('image/webp',0.1);
返回包含图片的Blob
- 适合大图片/异步加载/仅应用内部使用
- 全称: Binary Large Object(File 继承自 Blob)
- 图片的类型默认为
image/png
,分辨率为96 dpi
resultBlob = File.create(encodedImage.data(), encodedImage.size(), encodingMimeType);
function blobCallback(blob){
//创建一个img标签
var newImg = document.createElement("img"),
//以blob对象为基础创建一个url
url = URL.createObjectURL(blob);
console.log(url);
console.log(blob);
//加载后销毁
newImg.onload = function () {
// no longer need to read the blob so it's revoked
URL.revokeObjectURL(url);
};
//img标签属性赋值
newImg.src = url;
//添加为子元素
document.body.appendChild(newImg);
}
canvas.toBlob((blob)=>{blobCallback(blob)}, "image/jpeg", 0.95);
绘制图片
ctx.drawImage(image, x, y,width,height)
图像重复
ctx.createPattern(image, repeat)
repeat 全部重复
repeat-x 沿x轴重复
repeat-y 沿y轴重复
no-repeat 不重复
通用篇
全局透明度
ctx.globalAlpha = 0.5;
设置或返回填充canvas的颜色、渐变、模式
ctx.fillStyle = 'cornflowerblue';
用于设置或返回笔触的颜色、渐变、模式
ctx.strokeStyle = 'blue';
设置填充渐变
gradient = ctx.createLinearGradient(start-x,start-y,end-x,end-y);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.25, 'white');
gradient.addColorStop(0.5, 'purple');
gradient.addColorStop(0.75, 'red');
gradient.addColorStop(1, 'yellow');
ctx.fillStyle=gradient;
旋转/缩放/平移/水平镜像/垂直镜像
ctx.rotate(-Math.PI/8);
ctx.scale(2,2);
ctx.translate(30,30);
ctx.scale(1,-1);
ctx.scale(-1,1);
存为Path2D对象
let rectangle = new Path2D();
rectangle.rect(10, 10, 50, 50);
ctx.stroke(rectangle);
字体篇
设置字体格式
ctx.font = '38pt Arial';
设置文字的内容和位置
ctx.fillText('Hello World', canvas.width / 2 - 150, canvas.height / 2 + 15);
ctx.strokeText("Hello World", canvas.width / 2 - 150, canvas.height / 2 + 15);
检查字体的宽度
ctx.measureText('Hello World').width
线条篇
设置线条宽度
ctx.lineWidth = 0.5;
绘制线条
ctx.beginPath();
// 通过给x+0.5,y+0.5实现抗锯齿,使线条更加平滑
ctx.moveTo(x+0.5,y+0.5);
ctx.lineTo(x+0.5,y+0.5);
ctx.stroke();
闭合路径
ctx.closePath();
设置虚线模式
ctx.setLineDash([5,4,3]);
设置虚线偏移量(动态)
offset+=3.0;
ctx.lineDashOffset=offset;
设置线段端点
ctx.lineCap='butt';
ctx.lineCap='round';
ctx.lineCap='square';
设置线段连接点
ctx.lineJoin='round';
ctx.lineJoin='bevel';
ctx.lineJoin='miter';
判断路径中是否包含监测点
ctx.isPointInPath(x,y)
图形篇
描边->空心
ctx.stroke();
填充->实心
ctx.fill();
绘制圆形
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
/**
* x,y指定圆心
* radius为半径
* startAngle,endAngle为起始点和终点,整圆值为0,Math.PI * 2
* anticlockwise是否顺时针
*/
/**绘制圆弧**/
//方法1
ctx.beginPath();
ctx.arc(100, 100, 50, Math.PI / 4, Math.PI, false);
ctx.stroke();
//方法2
ctx.beginPath();
ctx.moveTo(100, 20);
//起始点(100,20),A点(130,20),B点(130,50)
ctx.arcTo(100+30,20,100+30,20+30,30);
ctx.stroke();
/**二次贝塞尔曲线**/
//控制点120.5,180
//结束点200.5,180
ctx.beginPath();
ctx.moveTo(120.5,130);
ctx.quadraticCurveTo(120.5,180,200.5,180);
ctx.stroke();
/**三次贝塞尔曲线**/
ctx.beginPath();
ctx.moveTo(20,20)
ctx.bezierCurveTo(20,100,200,100,200,20)
ctx.stroke();
/**绘制圆形剪纸**/
ctx.beginPath();
//利用非零环绕规则:两个图形绘画方向相反,则计算差值
ctx.arc(300, 190, 150, 0, Math.PI * 2, false);
ctx.arc(300, 190, 120, 0, Math.PI * 2, true);
ctx.fill();
设置外角类型
ctx.lineJoin='round'
绘制矩形
ctx.strokeRect(x, y, width, height)
ctx.fillRect(x, y, width, height)
/**绘制阴影矩形**/
//禁用阴影:shadowColor:undefine;
ctx.shadowColor="rgba(0,0,0,0.75)";
//阴影水平偏移
ctx.shadowOffsetX=5;
//阴影垂直偏移
ctx.shadowOffsetY=5;
//越大越模糊
ctx.shadowBlur=5;
ctx.strokeRect(x, y, width, height)
ctx.fillRect(x, y, width, height)
/**逆时针绘制矩形**/
function rect(x,y,w,h,direction) {
if(direction){
ctx.moveTo(x,y);
ctx.lineTo(x,y+h);
ctx.lineTo(x+w,y+h);
ctx.lineTo(x+w,y);
ctx.closePath();
}else{
ctx.moveTo(x,y);
ctx.lineTo(x + w, y);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.closePath();
}
}
事件篇
鼠标事件
canvas.addEventListener('mousedown',function (event){})
canvas.addEventListener('mousemove',function (event){})
canvas.addEventListener('mouseup',function (event){})
canvas.addEventListener('mouseout',function (event){})
window.addEventListener('keydown',function (event){},true);
window.addEventListener('keypress',function (event){},true);
window.addEventListener('keyup',function (event){},true);
总结篇
canvas 跟 img 标签相比,唯一的不同就是它并没有 src 和 alt 属性。
canvas 只有两个属性 width 和 height,默认值为300*150。
canvas基础:
对于canvas来说,左上角的坐标是(0,0)
单线条:
moveTo => 画笔定位(必须,否则 lineTo 无效)
lineTo =>路径运动
lineWidth =>线条宽度
lineCap =>线条端点形状 => 获值 round|square|butt
lineJoin =>线条交界处外角类型 => miter|round|bevelstroke =>描边方法
strokeStyle =>设置颜色 => 获值形式 color|gradient|pattern
多线条:
- beginPath =>告诉 canvas 我们要绘制一条全新路径,防止之前效果被污染
- 矩形基础:
- fillRect =>绘制填充矩形
- strokeRect =>绘制边框矩形
- clearRect =>清除矩形区域
- 矩形基础:
- beginPath =>告诉 canvas 我们要绘制一条全新路径,防止之前效果被污染