Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1029340 of 应用图像 Using images

  • 版本网址缩略名: Web/API/Canvas_API/Tutorial/Using_images
  • 版本标题: 应用图像 Using images
  • 版本 id: 1029340
  • 创建于:
  • 创建者: zcyzcy88
  • 是否是当前版本?
  • 评论
标签: 

修订内容

{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_text", "Web/API/Canvas_API/Tutorial/Transformations")}}

canvas更有意思的一项特性就是图像操作能力。可以用于动态的图像合成或者作为图形的背景,以及游戏界面(Sprites)等等。浏览器支持的任意格式的外部图片都可以使用,比如PNG、GIF或者JPEG。 你甚至可以将同一个页面中其他canvas元素生成的图片作为图片源。

引入图像到canvas里需要以下两步基本操作:

  1. 获得一个指向{{domxref("HTMLImageElement")}}的对象或者另一个canvas元素的引用作为源,也可以通过提供一个URL的方式来使用图片(参见例子
  2. 使用drawImage()函数将图片绘制到画布上

我们来看看具体是怎么做的。

获得需要绘制的图片

canvas的API可以使用下面这些类型中的一种作为图片的源:

{{domxref("HTMLImageElement")}}
这些图片是由Image()函数构造出来的,或者任何的{{HTMLElement("img")}}元素
{{domxref("HTMLVideoElement")}}
用一个HTML的 {{HTMLElement("video")}}元素作为你的图片源,可以从视频中抓取当前帧作为一个图像
{{domxref("HTMLCanvasElement")}}
可以使用另一个 {{HTMLElement("canvas")}} 元素作为你的图片源。
{{domxref("ImageBitmap")}}
这是一个高性能的位图,可以低延迟地绘制,它可以从上述的所有源以及其它几种源中生成。

这些源统一由 {{domxref("CanvasImageSource")}}类型来引用。

有几种方式可以获取到我们需要在canvas上使用的图片。

使用相同页面内的图片

我们可以通过下列方法的一种来获得与canvas相同页面内的图片的引用:

  • {{domxref("document.images")}}集合
  •  {{domxref("document.getElementsByTagName()")}}方法
  • 如果你知道你想使用的指定图片的ID,你可以用{{domxref("document.getElementById()")}}获得这个图片

使用其它域名下的图片

在 {{domxref("HTMLImageElement")}}上使用crossOrigin属性,你可以请求加载其它域名上的图片。如果图片的服务器允许跨域访问这个图片,那么你可以使用这个图片而不污染canvas,否则,使用这个图片将会污染canvas

使用其它 canvas 元素

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

一个常用的应用就是将第二个canvas作为另一个大的 canvas 的缩略图。

由零开始创建图像

或者我们可以用脚本创建一个新的 {{domxref("HTMLImageElement")}} 对象。要实现这个方法,我们可以使用很方便的Image()构造函数。

var img = new Image();   // 创建一个<img>元素
img.src = 'myImage.png'; // 设置图片源地址

当脚本执行后,图片开始装载。

若调用 drawImage 时,图片没装载完,那什么都不会发生(在一些旧的浏览器中可能会抛出异常)。因此你应该用load时间来保证不会在加载完毕之前使用这个图片:

var img = new Image();   // 创建img元素
img.onload = function(){
  // 执行drawImage语句
}
img.src = 'myImage.png'; // 设置图片源地址

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

通过 data: url 方式嵌入图像

我们还可以通过 data:url 方式来引用图像。Data urls 允许用一串 Base64 编码的字符串的方式来定义一个图片。

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

其优点就是图片内容即时可用,无须再到服务器兜一圈。(还有一个优点是,可以将 CSS,JavaScript,HTML 和 图片全部封装在一起,迁移起来十分方便。)缺点就是图像没法缓存,图片大的话内嵌的 url 数据会相当的长:

使用视频帧

你还可以使用{{HTMLElement("video")}} 中的视频帧(即便视频是不可见的)。例如,如果你有一个ID为“myvideo”的{{HTMLElement("video")}} 元素,你可以这样做:

function getMyVideo() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');

    return document.getElementById('myvideo');
  }
}

它将为这个视频返回{{domxref("HTMLVideoElement")}}对象,正如我们前面提到的,它可以作为我们的Canvas图片源。

绘制图片

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

drawImage(image, x, y)
其中 image 是 image 或者 canvas 对象,xy 是其在目标 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';
  }

结果看起来是这样的:

