发表于 2021-02-12|更新于 2021-08-24|前端
字数总计:2.6k|阅读时长:10 分钟 | 阅读量:920
长久以来,web 上的动画都是 Flash。比如动画广告、游戏等等,基本上都是 F1ash 实现的。Flash 是有缺点的,比如需要安装 Adobe Flash Player, 漏洞多,重量比较大。卡顿和不流畅等等
HTML5 提出了一个新的 canvas 标签,彻底颠覆了 Flash 的主导地位。无论是广告、游戏都可以使用 canvas 实现了,Canvas 是一个轻量级的画布,我们使用 Canvas 进行 JavaScript 的编程,不需要增加额外的插件,性能也很好,不卡顿,在手机中也很流畅
HTML
<canvas width="400" height="500" id="mycanvas">
当前浏览器版本不支持,请升级浏览器
</canvas>
canvas 的标签属性只有两个,width 和 height.。表示的是 canvas 画布的宽度和高度。注意 canvas 的 width 和 height 不要用 css 的样式来设置,如果使用 css 的样式来设置,画布会失真,会变形 标签对儿里面的文字是用来提示低版本浏览器 (IE6/7/8)
方法 / 属性 | 描述 |
---|---|
getContext() | 得到画布上下文,上下文有两个,2d 的上下文和 3d 的上下文 |
fillStyle | 设置颜色 |
fillRect(x,y,width,height) | 方法绘制 “已填色” 的矩形。默认的填充颜色是黑色。 |
我们使用 canvas 绘制了一个图形,一旦绘制成功了,canvas 就像素化了他们。 canvas 没有能力,从画布上再次得到这个图形,也就是说我们没有能力去修改已经在画布上的内容。这个就是 canvas 比较轻量的原因,Flash 重的原因之一就有它可以通过对应的 api 得到已经上 “画布” 的内容然后再次绘制,如果我们想要让这个 canvas 图形移动,必须按照清屏 - 更新 - 渲染的逻辑进行编程,总之就是重新再画一次
清屏 - 更新 - 渲染,这个思想就可以为 canvas 的动画思想
JAVASCRIPT
var canvas=document.getElementById("mycanvas");
var ctx=canvas.getContext("2d")
ctx.fillStyle="blue"
// 设置信号量
var left=10;
setInterval(()=>{
//清除画布
ctx.clearRect(0,0,700,600)
// 更新信号量
left++;
ctx.fillRect(left,left,100,100)
if(left==700){
left=10
}
},4)
实际上,动画的生存就是相关静态画面连续插放了,这个就是动画的过程。我们把每一次绘制的静态画面叫做 " 一帧 ",时间的间隔 (定时器的间隔) 就表示的是帧的间隔
因为 canvas 不能得到已经上屏的对象,所以我们要维持对象的状态。在 canvas 动画中,我们都使用面向对象来进行编程,因为我们可以使用面向对象的方式来维持 canvas 需要的属性和状态
JAVASCRIPT
// 获取画布
var can = document.getElementById("can")
var ctx = can.getContext("2d");
// 绘制方法
function Rect(x, y, w, h, color) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color
}
// 更新方法
Rect.prototype.update = function () {
this.x++;
}
// 渲染
Rect.prototype.render = function () {
// 设置颜色
ctx.fillStyle = this.color;
// 渲染
ctx.fillRect(this.x, this.y, this.w, this.h);
}
// 实例化
var r1 = new Rect(100, 100, 50, 50, "#91d5ff")
// 动画过程
setInterval(() => {
//清屏
ctx.clearRect(0, 0, can.width, can.height)
//更新
r1.update()
// 渲染
r1.render()
}, 5)
动画过程在主定时器里面,每一帧都会调动实例的更新和渲染方法
方法 / 属性 | 描述 |
---|---|
fillStyle | 设置填充颜色 |
fillRect(x,y,width,height) | 方法绘制 “已填色” 的矩形。默认的填充颜色是黑色。 |
strokeStyle | 设置边框颜色 |
strokeRect(x,y,width,height) | 方法绘制矩形边框。默认的填充颜色是黑色。 |
clearRect(x,y,width,height) | 清除画布内容 |
globalAlpha | 设置透明度 0-1 |
JAVASCRIPT
// 创建路径
ctx.beginPath()
// 移动绘制点
ctx.moveTo(100,100)
// 描述行进路径
ctx.lineTo(200,300);
ctx.lineTo(300,230);
ctx.lineTo(440,290);
ctx.lineTo(380,50);
// 封闭路径
ctx.closePath()
// 设置颜色
ctx.strokeStyle="#91d5ff"
// 绘制不规则图形
ctx.stroke()
// 填充不规则图形
ctx.fill()
JAVASCRIPT
arc(x, y, radius, startAngle, endAngle, anticlockwise)
x,y
为绘制圆弧所在圆上的圆心坐标。radius
为半径。startAngle
以及endAngle
参数用弧度定义了开始以及结束的弧度。这些都是以 x 轴为基准。- 参数
anticlockwise
为一个布尔值。为 true 时,是逆时针方向,否则顺时针方向。
注意:
arc()
函数中表示角的单位是弧度,不是角度。角度与弧度的 js 表达式:弧度 =(Math.PI/180)* 角度。
JAVASCRIPT
// 创建路径
ctx.beginPath();
// 圆周长 2π 2*3.14≈7 2*Math.PI
ctx.arc(200,200,100,0,2*Math.PI,false)
// ctx.arc(200,200,100,0,0.3,false)
// 绘制
ctx.stroke()
我们可以利用 lineWidth
设置线的粗细,属性值必须是数字,默认是 1.0。没有单位
JAVASCRIPT
ctx.beginPath();
ctx.moveTo(100,150)
ctx.lineTo(200,200)
ctx.lineTo(300,50)
ctx.lineWidth=10
ctx.stroke()
JAVASCRIPT
// 设置文字
ctx.font="30px 宋体"
// 设置文字对齐方式
ctx.textAlign="start"
ctx.fillText("Hello Canvas",100,100)
- 线型渐变
JAVASCRIPT
// 渐变
var linear=ctx.createLinearGradient(0, 0, 200, 200);
linear.addColorStop(0,"red");
linear.addColorStop(0.5,"#91d5ff");
linear.addColorStop(0.8,"#ffec3d");
linear.addColorStop(1,"blue")
ctx.fillStyle=linear
ctx.fillRect(10,10,200,100)
JAVASCRIPT
// 阴影
ctx.shadowOffsetX=10 // 左右偏移
ctx.shadowOffsetY=10 // 上下偏移
ctx.shadowBlur=3; // 模糊度
ctx.shadowColor="red"; // 颜色
// 设置文字
ctx.font="30px 宋体"
ctx.fillText("Hello Canvas",100,100)
JAVASCRIPT
// 创建image元素
var img=new Image();
// 设置src地址
img.src="https://tva3.sinaimg.cn/large/006djwNZgy1gmqxcekdm8j31hc0u0dln.jpg"
// 必须在onload 之后绘制图片
img.onload=function(){
ctx.drawImage(img,100,100,200,100)
}
- 4 个参数
JAVASCRIPT
drawImage(img,x,y,width,height)
- 8 个参数 切片 Slicing
JAVASCRIPT
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
- 前 4 个参数指的是你在图片中设置切片的宽度和高度,以及切片位置
- 后 4 个参数指的是切片在画布上的位置和切片的宽度和高度
JAVASCRIPT
// 游戏类
function Game() {
this.dom = document.querySelector("canvas");
this.ctx = this.dom.getContext("2d");
// 添加属性,保存需要的图片地址
this.R = {
"01": "https://tvax3.sinaimg.cn/large/006djwNZgy1gkyvxt1exaj33y8280b2c.jpg",
"02": "https://tva1.sinaimg.cn/large/006djwNZgy1gkyzq80yobj31hc0u0n4r.jpg",
"03": "https://tva3.sinaimg.cn/large/006djwNZgy1gmqxcekdm8j31hc0u0dln.jpg",
"04": "https://tva4.sinaimg.cn/large/006djwNZgy1gmqxee8qo6j31hc0u0qcr.jpg"
}
// 获取资源图片的总数
var allAmount = Object.keys(this.R).length
// 计数器
var count = 0
// 遍历对象获取每一个地址
for (k in this.R) {
var src = this.R[k]
// 创建图片
this.R[k] = new Image()
// 设置图片地址
this.R[k].src = src;
// 判断图片是否加载完成
var self = this
this.R[k].onload = function () {
// 计数
count++;
// 清屏
self.ctx.clearRect(0, 0, 600, 500)
self.ctx.font = "16px Arial"
// 设置资源加载文案
self.ctx.fillText("图片已加载:" + count + "/" + allAmount, 10, 50)
}
}
}
console.log(new Game());
保存画布 (canvas) 的所有状态
save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
Canvas 状态存储在栈中,每当 save()
方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:
- 当前应用的变形(即移动,旋转和缩放,见下)
- 以及下面这些属性:
strokeStyle
,fillStyle
,globalAlpha
,lineWidth
,lineCap
,lineJoin
,miterLimit
,lineDashOffset
,shadowOffsetX
,shadowOffsetY
,shadowBlur
,shadowColor
,globalCompositeOperation
,font
,textAlign
,textBaseline
,direction
,imageSmoothingEnabled
你可以调用任意多次 save
方法。每一次调用 restore
方法,上一个保存的状态就从栈中弹出,所有设定都恢复。
- translate 和 CSS3 的 translate 属性一样也是发挥着空间平移作用
JAVASCRIPT
// 保存
ctx.save();
ctx.translate(50,50)
ctx.fillRect(0,0,120,120)
// 恢复
ctx.restore()
// 渲染位置是没有存档之前的位置
ctx.fillRect(0,200,120,120)
- 变形实际上都是将整个画布进行的变形,所以如果一旦变形操作多了,画布将变得不可控
- 如果使用到变形,一定记住下面的规律:变形之前要先备份,将世界和平的状态进行备份,然后再变形,变形完毕后一定要恢复到世界和平的样子,不要影响下一次的操作
JAVASCRIPT
// 保存
ctx.save();
ctx.translate(200,100)
ctx.rotate(1)
ctx.fillRect(0,0,120,120)
// 恢复
ctx.restore()
// 渲染位置是没有存档之前的位置
ctx.fillRect(0,200,120,120)
rotate(angle)
这个方法只接受一个参数:旋转的角度 (angle),它是顺时针方向的,以弧度为单位的值。
旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate
方法。
JAVASCRIPT
ctx.save();
ctx.translate(200,100)
ctx.scale(0.6,0.6)
ctx.fillRect(0,0,120,120)
// 恢复
ctx.restore()
// 渲染位置是没有存档之前的位置
ctx.fillRect(0,200,120,120)
scale
方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比 1 小,会缩小图形, 如果比 1 大会放大图形。默认值为 1, 为实际大小。
7.5 Transforms
最后一个方法允许对变形矩阵直接修改。
JAVASCRIPT
transform(a, b, c, d, e, f)
// 如果任意一个参数是`Infinity`,变形矩阵也必须被标记为无限大,否则会抛出异常。
这个函数的参数各自代表如下:
a(m11)
水平方向的缩放b(m12)
竖直方向的倾斜偏移c(m21)
水平方向的倾斜偏移d(m22)
竖直方向的缩放e(dx)
水平方向的移动f(dy)
竖直方向的移动
- 合成其实就是我们常见的蒙板状态,本质就是如何进行压盖,如何进行显示
JAVASCRIPT
ctx.fillStyle="#91d5ff"
ctx.fillRect(100,100,100,100)
ctx.fillStyle="#ffc069"
ctx.beginPath()
ctx.arc(200,200,60,0,7,false)
ctx.fill()
globalCompositeOperation
这个属性设定了在画新图形时采用的遮盖策略,其值是一个标识 12 种遮盖方式的字符串。globalCompositeOperation = type
JAVASCRIPT
ctx.globalCompositeOperation="destination-over"
文章作者: 橘子味雪糕
文章链接: https://liuxianl.com/2021/02/12/%E5%89%8D%E7%AB%AF/canvas/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 橘子味雪糕!
相关推荐
2020-12-21ES6:promise、async 的理解
2021-08-0549 个常用 JavaScript 方法封装
评论
提交
2 评论
Anonymous Chrome 91.0.4472.124 Windows 10.0
2021-07-04回复
前端小菜鸡 Chrome 88.0.4324.190 Windows 10.0
2021-03-07回复
膜拜大佬 想要微信联系方式
橘子味雪糕 Edge 89.0.774.54 Windows 10.0
2021-03-17回复
@前端小菜鸡 , 不好意思啊 才看到 在关于页面有二维码
Powered By Valine v1.4.14
橘子味雪糕
竟然选择了远方,便只顾风雨兼程
公告
2021-08-30 MON☀️ 29 *C💧 84%
22:13:18
36.18.174.210HangzhouPM
那年今日
A.D.2010印度尼西亚锡纳朋火山沉睡 400 年后再次爆发
A.D.1619日本大名岛津义弘逝世
A.D.1785民族英雄林则徐出生
A.D.1797英国作家玛丽・雪莱出生
A.D.1871英国物理学家卢瑟福出生
A.D.1929中国现代农民运动领袖彭湃逝世
A.D.1930“股神” 沃伦・巴菲特出生
A.D.1935法国作家巴比塞逝世
A.D.1940电子的发现者汤姆生在英格兰剑桥逝世
A.D.1956毛泽东发表 “球籍论”
A.D.1972世界足球先生帕维尔・内德维德出生
A.D.1990中国史学家钱穆逝世
A.D.1998中国兴建首条跨海铁路
A.D.2010印度尼西亚锡纳朋火山沉睡 400 年后再次爆发
A.D.1619日本大名岛津义弘逝世
目录
- \1. canvas 笔记
- 1.1. 一。概述
- 1.2. 二。基本使用
- 1.3. 三.canvas 的编程思想
- 1.4. 四. canvas 绘制功能
- 1.5. 五。图片使用
- 1.6. 六。资源管理器
- 1.7. 七。变形
- 1.8. 八。合成
最新文章
49 个常用 JavaScript 方法封装2021-08-05
正则2021-07-09
Vue 3 学习笔记2021-05-05
canvas 笔记2021-02-12
SassScript2021-02-11
©2019 - 2021 By 橘子味雪糕
A world that knows nothing will surprise you if you go on 湘 ICP 备 20001832 号 - 3 本网站由 提供 CDN 加速服务