1.canvas、img、video,都是图像对象,属于图像类型的节点。这种图像对象不是Image 对象,而是对加载图像数据流的节点的统称。javascript
2.图像对象的数据的读写php
读取图像数据html
写入图像数据前端
canvas 读取img 图像的案例: https://www.runoob.com/try/tr...
canvas 读取video 图像的案例: https://www.w3school.com.cn/t...vue
3.gif 是介于图片和视频之间的特殊存在。html5
直接绘制gif 确定是很差使的java
<div> <img id="img" src="./assets/images/girl.gif"> </div> <canvas id="c" width="300" height="212"></canvas> <script> const img=document.getElementById("img"); const c=document.getElementById("c"); const ctx=c.getContext('2d'); ctx.drawImage(img,0,0); </script>
利用requestAnimationFrame,频繁绘制,也很差使git
const img=document.getElementById("img"); const c=document.getElementById("c"); const ctx=c.getContext('2d'); render(); function render(){ ctx.drawImage(img,0,0); window.requestAnimationFrame(render); }
<video src="./assets/images/girl.gif"></video>
1.获取gif 数据github
let xhr=new XMLHttpRequest(); xhr.open('get','./assets/images/zao.gif'); xhr.setRequestHeader("Content-Type", "text/plain"); xhr.send(); xhr.onreadystatechange=function(){ if(xhr.readyState===4){ if(xhr.status===200){ console.log('response',xhr.response); } } }
2.从response 中提取gif 数据,并解析成ImageData 对象的集合canvas
3.用canvas 上下文的putImageData 方法,将ImageData 数据加载到canvas 中
具体实现方式我就不说了,有点复杂,不是一时片刻能说完的(真正缘由是我研究了半天libgif.js源码,仍是只看懂了大概流程)。先知道这个原理吧,libgif.js 库就是实现这块功能的。
libgif.js已经完成了对gif 的解析,并将其写入了canvas 中。
libgif.js网址:https://github.com/buzzfeed/l...
下面是我从官网上复制粘贴下来,用百度翻译一下 ,而后略做调整。英语好的能够跳过这里,看官网。
1.写在图片标签里的属性 Image tag attributes
2.构造函数 Constructor options
3.loading 事件
4.播放控制器 play controls
5.数据获取 getters
6.官方案例
<div> <img id="img1" src="./assets/images/zao.gif" rel:auto_play="1" rel:rubbable="1" > </div> <div> <img id="img2" src="./assets/images/zao.jpg" rel:animated_src="./assets/images/zao.gif" rel:auto_play="0" /> </div> <div> <a href="javascript:;" onmousedown="sup2.pause(); return false;">Pause</a> | <a href="javascript:;" onmousedown="sup2.play(); return false;">Play</a> | <a href="javascript:;" onmousedown="sup2.move_to(0); return false;">Restart</a> | <a href="javascript:;" onmousedown="sup2.move_relative(1); return false;">Step forward</a> | <a href="javascript:;" onmousedown="sup2.move_relative(-1); return false;">Step back</a> </div> <canvas id="c" width="300" height="212"></canvas> <script src="./lib/libgif.js"></script> <script src="./lib/rubbable.js"></script> <script> let img1=document.getElementById("img1"); let img2=document.getElementById("img2"); let sup1 = new RubbableGif({ gif: img1 } ); sup1.load(); let sup2 = new SuperGif({ gif: img2 } ); sup2.load(); </script>
注:
实际项目中,咱们可能只是想在咱们的canvas 项目里添加动起来表情包,而不是额外的创建一个真实的img 节点,更不是再生成一个真实的canvas 将其替换。因此,我作了一下调整:
1.将rubbable.js 中替换img 节点的方法过滤掉。为何叫过滤呢,由于这样不会影响原始功能,尊重做者。
if(parent){ parent.insertBefore(div, gif); parent.removeChild(gif); }
2.引用Image 对象代替真实的<img> 节点,这样就不须要再让浏览器渲染img 了,节省资源,真正只将其当成一个传递数据的工具。
const gif=new Image(w,h); gif.setAttribute('data-animated_src',src);
3.为SuperGif 添加一个change 属性的方法,让其在图片渲染时执行。这样就能够在外部,实时获取SuperGif 里的canvas。注意,这种写法不会影响对象的继承,由于SuperGif 还有各个叫RubbableGif 的子级,SuperGif 实例对其原型属性修改后,RubbableGif 的实例也会继承这种修改。这个问题也能够从继承上解决,我本着尊重做者的目的,就不改了(其实是看得费劲,不想深究了)。
(function (root, factory) { //... }(this, function () { //渲染监听方法 var change=function(){} var SuperGif = function ( opts ) { //... var player = (function () { //... var putFrame = function () { //... if(options.change){options.change()} } } } })
4.还有的小问题,libgif.js 对标签属性的定义不规范。rel:auto_play="0" ,这样的方式定义在模板文件里还能够,好比vue的v-on:click="play()"。在真正的HTML 要这样的写:data-auto_play="0"
六,canvas 显示图片
1.canvas显示图片的方式有两种:
canvas 绘图:
参考地址: https://www.runoob.com/try/tr...
2.上代码:
项目地址:https://github.com/buglas/fun...,中的gif4.html 文件
<div> <canvas id="canvas" width="300" height="212"></canvas> </div> <script src="./lib/libgif.js"></script> <script src="./lib/rubbable.js"></script> <script> const canvas=document.getElementById('canvas'); const ctx=canvas.getContext('2d'); const src='./assets/images/girl.gif'; const [w,h]=[150,133]; const GifTool={ drawGif:({src,w,h,draw})=>{ const gif=new Image(w,h); gif.setAttribute('data-animated_src',src); const sup = new SuperGif({ gif, change:()=>{ const canvas=sup.get_canvas(); const curCtx=canvas.getContext("2d"); const imgData=curCtx.getImageData(0,0,w,h); draw({imgData,canvas}); } }); sup.load(); } } GifTool.drawGif({ src,w,h, draw:({imgData})=>{ ctx.putImageData(imgData,0,0); } }); </script>
GifTool.drawGif({ src,w,h, draw:({canvas})=>{ const pat=ctx.createPattern(canvas,"repeat"); ctx.rect(0,0,w,h); ctx.fillStyle=pat; ctx.fill(); } });
GifTool.drawGif({ src,w,h, draw:({canvas})=>{ const pat=ctx.createPattern(canvas,"repeat"); ctx.save(); ctx.translate(10,0); ctx.beginPath(); ctx.arc(60,80,60,0,Math.PI*2); ctx.fillStyle=pat; ctx.fill(); ctx.restore(); ctx.save(); ctx.translate(150,40); ctx.beginPath(); ctx.arc(60,80,60,0,Math.PI*2); ctx.fillStyle=pat; ctx.fill(); ctx.restore(); } });