{{EmbedLiveSample("drawImage_example_1", 220, 160, "https://mdn.mozillademos.org/files/206/Canvas_backdrop.png")}}

缩放 Scaling

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

{{domxref("CanvasRenderingContext2D.drawImage", "drawImage(image, x, y, width, height)")}}
这个方法多了2个参数:width 和 height,这两个参数用来控制 当像canvas画入时应该缩放的大小

drawImage 示例 2

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

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

{{EmbedLiveSample("Example_Tiling_an_image", 160, 160, "https://mdn.mozillademos.org/files/251/Canvas_scale_image.png")}}

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var img = new Image();
  img.onload = function(){
    for (var i=0;i<4;i++){
      for (var j=0;j<3;j++){
        ctx.drawImage(img,j*50,i*38,50,38);
      }
    }
  };
  img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
}

切片 Slicing

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

{{domxref("CanvasRenderingContext2D.drawImage", "drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)")}}
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。

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

drawImage 示例 3

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

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

{{EmbedLiveSample("Example_Framing_an_image", 160, 160, "https://mdn.mozillademos.org/files/226/Canvas_drawimage2.jpg")}}

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);
}

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

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

下面的代码应该是蛮简单易懂的了。就是遍历图像对象数组,依次创建新的 canvas 元素并添加进去。可能唯一需要注意的,对于那些并不熟悉 DOM 的朋友来说,是 insertBefore 方法的用法。insertBefore 是父节点(单元格)的方法,用于将新节点(canvas 元素)插入到我们想要插入的节点之前。

{{EmbedLiveSample("Art_gallery_example", 725, 400)}}

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);
    }
  }
}

控制图像的缩放行为 Controlling image scaling behavior

{{ gecko_minversion_header("1.9.2") }}

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

cx.mozImageSmoothingEnabled = false;

