注: 添加语法提示
/** @type {HTMLCanvasElement} */,放在获取canvas节点之前
获取canvas节点上下文
<canvas id="canvas" width="500" height="500"></canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
1.绘制基本图形
// x,y是起始点坐标,width,height是绘制的矩形长宽
1.填充的矩形
fillRect(x,y,width,height)
2.矩形边框
strokeRect(x,y,width,height)
3.清除指定矩形区域:
strokeRect(x,y,width,height)
例子:ctx.fillRect(25, 25, 100, 100);
2.绘制路径
- 首先路径需要起始点
- 然后使用绘图命令画出路径
- 封闭路径
- 路径一旦生成,只能通过描边或者填充来渲染图形
常用函数
beginPath():新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径
closePath():闭合路径之后图形绘制命令又重新指向到上下文中
stroke():通过线条来绘制图形的轮廓
fill():通过填充路径的内容区域生成实心的图形
moveTo(x, y):移动笔触
lineTo(下, y):绘制直线
绘制描边三角形
ctx.beginPath()
ctx.fillStyle = '#007acc'
ctx.moveTo(150,150)
ctx.lineTo(180,130)
ctx.lineTo(120,130)
ctx.closePath()
ctx.stroke()
绘制圆弧:arc(x, y, radius, startAngle, endAngle, anticlockwise)
x,y:圆心位置
radius:圆半径
startAngle, endAngle:起点终点位置(弧度制)
anticlockwise:绘制方向(默认是顺时针,Boolean)
// 绘制扇形
ctx.beginPath()
ctx.fillStyle = '#007acc'
ctx.moveTo(50, 50)
ctx.arc(50, 50, 50, 0, 0.8 * Math.PI)
ctx.fill()
绘制色值
for(let i = 1;i<6;i++){
for(let j = 1;j<6;j++){
ctx.fillStyle = `rgba(${i*22.5},${j*22.5},${(i+j)*22.5},.7)`
ctx.fillRect(i*20,j*20,20,20)
}
}
3.样式
ctx.lineWidth = 20 // number
// 线段两端的样式
ctx.lineCap = 'butt' // butt(默认):线段末端以方形结束,round:圆形,square:方形结束
// 拐角样式
ctx.lineJoin = 'miter' // bevel:去除拐角的尖角,round:圆弧型,miter:默认
// 设置虚线
ctx.setLineDash([4, 2])// 4:实线的长度,2两条线的距离,setLineDash接收一个数组
ctx.lineDashOffset = -offset // 改变正负可以改变虚线方向
// 测试
let offset = 16
function draw() {
ctx.clearRect(0, 0, 500, 500)
ctx.setLineDash([4, 2])// 4:实线的长度,2两条线的距离
ctx.lineDashOffset = -offset // 改变正负可以改变虚线方向
ctx.strokeRect(10, 10, 100, 100)
}
function march() {
offset--
if (offset < 0) {
offset = 16
}
draw();
setTimeout(march, 20)
}
march()
// 渐变
createLinearGradient(x1, y1, x2, y2):渐变起点(x1,y1)终点(x2,y2)
createRadialGradient(x1, y1, r1, x2, y2, r2):前三个点定义一个以(x1,y1)为原点,r1为半径,后面三个参数定义另一个以(x2,y2)为原点,半径为r2的圆
注: 半径为r2的圆的圆心一定要在r1圆内,并且r2的圆一定要包裹r1的圆,否则渐变会变的很奇怪
// 阴影
shadowOffsetX/shadowOffsetY=float,阴影偏移的的距离,右/下,为负则是:左/上
shadowBlur=float, 阴影的模糊程度
shadowColor=float, 阴影的颜色效果
// 填充
fill()
ctx.beginPath('evenodd')// nonzero:不填充;evenodd:
ctx.arc(200,200,30,0,Math.PI)
ctx.arc(200,200,50,0,Math.PI)
ctx.fill('evenodd')
4.字体
// 文本样式
font = value 使用与cssfont属性相同的语法,默认字体是10px sans-serif(参考链接:https://www.runoob.com/tags/canvas-font.html)
textAlign=value 文本对齐。可选值:start,end,left,right,center,默认值:start
textBaseline=value 基线对齐选项。可选值:top,hanging,middle,alphabetic,ideographic,bottom,默认值:alphabetic
direction=value 文本方向。可选值:ltr,rtl,inherit,默认值:inherit
ctx.font = '40px arial italic '
ctx.textAlign = 'start'
ctx.textBaseline = 'alphabetic'
ctx.direction = 'ltr'
ctx.strokeStyle = 'red'
ctx.strokeText('这是文本内容',100,50)
5.变形Transformations
- 状态的保存和恢复:
Saving and restoring state
a.save():保存画布的状态
b.restore():save和restore方法是用来保存和恢复canvas状态的,都没有参数,Canvas的状态就是当前画面应用的所有样式和变形的一个快照
c.Canvas中,适用save()方法来保存状态,适用restore()方法来恢复状态;canvas状态是以栈的方式来保存:每次调用save()方法,就会把栈顶的方法取出来,并把画布恢复到这个状态,用这个状态绘图。 - 移动Translating
// translate(x,y),x是左右偏移量;y是上下偏移量
// 代码
for (let i = 1; i < 5; i++) {
for (let j = 1; j < 6; j++) {
ctx.save()
ctx.fillStyle = `rgb(${i*50},${j*50},${i*j*10})`
ctx.translate(10+j*50,10+i*50)
ctx.fillRect(0,0,25,25)
ctx.fill()
ctx.restore()
}
}
- 旋转 Rotating
// rotate方法,它用于以原点为中心旋转canvas
// ratate(angle):angle是旋转的角度,顺时针方向,以弧度为单位的值
// 代码
ctx.translate(150, 200)// 旋转中心
for(let i=1;i <7;i++) {
ctx.rotate(Math.PI*2/6)
ctx.beginPath()
ctx.arc(50,50,25,0,Math.PI*2) // 前两个参数是相对旋转中心的位置
ctx.fill()
}
- 缩放 Scalling
// scale(x,y) 两个参数都是实数,可以为负值,x为水平缩放因子,y为垂直缩放因子,如果比1小会缩小,比1大会放大,默认为1
// 注:缩放后面所有数值
// 代码
ctx.fillText('1',20,13)
for(let i=1;i<5;i++){
ctx.save()
ctx.translate(100-i*20,100-i*20)
ctx.scale(i*1,i*1)
ctx.strokeRect(0,0,40,40)
ctx.stroke()
ctx.restore()
}
ctx.fillText('2',200,13)
for(let i=1;i<5;i++){
ctx.save()
ctx.translate(200,20)
ctx.scale(i,i)
ctx.strokeRect(0,0,40,40)
ctx.stroke()
ctx.restore()
}
ctx.fillText('3',20,193)
for(let i=1;i<5;i++){
ctx.save()
ctx.translate(i*20,200+i*20-20)
ctx.scale(2*i,2*i)
ctx.lineWidth = 2/(2*i) // 使线条的宽度保持一致
ctx.strokeRect(0,0,20,20)
ctx.stroke()
ctx.restore()
}
- 变形Transforms
transform(a,b,c,d,e,f)
a:水平方向的缩放
b:竖直方向的倾斜偏移
c:水平方向的倾斜偏移
d:竖直方向的缩放
e:水平方向的移动
f:竖直方向的移动
// 代码
ctx.fillStyle = 'rgb(231, 212, 233)'
ctx.fillRect(0, 0, 150, 150)
ctx.fillStyle = `rgb(0,0,0)`
ctx.transform(2, 2, 0.3, 1, 20, 20)
ctx.fillRect(0,0, 150, 150)
6.合成
- 制作刮刮卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
#thanks {
width: 500px;
height: 500px;
position: absolute;
z-index: -1;
font-size: 50px;
color: red;
line-height: 500px;
text-align: center;
}
#canvas {
/* background-color: aliceblue; */
border: 1px solid #000
}
</style>
<body>
<div id="thanks"></div>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<script type="text/javascript">
/**
* @type {HTMLCanvasElement}
*/
const ctx = document.getElementById('canvas').getContext('2d')
let img = new Image()
img.src = './story2.png'
img.onload = function () {
ctx.drawImage(img, 0, 0, 600, 400)
}
var isDraw = false
canvas.onmousedown = function () {
isDraw = true
}
canvas.onmouseup = function () {
isDraw = false
}
canvas.onmousemove = function (e) {
if (isDraw) {
var x = e.pageX
var y = e.pageY
ctx.globalCompositeOperation = 'destination-out'
ctx.beginPath()
ctx.arc(x, y, 20, 0, 2 * Math.PI)
ctx.fill()
}
}
let random = ~~(Math.random() * 10);
var ggk = document.querySelector('#thanks')
random < 5 ? ggk.innerHTML = '恭喜你中奖了' + random : ggk.innerHTML = '谢谢惠顾' + random
</script>
</html>
总结
- 以上这些内容基本都是从MDN上面自学的,如有不对的地方欢迎指正;这里一下附上MDN的链接: developer.mozilla.org/zh-CN/docs/…
- 最后的一个刮刮卡是参考掘金一位大佬在掘金发的文章,现在找不到了,如有侵权马上删除;