目录
一、基本图形绘制
1.1、矩形绘制
1.2、圆弧绘制
1.3、线段绘制
1.4、贝尔赛曲线绘制气泡框和爱心
1.5、画布清除
二、样式控制
2.1、颜色设置
2.2、线性渐变与径向渐变
2.3、pattern印章填充样式
2.4、线段和虚线样式
2.5、绘制图片、视频添加水印
2.6、文字绘制与对齐
2.7、旋转、位移、缩放
三、高级应用
3.1、合成图像模式实现刮刮卡
3.2、裁剪路径
3.3、状态的保存与恢复
文档:在mdn搜canvas: https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API
画布创建与上下文对象
1.找到画布
var context = document.getElementById("MyCanvas");
2.获取画笔,上下文对象
var ctx = context.getContext("2d");
填充绘制矩形fillRect(位置x,位置y,宽度,高度)
ctx.fillRect(100, 200, 300, 300)
路径绘制矩形strokeRect(位置x,位置y,宽度,高度)
ctx.strokeRect(100, 50, 200, 80)
绘制圆弧arc(圆心x,圆心y,半径,开始角度,结束角度,逆时针or顺时针(默认顺时针false))+stroke()
备注:Math.PI / 2==>90度 Math.PI * 2==>360度
ctx.arc(300, 200, 50, 0, Math.PI / 2, true);
ctx.stroke()
扩展:纯色笑脸
左边为基础班,右边为改进版,其中moveTo()可以绘制一条不连续的路径。
lineTo(终点的x轴坐标, 终点的y轴坐标)
ctx.beginPath();
ctx.moveTo(200, 300)
// 曲线从moveTo()指定的点开始:(200, 300)。控制点位于 (150, 300)。曲线在 (150, 200) 处结束。
ctx.quadraticCurveTo(150, 300, 150, 200)
ctx.quadraticCurveTo(150, 100, 300, 100)
ctx.quadraticCurveTo(450, 100, 450, 200)
ctx.quadraticCurveTo(450, 300, 250, 300)
ctx.quadraticCurveTo(250, 350, 150, 350)
ctx.quadraticCurveTo(200, 350, 200, 300)
ctx.stroke()
ctx.closePath();
ctx.beginPath();
ctx.moveTo(300, 200);
ctx.bezierCurveTo(350, 150, 400, 200, 300, 250);
ctx.bezierCurveTo(200, 200, 250, 150, 300, 200);
ctx.stroke()
ctx.closePath();
//========================封装路径:Path2D=============
var heartPath=new Path2D()
heartPath.moveTo(300, 200);
heartPath.bezierCurveTo(350, 150, 400, 200, 300, 250);
heartPath.bezierCurveTo(200, 200, 250, 150, 300, 200);
ctx.stroke(heartPath)
ctx.fill(heartPath);//黑色填充
ctx.clearRect(0, 0, context.clientWidth, context.clientHeight)//一键清除
扩展:渐渐消失
let height = 0;
let t1 = setInterval(() => {
height++;
ctx.clearRect(0, 0, context.clientWidth, height);
if (height > context.clientHeight) {
clearInterval(t1)
}
}, 10)
补充:ctx.beginPath(); ctx.closePath();//完成路径的分段
绘制效果展示:
ctx.strokeStyle = 'red';//颜色设置
ctx.fillStyle = "green";//填充的颜色设置
ctx.fill(heartPath);//填充设置
线性渐变:createLinearGradient
径向渐变:createRadialGradient
//==============线性渐变=================
let index = 0;
function render() {
ctx.clearRect(0, 0, 600, 400);
index += 0.01;
if (index > 1) {
index = 0
}
let linearGradient = ctx.createLinearGradient(100, 200, 400, 500)
linearGradient.addColorStop(0, 'red')
linearGradient.addColorStop(index, 'pink')
linearGradient.addColorStop(1, 'blue')
ctx.fillStyle = linearGradient
ctx.fillRect(100, 200, 300, 300)
requestAnimationFrame(render)
}
requestAnimationFrame(render)
//==============径向渐变模拟3D球=================
let radiaGradient = ctx.createRadialGradient(250, 150, 10, 300, 200, 100)
radiaGradient.addColorStop(0, 'pink')
radiaGradient.addColorStop(1, 'red')
ctx.fillStyle = radiaGradient;
ctx.arc(300, 200, 100, 0, Math.PI * 2)
ctx.fill()
createPattern创建图片,放置原理和css一样
var img = new Image()
img.src = './pat.png'
img.onload=function(){
// createPattern的重复方式repeat,no-repeat,repeat-x,repeat-y
var pattern=ctx.createPattern(img,'no-repeat')
ctx.fillStyle=pattern
ctx.fillRect(0,0,600,400)
}
lineCap(线条端点样式):butt平齐 round半圆 square正方形
lineJoin(设置2个线段连接处的样式):mitter外侧相连的角 round角磨圆 bevel
虚线:以数组形式setLineDash
let index = 0
function render() {
ctx.clearRect(0, 0, 600, 400)
index++
if (index > 40) {
index = 0
}
ctx.moveTo(150, 150)
ctx.lineTo(300, 200)
ctx.lineTo(450, 150)
ctx.lineWidth = 10
// 线条端点样式:butt平齐 round半圆 square正方形
ctx.lineCap = 'square'
// 设置2个线段连接处的样式,mitter外侧相连的角 round角磨圆 bevel
ctx.lineJoin = 'mitter'
// 对斜接面进行限制
// ctx.miterLimit = 5
ctx.setLineDash([40, 20])
ctx.lineDashOffset = index
ctx.stroke()
requestAnimationFrame(render)
}
render()
第一种:基于画布的坐标,不管原图大小;
第二种:基于画布的坐标,可设置要展示的原图大小;
第三种:基于画布的坐标,在原图的大小上进行截取,并展示在画布上;
drawImage(image, dx, dy);
drawImage(image, dx, dy, dWidth, dHeight);
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
let img=new Image()
img.src='./bigs.png'
img.onload=function(){
ctx.drawImage(img,0,0)
ctx.drawImage(img,0,0,600,400)
// 原图片大小:1200x700
ctx.drawImage(img,400,230,400,230,0,0,600,400)
}
给视频添加水印,无非就是同时将视频与图片同时放在画布上,都是用drawImage方法渲染的
填充文字: fillText(文本,起点x,起点y,文字最大宽度)
气泡文字: strokeText(文本,起点x,起点y,文字最大宽度)
ctx.strokeStyle = "pink"
ctx.font = "100px Microsoft YaHei"
// 填充文字
// fillText(文本,起点x,起点y,文字最大宽度)
ctx.fillText("Hello world!", 200, 300, 400)
// 文本对齐选项(textAlign,start,end,left,right,center)
ctx.textAlign = 'center'
// 文本基线对齐(textBaseline,middle,top,bottom,alphabetic)
ctx.textBaseline = 'middle'
ctx.font = "50px serif";
ctx.strokeText("Hello world", 300, 200);
ctx.arc(300, 200, 5, 0, 2 * Math.PI)
ctx.fill()
// 预测文本宽度
let text=ctx.measureText("你CDC")
console.log(text);//width: 125
rotate旋转(角度)、translate位移、scale缩放(倍数)
// scale缩放(倍数)
ctx.fillRect(0, 0, 50, 50)
// translate位移
ctx.translate(100, 100)
ctx.scale(5, 2)
ctx.fillRect(0, 0, 50, 50)
// rotate旋转
ctx.rotate(Math.PI / 6)
ctx.fillRect(0, 0, 500, 50)
谢谢惠顾
clip(路径值)
var heartPath = new Path2D()
heartPath.moveTo(300, 200);
heartPath.bezierCurveTo(350, 150, 400, 200, 300, 250);
heartPath.bezierCurveTo(200, 200, 250, 150, 300, 200);
ctx.clip(heartPath)
ctx.fill(heartPath)
let img = new Image()
img.src = './bigs.png'
img.onload = function () {
ctx.drawImage(img, 0, 0, 600, 400)
ctx.lineWidth = 10
ctx.stroke(heartPath)
}
save():保存 restore():恢复
这个操作就像“栈”一样,最后一次保存的是绿色,所以先恢复的是绿色
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 50, 50)
ctx.save();//红色保存
ctx.fillStyle = 'green'
ctx.fillRect(50, 50, 50, 50)
ctx.save();//绿色保存
ctx.fillStyle = 'blue'
ctx.fillRect(100, 100, 50, 50)
ctx.restore();//绿色恢复
ctx.fillRect(150,150, 50, 50)