{{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_text", "Web/API/Canvas_API/Tutorial/Transformations")}}

修订版来源

<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_text", "Web/API/Canvas_API/Tutorial/Transformations")}}</div>

<p>canvas更有意思的一项特性就是图像操作能力。可以用于动态的图像合成或者作为图形的背景,以及游戏界面(Sprites)等等。浏览器支持的任意格式的外部图片都可以使用,比如PNG、GIF或者JPEG。 你甚至可以将同一个页面中其他canvas元素生成的图片作为图片源。</p>

<p><span style="line-height:1.5">引入图像到canvas里需要以下两步基本操作:</span></p>

<ol>
 <li>获得一个指向{{domxref("HTMLImageElement")}}的对象或者另一个canvas元素的引用作为源,也可以通过提供一个URL的方式来使用图片(参见<a href="https://www.html5canvastutorials.com/tutorials/html5-canvas-images/" target="_blank">例子</a>)</li>
 <li>使用<code>drawImage()</code>函数将图片绘制到画布上</li>
</ol>

<p>我们来看看具体是怎么做的。</p>

<h2 id="获得需要绘制的图片">获得需要绘制的图片</h2>

<p>canvas的API可以使用下面这些类型中的一种作为图片的源:</p>

<dl>
 <dt><strong style="font-weight:bold">{{domxref("HTMLImageElement")}}</strong></dt>
 <dd>这些图片是由<code>Image()函数构造出来的,或者任何的{{HTMLElement("img")}}元素</code></dd>
 <dt><strong style="font-weight:bold; line-height:1.5">{{domxref("HTMLVideoElement")}}</strong></dt>
 <dd>用一个HTML的&nbsp;<span style="line-height:1.5">{{HTMLElement("video")}}元素作为你的图片源,可以从视频中抓取当前帧作为一个图像</span></dd>
 <dt><strong style="font-weight:bold">{{domxref("HTMLCanvasElement")}}</strong></dt>
 <dd>可以使用另一个&nbsp;{{HTMLElement("canvas")}} 元素作为你的图片源。</dd>
 <dt><strong style="font-weight:bold">{{domxref("ImageBitmap")}}</strong></dt>
 <dd>这是一个高性能的位图,可以低延迟地绘制,它可以从上述的所有源以及其它几种源中生成。</dd>
</dl>

<p>这些源统一由&nbsp;{{domxref("CanvasImageSource")}}类型来引用。</p>

<p>有几种方式可以获取到我们需要在canvas上使用的图片。</p>

<h3 id="Using_images_which_are_on_the_same_page" name="Using_images_which_are_on_the_same_page">使用相同页面内的图片</h3>

<p>我们可以通过下列方法的一种来获得与canvas相同页面内的图片的引用:</p>

<ul>
 <li>{{domxref("document.images")}}集合</li>
 <li>&nbsp;{{domxref("document.getElementsByTagName()")}}方法</li>
 <li>如果你知道你想使用的指定图片的ID,你可以用{{domxref("document.getElementById()")}}获得这个图片</li>
</ul>

<h3 id="Using_other_canvas_elements" name="Using_other_canvas_elements">使用其它域名下的图片</h3>

<p>在&nbsp;{{domxref("HTMLImageElement")}}上使用<a href="https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes">crossOrigin</a>属性,你可以请求加载其它域名上的图片。如果图片的服务器允许跨域访问这个图片,那么你可以使用这个图片而不污染canvas,否则,使用这个图片将会<a href="https://developer.mozilla.org/zh-CN/docs/CORS_Enabled_Image#.E4.BB.80.E4.B9.88.E6.98.AF.22.E8.A2.AB.E6.B1.A1.E6.9F.93.22.E7.9A.84canvas">污染canvas</a>。</p>

<h3 id="Using_other_canvas_elements" name="Using_other_canvas_elements">使用其它 canvas 元素</h3>

<p><span style="line-height:1.5">和引用页面内的图片类似地,用 </span><code style="font-style: normal; line-height: 1.5;"><a href="/en/DOM/document.getElementsByTagName" title="en/DOM/document.getElementsByTagName">document.getElementsByTagName</a> </code><span style="line-height:1.5">或 </span><code style="font-style: normal; line-height: 1.5;"><a href="/en/DOM/document.getElementById" title="en/DOM/document.getElementById">document.getElementById</a> </code><span style="line-height:1.5">方法来获取其它 canvas 元素。但你引入的应该是已经准备好的 canvas。</span></p>

<p><span style="line-height:1.5">一个常用的应用就是将第二个canvas作为另一个大的 canvas 的缩略图。</span></p>

<h3 id="Creating_an_image_from_scratch" name="Creating_an_image_from_scratch">由零开始创建图像</h3>

<p>或者我们可以用脚本创建一个新的 {{domxref("HTMLImageElement")}} 对象。要实现这个方法,我们可以使用很方便的<code>Image()构造函数。</code></p>

<pre class="brush: js">
var img = new Image();   // 创建一个&lt;img&gt;元素
img.src = 'myImage.png'; // 设置图片源地址
</pre>

<p>当脚本执行后,图片开始装载。</p>

<p>若调用 <code>drawImage</code> 时,图片没装载完,那什么都不会发生(在一些旧的浏览器中可能会抛出异常)。因此你应该用load时间来保证不会在加载完毕之前使用这个图片:</p>

<pre class="brush: js">
var img = new Image();   // 创建img元素
img.onload = function(){
  // 执行drawImage语句
}
img.src = 'myImage.png'; // 设置图片源地址
</pre>

<p><span style="line-height:1.5">如果你只用到一张图片的话,这已经够了。但一旦需要不止一张图片,那就需要更加复杂的处理方法,但图片预装载策略超出本教程的范围,感兴趣的话可以参考</span><a class="external" href="https://www.webreference.com/programming/javascript/gr/column3/" style="line-height: 1.5;">JavaScript Image Preloader</a><span style="line-height:1.5">。</span></p>

<h3 id="Embedding_an_image_via_data:_url" name="Embedding_an_image_via_data:_url">通过 data: url 方式嵌入图像</h3>

<p>我们还可以通过&nbsp;<a class="external" href="https://en.wikipedia.org/wiki/Data:_URL">data:url</a>&nbsp;方式来引用图像。Data urls 允许用一串 Base64 编码的字符串的方式来定义一个图片。</p>

<pre class="brush: js">
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
</pre>

<p name="drawImage">其优点就是图片内容即时可用,无须再到服务器兜一圈。(还有一个优点是,可以将 CSS,JavaScript,HTML 和 图片全部封装在一起,迁移起来十分方便。)缺点就是图像没法缓存,图片大的话内嵌的 url 数据会相当的长:</p>

<h3 id="drawImage" name="drawImage">使用视频帧</h3>

<p>你还可以使用{{HTMLElement("video")}} 中的视频帧(即便视频是不可见的)。例如,如果你有一个ID为“myvideo”的{{HTMLElement("video")}} 元素,你可以这样做:</p>

<pre class="brush: js  language-js" data-number="" style="padding: 1em 0px 1em 30px; border-left-width: 6px; border-left-style: solid; border-left-color: rgba(0, 83, 159, 0.65098); font-family: Consolas, Monaco, 'Andale Mono', monospace; font-size: 14px; direction: ltr; white-space: normal; word-break: normal; tab-size: 4; text-shadow: none; background-image: url(https://developer.cdn.mozilla.net/media/redesign/img/blueprint-dark.png); background-color: rgba(234, 239, 242, 0.247059); background-position: 50% 0%;">
<code class="language-js" style="font-family: Consolas, Monaco, 'Andale Mono', monospace; direction: ltr; white-space: pre; word-spacing: normal; word-break: normal; tab-size: 4; color: inherit; text-shadow: none;"><span class="keyword token" style="color:rgb(0, 119, 170)">function</span> <span class="function token">getMyVideo<span class="punctuation token" style="color:rgb(153, 153, 153)">(</span></span><span class="punctuation token" style="color:rgb(153, 153, 153)">)</span> <span class="punctuation token" style="color:rgb(153, 153, 153)">{</span>
  <span class="keyword token" style="color:rgb(0, 119, 170)">var</span> canvas <span class="operator token" style="background:rgba(255, 255, 255, 0.498039); color:rgb(166, 127, 89)">=</span> document<span class="punctuation token" style="color:rgb(153, 153, 153)">.</span><span class="function token">getElementById<span class="punctuation token" style="color:rgb(153, 153, 153)">(</span></span><span class="string token" style="color:rgb(102, 153, 0)">'canvas'</span><span class="punctuation token" style="color:rgb(153, 153, 153)">)</span><span class="punctuation token" style="color:rgb(153, 153, 153)">;</span>
  <span class="keyword token" style="color:rgb(0, 119, 170)">if</span> <span class="punctuation token" style="color:rgb(153, 153, 153)">(</span>canvas<span class="punctuation token" style="color:rgb(153, 153, 153)">.</span>getContext<span class="punctuation token" style="color:rgb(153, 153, 153)">)</span> <span class="punctuation token" style="color:rgb(153, 153, 153)">{</span>
    <span class="keyword token" style="color:rgb(0, 119, 170)">var</span> ctx <span class="operator token" style="background:rgba(255, 255, 255, 0.498039); color:rgb(166, 127, 89)">=</span> canvas<span class="punctuation token" style="color:rgb(153, 153, 153)">.</span><span class="function token">getContext<span class="punctuation token" style="color:rgb(153, 153, 153)">(</span></span><span class="string token" style="color:rgb(102, 153, 0)">'2d'</span><span class="punctuation token" style="color:rgb(153, 153, 153)">)</span><span class="punctuation token" style="color:rgb(153, 153, 153)">;</span>

    <span class="keyword token" style="color:rgb(0, 119, 170)">return</span> document<span class="punctuation token" style="color:rgb(153, 153, 153)">.</span><span class="function token">getElementById<span class="punctuation token" style="color:rgb(153, 153, 153)">(</span></span><span class="string token" style="color:rgb(102, 153, 0)">'myvideo'</span><span class="punctuation token" style="color:rgb(153, 153, 153)">)</span><span class="punctuation token" style="color:rgb(153, 153, 153)">;</span>
  <span class="punctuation token" style="color:rgb(153, 153, 153)">}</span>
<span class="punctuation token" style="color:rgb(153, 153, 153)">}</span></code></pre>

<p name="drawImage">它将为这个视频返回{{domxref("HTMLVideoElement")}}对象,正如我们前面提到的,它可以作为我们的Canvas图片源。</p>

<h2 id="drawImage" name="drawImage">绘制图片</h2>

<p><span style="line-height:1.5">一旦获得了源图对象,我们就可以使用 </span><code style="font-style: normal; line-height: 1.5;">drawImage</code><span style="line-height:1.5"> 方法将它渲染到 canvas 里。</span><code style="font-style: normal; line-height: 1.5;">drawImage</code><span style="line-height:1.5"> 方法有三种形态,下面是最基础的一种。</span></p>

<dl>
 <dt><strong><code>drawImage(image, x, y)</code></strong></dt>
 <dd><span style="line-height:1.5">其中 </span><code style="font-style: normal; line-height: 1.5;">image</code><span style="line-height:1.5"> 是 image 或者 canvas 对象,</span><code style="font-style: normal; line-height: 1.5;">x</code><span style="line-height:1.5"> 和 </span><code style="font-style: normal; line-height: 1.5;">y 是其在目标 canvas 里的起始坐标。</code></dd>
</dl>

<h3 id="drawImage_example_1" name="drawImage_example_1">例子:一个简单的线图</h3>

<p><img alt="" class="internal" src="/@api/deki/files/58/=Canvas_backdrop.png" style="float:right" /></p>

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

<pre class="brush: js">
  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';
  }
</pre>

<p>结果看起来是这样的:</p>

<p>{{EmbedLiveSample("drawImage_example_1", 220, 160, "https://mdn.mozillademos.org/files/206/Canvas_backdrop.png")}}</p>

<h2 id="Scaling" name="Scaling">缩放 Scaling</h2>

<p><code>drawImage</code> 方法的又一变种是增加了两个用于控制图像在 canvas 中缩放的参数。</p>

<dl>
 <dt>{{domxref("CanvasRenderingContext2D.drawImage", "drawImage(image, x, y, width, height)")}}</dt>
 <dd>这个方法多了2个参数:<code>width</code>&nbsp;和&nbsp;<code>height,</code>这两个参数用来控制&nbsp;当像canvas画入时应该缩放的大小</dd>
</dl>

<h4 id="drawImage_example_2" name="drawImage_example_2"><code>drawImage</code> 示例 2</h4>

<p><img alt="" class="internal" src="/@api/deki/files/106/=Canvas_scale_image.png" style="float:right" /></p>

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

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

<p>{{EmbedLiveSample("Example_Tiling_an_image", 160, 160, "https://mdn.mozillademos.org/files/251/Canvas_scale_image.png")}}</p>

<pre>
<code>function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var img = new Image();
  img.onload = function(){
    for (var i=0;i&lt;4;i++){
      for (var j=0;j&lt;3;j++){
        ctx.drawImage(img,j*50,i*38,50,38);
      }
    }
  };
  img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
}</code></pre>

