博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
canvas元素简易教程(5)(大部分转自火狐,自己只写了简单的代码分析)
阅读量:7251 次
发布时间:2019-06-29

本文共 8897 字,大约阅读时间需要 29 分钟。

好了,上次我们说过要对canvas的应用图像进行简单的讲解,现在就让我们开始吧。

首先,我要对canvas的应用图像做一个简单的介绍。在html5中,canvas标签加入的十分有趣的功能就是引入图像。什么?你要说image也能做到?好吧,你赢了。Image的却能做到这一点,但是我所说的是引入图像,不是载入图像。你要问这俩有啥区别?好吧,你又赢了。我来讲讲吧。。。

Canvas的引入图像与载入图像的最大区别是,你载入就是把图片下载到容器里面然后放那,引入可就不一样了,你可以进行一些简单的改动,比如裁剪啊合成啊什么的。

怎么做到?别急,咱慢慢来。首先我需要讲清楚几点:第一,canvas也不是什么格式的图片都能载入的,这个需要浏览器支持。第二canvas目前仅可以在图像中加入文字。

好了,现在开始讲解。首先,引入图像需要两步简单的步骤:

第一步当然是来源的图片了,我们提供了四种载入方式,也就是说,不是让你使用一个简单的URL载入,而是让你用JS的image对象或者其他canvas的引用。

第二步也是最关键的一步,就是用drawImage方法将图像插入到canvas中。

我们先来看看第一步,共有四种载入方式:引用页面内的图片、使用其它canvas元素、从零开始创建图像或者通过data: url方式嵌入图像。我想你已经明白了吧。不明白?不明白我就给你讲讲。

首先是引用页内的图片,我们可以通过document.images集合、document.getElementsByTagName方法又或者document.getElementById方法来获取页面内的图片(如果已知图片元素的 ID)。也就是说,可以通过DOM的元素查找方法来引用页面内的图片对象。

然后是使用其canva对象,和引用页面内的图片类似地,用document.getElementsByTagName或document.getElementById方法来获取其它canvas元素。但你引入的应该是已经准备好的canvas。

然后是由零开始创建图像,我们可以用脚本创建一个新的Image对象,但这种方法的主要缺点是如果不希望脚本因为等待图片装置而暂停,还得需要突破预装载。

先看看怎么创建图片吧:

var img = new Image();   // Create new Image object 

img.src = 'myImage.png'; // Set source path 

当脚本执行后,图片开始装载。若调用drawImage时,图片没装载完,脚本会等待直至装载完毕。如果不希望这样,可以使用onload事件:

var img = new Image();   // Create new Image object 

img.onload = function(){ 

  // execute drawImage statements here 

img.src = 'myImage.png'; // Set source path 

如果你只用到一张图片的话,这已经够了。但一旦需要不止一张图片,那就需要更加复杂的处理方法,但图片预装载策略超出本教程的范围,感兴趣的话可以参JavaScript Image Preloader。

最后是用通过data: url方式嵌入图像,在介绍这种方式之前我想先讲一下什么是data: url:

data: url是用一串Base64编码的字符串的方式来定义一个图片。其优点就是图片内容即时可用,无须再到服务器兜一圈。(还有一个优点是,可以将CSS,JavaScript,HTML和 图片全部封装在一起,迁移起来十分方便。)缺点就是图像没法缓存,图片大的话内嵌的url数据会相当的长。明白了么?不明白用Base编码是什么意思是吧,没事,有我呢。

下面的例子是一张GIF图片用base 64进行编码后的data URI:

data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge 8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1h LnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g 77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7

同一张图片如果不用base 64编码的话将会如下显示:

data:image/gif,GIF89a%22%00%1B%00%F7%00%00lll%D6%D6%D6%FF%EB%85 %FF%E0%7B%FF%F7%91%FF%D4o%DF%DF%DF%F6%F6%F6%87%87%87%FE %CBf%FF%F4%8E%E6%B3NKKK%C5%92-%FF%FF%99%FF%FF%FF%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%2C%00%00 %00%00%22%00%1B%00%00%08%A9%00%1F%08%1CH%B0%A0%C1%83%08 %13*%5C%C8%B0%A1%C3%87%10%23J%9CH%91%60%83%8B%0D%0C%1C %A8h%B0%81%C5%00%1B9%0A%F4%E8%A0%A4%83%07%181j%9C%D8%80 %80%82%97%2F%0B6%40%60%80%A5%00%01)s%AA%94%D8%60%80G%84 %02P%22%E0Y%A0%81%C9%A3%25%138h%00%80g%02%A3%04%A2J%8D %BA%60i%D3%88%0D%9E%3A%B8%C9%95kU%A6N%8D%0E%18Kv%EC%D7 %AB%10%B3%1A-%C0%B6-%5B%A3%60%23%1A%D0I%97%C1%D0%88%07 %02%20%00%C0%B7%AF_%00%08%02L%3C%60%20%80%E1%C3%88%03 %AC%14%C9%B8%B1%E3%C7%90%23K%9EL0%20%00%3B

