目录
绘制图像_缩放图像
绘制图像_图像切片
Canvas状态的保存和恢复
图形变形_平移
图形变形_旋转
图形变形_缩放
图形变形_变形
裁切路径
动画_时钟
动画_运动的小球
引入外部SVG
绘制图像_缩放图像
ctx.drawImage(img, x, y, width, height)
img :图像数据,可以是 <img> 元素,也可以是 <canvas> 元素
x :在目标 canvas 里放置图像的左上角的横坐标
y :在目标 canvas 里放置图像的左上角的纵坐标
width :图像在画布上的宽度
height :图像在画布上的高度
function draw(imgUrl, x, y) {
// 定义img
var img = new Image()
img.src = imgUrl
// 图片加载完后绘制图像
img.onload = function () {
// 绘制图像
ctx.drawImage(img, x, y, 200, 200)
}
}
// 通过遍历绘制九张图片铺满画布
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
draw('./assets/4.jpg', i * 200, j * 200)
}
}
绘制图像_图像切片
ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
img :图像数据,可以是 <img> 元素,也可以是 <canvas> 元素·
sx :图像源被切的开始位置的横坐标
sy :图像源被切的开始位置的纵坐标
sWidth :图像源被切的宽度
sHeight :图像源被切的高度
dx :图像在画布的开始位置的横坐标
dy :图像在画布的开始位置的纵坐标
dWidth :图像在画布的宽度
dHeight :图像在画布的高度
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。
剩余的8个参数前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
// 定义图片
var img = new Image()
img.src = './assets/2.jpg'
// 图片加载完成后绘制图像
img.onload = function () {
// 绘制图像
// 从源图片(50,50)的位置开始切片,切片大小为50*50
//切片在画布上的起始位置为(100,100),切片在画布上最终画出 //来的大小为200*200
ctx.drawImage(img, 50, 50, 50,50, 100, 100, 200, 200)
}
//绘制矩形
ctx.lineWidth = 30
ctx.strokeStyle = 'yellow'
ctx.strokeRect(100, 100, 200, 200)
Canvas状态的保存和恢复
1、 ctx.save() :将画布的当前状态保存起来,相当于在内存之中产生一个样式快照
一个绘画状态包括:
1.1、当前的一些样式: strokeStyle , fillStyle , lineWidth , lineCap , lineJoin ,lineDashOffset , shadowOffsetX , shadowOffsetY , shadowBlur , shadowColor ,
font , textAlign , textBaseline 等
1.2、当前应用的变形(即移动,旋转和缩放)
1.3、当前的裁切路径(clipping path)
2、ctx.restore() :将画布的样式恢复到之前保存的快照
ctx.fillRect(0, 0, 300, 300)//绘制矩形
ctx.save()//保存当前状态
ctx.fillStyle = 'green'//设置填充色
ctx.fillRect(30, 30, 240,240)//绘制矩形
ctx.save()//保存当前状态
ctx.fillStyle='#fff'//设置填充色
ctx.fillRect(60,60,180,180)//绘制矩形
ctx.restore()//恢复上一个状态
ctx.fillRect(90,90,120,120)
ctx.restore()//恢复上上一个状态
ctx.fillRect(120,120,60,60)
图形变形_平移
ctx.translate(x, y)
x :是左右偏移量, x>0 ,向右平移, x<0 ,向左平移
y :是上下偏移量, y>0 ,向下平移, y<0 ,向上平移
for (var i = 0; i < 2; i++) {
for (var j = 0; j < 2; j++) {
ctx.restore()//恢复上一次状态
ctx.save()//保存上一次状态
//产生平移
ctx.translate(50 * i + 10, 50 * j + 10)
//设置填充颜色
ctx.fillStyle = ['red', 'green'][j]
//绘制小矩形
ctx.fillRect(0, 0, 25, 25)
}
}
图形变形_旋转
ctx.rotate(angle) :以 原点为中心 旋转 坐标系
angle :旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
// 平移
ctx.translate(100, 100)
for (var i = 1; i < 7; i++) {
// 旋转坐标系
ctx.rotate((Math.PI*2)/6)
// 绘制圆形
ctx.beginPath()
ctx.fillStyle = 'red'
ctx.arc(0, 30, 5, 0, Math.PI * 2)
ctx.fill()
}
图形变形_缩放
ctx.scale(x,y) :用于缩放图像。
x : x 轴方向的缩放因子
y : y 轴方向的缩放因子
默认情况下,一个单位就是一个像素,缩放因子可以缩放单位,比如缩放因子 0.5 表示将大小缩小为原来的50%,缩放因子 10 表示放大十倍。
如果缩放因子为1,就表示图像没有任何缩放。
如果为-1,则表示方向翻转。 ctx.scale(-1, 1) 为水平翻转, ctx.scale(1, -1) 表示垂直翻转。
ctx.translate(100, 100)//平移
ctx.save()//保存当前状态
// 绘制第一个矩形
ctx.fillStyle = 'green'
ctx.fillRect(0, 20, 100, 100)
//绘制X轴所在的一条直线
ctx.beginPath()
ctx.moveTo(0,0)
ctx.lineTo(500,0)
ctx.stroke()
// 绘制第二个矩形
ctx.scale(0.5, 0.5)//缩放网格
ctx.fillStyle = 'yellow'
ctx.fillRect(0, 40, 100, 100)
ctx.restore()//恢复之前的状态
ctx.scale(1, -1)//垂直方向翻转
// 绘制第一个矩形
ctx.fillStyle = 'green'
ctx.fillRect(0, 20, 100, 100)
// 绘制第二个矩形
ctx.scale(0.5, 0.5)//缩放网格
ctx.fillStyle = 'yellow'
ctx.fillRect(0, 40, 100, 100)
图形变形_变形
1、 ctx.transform(a, b, c, d, e, f) :接受变换矩阵的六个元素作为参数,完成缩放、平移和倾斜等变形。
a :x轴方向缩放
b :x轴方向倾斜
c :y轴方向倾斜
d :y轴方向缩放
e :x轴方向平移
f :y轴方向平移
2、默认状态: transform(1,0,0,1,0,0)
变换矩阵: a c e
[ b d f ]
0 0 1
点 (x,y) 经过矩阵变换后得到 (x',y')
1 、x' = ax + cy + e;
2 、y' = bx + dy + f;
ctx.setTransform(a, b, c, d, e, f) :重置并创建新的变换矩阵
ctx.resetTransform() :重置当前变形为单位矩阵,它和调用以下语句是一样的:
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillRect(0, 0, 100, 100);//绘制参考矩形
ctx.fillStyle='green'
// ctx1.transform(0.5, 0, 0, 0.5, 0, 0);//缩放
// ctx1.transform(1, 0, 0, 1, 50, 50);//平移
// ctx1.transform(1, 1, 0, 1, 0, 0);//倾斜
ctx.transform(0.5, 1, 0, 0.5, 50, 50);//综合变形
ctx.fillRect(0, 100, 100, 100);//绘制变形后的矩形
ctx.setTransform(0.5, 0, 0, 0.5, 0, 0);//重置并创建新的变化矩阵
ctx.fillRect(0, 400, 100, 100);//绘制重置并创建新变形后的矩形
裁切路径
ctx.clip() :将构建的路径转换为裁剪路径,裁切路径确定好之后,再绘制图形,裁切路径内的图形可以显示,裁切路径外的图形不显示。
默认情况下,canvas 有一个与它自身一样大的裁切路径(也就是没有裁切效果)。
提示:
裁切路径也属于canvas状态
var ctx = document.getElementById('canvas').getContext('2d')
ctx.save()//保存状态
ctx.fillRect(0, 0, 200, 200)//绘制一个跟画布一样大小的黑色矩形
ctx.arc(100, 100, 50, 0, 2 * Math.PI)//定义个圆形的路径
ctx.clip()
// ctx.restore()
// 绘制一个跟画布一样大小的黄色矩形
ctx.fillStyle = 'yellow'
ctx.fillRect(0, 0, 200, 200)
动画_时钟
<canvas width="150" height="150" id="canvas"></canvas>
<script>
var ctx = document.getElementById('canvas').getContext('2d')
ctx.translate(75, 75)//移动原点到画布的正中心
ctx.rotate(-Math.PI / 2)//逆时针旋转九十度
ctx.lineCap = 'round'//设置线条末端样式
ctx.save()
clock()
function clock() {
ctx.clearRect(-75, -75, 150, 150)
// 绘制一个跟画布一样大小的粉色矩形
ctx.fillStyle = 'pink'
ctx.fillRect(-75, -75, 150, 150)
// 获取当前时间
var now = new Date()
// 绘制小时的刻度
ctx.lineWidth = 3//设置线条宽度
for (var i = 0; i < 12; i++) {
ctx.beginPath()
ctx.rotate(Math.PI / 6)
ctx.moveTo(68, 0)
ctx.lineTo(75, 0)
ctx.stroke()
}
// 绘制分钟的刻度
ctx.lineWidth = 2//设置线条宽度
for (var i = 0; i < 60; i++) {
// 如果i除以五的余数不为0,则代表不跟小时的刻度重合,则绘制分钟的刻度
if (i % 5 != 0) {
ctx.beginPath()
ctx.moveTo(72, 0)
ctx.lineTo(75, 0)
ctx.stroke()
}
ctx.rotate(Math.PI / 30)
}
var hour = now.getHours()
var min = now.getMinutes()
var sec = now.getSeconds()
hour = hour > 12 ? hour - 12 : hour
console.log(hour)
console.log(min)
console.log(sec)
// 绘制时针
ctx.restore()
ctx.save()
ctx.lineWidth = 5
ctx.rotate((Math.PI / 6) * (hour + min / 60 + sec / 3600))
ctx.beginPath()
ctx.moveTo(-10, 0)
ctx.lineTo(40, 0)
ctx.stroke()
// 绘制分针
ctx.restore()
ctx.save()
ctx.lineWidth = 4
ctx.rotate((Math.PI / 30) * (min + sec / 60))
ctx.beginPath()
ctx.moveTo(-10, 0)
ctx.lineTo(60, 0)
ctx.stroke()
// 绘制秒针
ctx.restore()
ctx.save()
ctx.lineWidth = 3
ctx.rotate((Math.PI / 30) * (sec))
ctx.beginPath()
ctx.moveTo(-10, 0)
ctx.lineTo(60, 0)
ctx.strokeStyle = 'red'
ctx.stroke()
// 在原点处绘制红色小圆点
ctx.beginPath()
ctx.arc(0, 0, 5, 0, 2 * Math.PI)
ctx.fillStyle = 'red'
ctx.fill()
// 在秒针末端绘制小圆圈
ctx.beginPath()
ctx.arc(65, 0, 5, 0, 2 * Math.PI)
ctx.stroke()
ctx.restore()
}
setInterval(function () {
clock()
}, 1000)
动画_运动的小球
var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var raf;
var x = 250//定义小球的圆心的默认横坐标
var y = 250//定义小球的圆形的默认纵坐标
var stepX = 5//定义小球每次运动水平方向的偏移矢量
var stepY = 2//定义小球每次运动垂直方向的偏移矢量
function draw() {
// ctx.clearRect(0, 0, 500, 500)
// 每次绘制前都画一个带点透明的矩形,这样可以产生尾巴的效果
ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fillRect(0, 0, 500, 500);
//根据小球的新的圆心的位置绘制小球
ctx.beginPath()
ctx.arc(x, y, 20, 0, 2 * Math.PI)
ctx.fillStyle = 'red'
ctx.fill()
// 判断小球的位置.如果超出
if (x + 20 >= 500 || x - 20 <= 0) {
stepX = -stepX;
}
if (y + 20 >= 500 || y - 20 <= 0) {
stepY = -stepY;
}
// 改变小球的位移
x += stepX
y -= stepY
}
function anim() {
draw()//绘制小球
//告诉浏览器我要执行一个动画,传递进去的回调函数会在每次重绘之前调用,一般情况下每秒执行60次
raf = window.requestAnimationFrame(anim)
}
anim()
// 监听鼠标的移动事件,让小球跟着鼠标移动位置
c.addEventListener('mousemove',function (e) {
window.cancelAnimationFrame(raf);
x = e.offsetX;
y = e.offsetY;
draw()
});
// 点击鼠标,则继续开始动画
c.addEventListener('click', function (e) {
anim()
});
引入外部SVG
SVG :遵循 XML 标准,用来定义可缩放矢量图形。
1、引入外部svg文件的方式
1.1、作为元素的背景图
#con {
width:100px;
height: 100px;
background: url('./test.svg') no-repeat;
}
1.2、使用 img 引入
<img src="test.svg" alt="" >
1.3、使用 object 引入
<object data="test.svg" type="image/svg+xml" />