<h2 id="Slicing" name="Slicing">切片 Slicing</h2>

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

<dl>
 <dt>{{domxref("CanvasRenderingContext2D.drawImage", "drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)")}}</dt>
 <dd>第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。</dd>
</dl>

<p><img alt="" class="internal" src="/@api/deki/files/79/=Canvas_drawimage.jpg" style="float:right" /></p>

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

<h4 id="drawImage_example_3" name="drawImage_example_3"><code>drawImage</code> 示例 3</h4>

<p><img alt="" class="internal" src="/@api/deki/files/80/=Canvas_drawimage2.jpg" style="float:right" /></p>

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

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

<p>{{EmbedLiveSample("Example_Framing_an_image", 160, 160, "https://mdn.mozillademos.org/files/226/Canvas_drawimage2.jpg")}}</p>

<pre class="brush: js">
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);
}
</pre>

<h2 id="Art_gallery_example" name="Art_gallery_example">示例:画廊 Art gallery example</h2>

<p><img alt="" class="internal" src="/@api/deki/files/57/=Canvas_art_gallery.jpg" style="float:right" /></p>

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

<p>在我这个例子里面,所有“画”都是固定宽高的,画框也是。你可以做些改进,通过脚本用画的宽高来准确控制围绕它的画框的大小。</p>

<p>下面的代码应该是蛮简单易懂的了。就是遍历图像对象数组,依次创建新的 canvas 元素并添加进去。可能唯一需要注意的,对于那些并不熟悉 DOM 的朋友来说,是 <code><a href="/En/DOM/Node.insertBefore" title="en/DOM/element.insertBefore">insertBefore</a></code> 方法的用法。<code>insertBefore</code> 是父节点(单元格)的方法,用于将新节点(canvas 元素)插入到我们想要插入的节点之前。</p>

<p>{{EmbedLiveSample("Art_gallery_example", 725, 400)}}</p>

<pre class="brush: js">
function draw() {

  // Loop through all images
  for (i=0;i&lt;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);
    }
  }
}
</pre>

<h2 id="控制图像的缩放行为_Controlling_image_scaling_behavior">控制图像的缩放行为 Controlling image scaling behavior</h2>

<p>{{ gecko_minversion_header("1.9.2") }}</p>

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

<pre class="brush: js">
cx.mozImageSmoothingEnabled = false;
</pre>

<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_text", "Web/API/Canvas_API/Tutorial/Transformations")}}</p>
恢复到这个版本