现在你知道了Base64有什么用了吧,它让URI明显小多了。但是请你注意,这种方法其实会让数据变大而不是变小,所以你要考虑浏览器对http压缩的支持与性能。而Base64不仅仅支持图片,也同样支持其他的文件甚至是HTML本身,但是IE8下对它的限制让人只能用于图片了。。。

好了,现在你知道什么是Base64了吧,那么我来说一下它的格式吧。data URI的格式很简单,在RFC 2397里有清楚的说明。基本的格式如下:

data:[][;charset=][;base64]

在这个格式中,data:URI的协议,表明这是一个data URI。第二部分,MIME type,表明了要呈现的数据的类型。拿PNG图片举个例子,它的MIME type是image/png。如果没有指定,MIME type将会默认为text/plain。charset在大多数情况下可以无视,对于图片来说它根本没用。下一部分指明了使用的编码。跟流行观念相反, 你不一定要用base 64编码。如果内容不是用base 64进行编码,那么这些数据就会使用标准的URL编码(对URL安全的ASCII字符将会保留原样显示,其他会显示成%xx格式的十六进制编码)进行编 码。编码后的数据可能会包含一些没用空格。

好了,说了这么多颇有跑题的嫌疑啊,我们来看看一个最基本的例子吧:

Var img_src =

'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';

一旦获得了源图对象,我们就可以使用drawImage方法将它渲染到canvas里。drawImag 方法有三种形态,下面是最基础的一种:

drawImage(image, x, y)

其中image是image或者canvas对象x和y是其在目标canvas里的起始坐标。

下面一个例子我用一个外部图像作为一线性图的背景。用背景图我们就不需要绘制负责的背景,省下不少代码。这里只用到一个image对象,于是就在它的onload事件响应函数中触发绘制动作。drawImage方法将背景图放置在canvas的左上角(0,0)处:

function draw() { 

    var ctx = document.getElementById('canvas').getContext('2d'); 

    var img = new Image(); 

    img.onload = function(){ 

      ctx.drawImage(img,0,0); 

      ctx.beginPath(); 

      ctx.moveTo(30,96); 

      ctx.lineTo(70,66); 

      ctx.lineTo(103,76); 

      ctx.lineTo(170,15); 

      ctx.stroke(); 

    } 

    img.src = 'images/backdrop.png'; 

  } 

这个例子是一个简单的图片引入然后将之作为背景,然后再上面绘制路径的样例,也是最基本的使用方法。

drawImage方法的又一变种是增加了两个用于控制图像在canvas中缩放的参数:

drawImage(image, x, y, width, height)

当中width和height分别是图像在canvas中显示大小。

在这个例子里,我会用一张图片像背景一样在canvas中以重复平铺开来。实现起来也很简单,只需要循环铺开经过缩放的图片即可。见下面的代码,第一层for循环是做行重复,第二层是做列重复的。图像大小被缩放至原来的三分之一,50x38 px。这种方法可以用来很好的达到背景图案的效果,在下面的教程中会看到。

注意:图像可能会因为大幅度的缩放而变得起杂点或者模糊。如果您的图像里面有文字,那么最好还是不要进行缩放,因为那样处理之后很可能图像里的文字就会变得无法辨认了。

看看例子:

function draw() { 

    var ctx = document.getElementById('canvas').getContext('2d'); 

    var img = new Image(); 

    img.onload = function(){ 

      for (i=0;i<4;i++){ 

        for (j=0;j<3;j++){ 

          ctx.drawImage(img,j*50,i*38,50,38); 

        } 

      } 

    } 

    img.src = 'images/rhino.jpg'; 

  } 

一个简单的缩放例子,用循环控制将很多小的缩略图拼接在一起,类似于window背景中的平铺效果。。。

drawImage方法的第三个也是最后一个变种有8个新参数,用于控制做切片显示的:

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

第一个参数和其它的是相同的,都是一个图像或者另一个canvas的引用。其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。

切片是个做图像合成的强大工具。假设有一张包含了所有元素的图像,那么你可以用这个方法来合成一个完整图像。例如,你想画一张图表,而手上有一个包含所有必需的文字的PNG文件,那么你可以很轻易的根据实际数据的需要来改变最终显示的图表。这方法的另一个好处就是你不需要单独装载每一个图像。

在这个例子里面我用到上面已经用过的犀牛图像,不过这次我要给犀牛头做个切片特写,然后合成到一个相框里面去。相框带有阴影效果,是一个以24-bit PNG格式保存的图像。因为24-bit PNG图像带有一个完整的8-bit alpha通道,与GIF和8-bit PNG不同,我可以将它放成背景而不必担心底色的问题。

我用一个与上面用到的不同的方法来装载图像,直接将图像插入到HTML里面,然后通过CSS隐藏(display:none)它。两个图像我都赋了id,方便后面使用。看下面的脚本,相当简单,首先对犀牛头做好切片(第一个drawImage)放在canvas上,然后再上面套个相框(第二个drawImage ):

function draw() { 

  var canvas = document.getElementById('canvas'); 

  var ctx = canvas.getContext('2d'); 

  // Draw slice 

  ctx.drawImage(document.getElementById('source'), 

                33,71,104,124,21,20,87,104); 

  // Draw frame 

  ctx.drawImage(document.getElementById('frame'),0,0); 

样例代码用到了切片的技术,裁剪与拼接的展示想必会使大家更加清晰的了解到切片的作用了。

好吧好吧,学了这么多,咱一起看一个大例子吧,一个能全面的体会今天所学习的东西的例子。希望大家喜欢~(反正不是我写的代码)

function draw() { 

 

  // Loop through all images 

  for (i=0;i<document.images.length;i++){ 

 

    // Don't add a canvas for the frame image 

    if (document.images[i].getAttribute('id')!='frame'){ 

 

      // Create canvas element 

      canvas = document.createElement('CANVAS'); 

      canvas.setAttribute('width',132); 

      canvas.setAttribute('height',150); 

 

      // Insert before the image 

      document.images[i].parentNode.insertBefore(canvas,document.images[i]); 

 

      ctx = canvas.getContext('2d'); 

 

      // Draw image to canvas 

      ctx.drawImage(document.images[i],15,20); 

 

      // Add frame 

      ctx.drawImage(document.getElementById('frame'),0,0); 

    } 

  } 

这一章最后的示例是弄一个小画廊。画廊由挂着几张画作的格子组成。当页面装载好之后,为每张画创建一个canvas元素并用加上画框然后插入到画廊中去。

在这个例子里面,所有“画”都是固定宽高的,画框也是。你可以做些改进,通过脚本用画的宽高来准确控制围绕它的画框的大小。其实这个并不难,对吗?

样例的代码应该是蛮自我解释的了。就是遍历图像对象数组,依次创建新的canvas元素并添加进去。可能唯一需要注意的,对于那些并不熟悉DOM的朋友来说,是insertBefore方法的用法。insertBefore是父节点(单元格)的方法,用于将新节点(canvas元素)插入到我们想要插入的节点之前。其实我非常鼓励大家试试别的方法,比如通过动态html插入什么的,或者自己定义个insertAfter函数啥的。

Gecko 1.9.2引入了mozImageSmoothingEnabled属性,值为false时,图像不会平滑地缩放。默认是true。

cx.mozImageSmoothingEnabled = false; 

好了,今天所讲的就到这里了,希望大家喜欢。在下一讲中我们会着重讲解一下运用样式与颜色,这是值得期待的一章,我们下次再见。

 

转载于:https://www.cnblogs.com/xiao-yao/archive/2012/03/22/2411178.html

你可能感兴趣的文章
《将博客搬至CSDN》
查看>>
TCP/IP和OSI参考模型
查看>>
python日志管理模块logging
查看>>
Android用Intent和Bundle传list
查看>>
MySQL count(*) 优化
查看>>
西城110/linux高级作业(12.26)
查看>>
负载产品性能测试——新建测试
查看>>
mongo学习记录
查看>>
node.js搭建本地服务器的代码分享
查看>>
Flask + mod_wsgi + Apache on Windows 部署成功
查看>>
python&mnist笔记
查看>>
redis学习(二)
查看>>
java运算符 与(&)、非(~)、或(|)、异或(^)
查看>>
jdbc的小warning
查看>>
ReactOS:基于Windows的开源操作系统
查看>>
在 Linux 中调试 C 程序的福音——gdb
查看>>
这些年一起学过的Linux
查看>>
Linux环境PHP7.0安装
查看>>
浏览器缓存机制
查看>>
Date、System、Calendar获取当前时间毫秒
查看>>