aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/canvasrenderingcontext2d/drawimage/index.html
blob: b0d477e9e87f25dc8f1b218865621a561e65dc6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
---
title: CanvasRenderingContext2D.drawImage()
slug: Web/API/CanvasRenderingContext2D/drawImage
tags:
  - API
  - Canvas
  - CanvasRenderingContext2D
  - Refer
translation_of: Web/API/CanvasRenderingContext2D/drawImage
---
<div>{{APIRef}}</div>

<p>Canvas 2D API 中的 <code><strong>CanvasRenderingContext2D</strong></code><strong><code>.drawImage()</code></strong> 方法提供了多种方式在Canvas上绘制图像。</p>

<h2 id="语法">语法</h2>

<pre class="syntaxbox">void <var><em>ctx</em>.drawImage(image, dx, dy);</var>
void <var><em>ctx</em>.drawImage(image, dx, dy, dWidth, dHeight);</var>
void <var><em>ctx</em>.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);</var>
</pre>

<p><img alt="drawImage" src="https://mdn.mozillademos.org/files/225/Canvas_drawimage.jpg" style="float: right;"></p>

<h3 id="参数">参数</h3>

<dl>
 <dt><code>image</code></dt>
 <dd>绘制到上下文的元素。允许任何的 canvas 图像源({{domxref("CanvasImageSource")}}),例如:{{domxref("CSSImageValue")}}{{domxref("HTMLImageElement")}}{{domxref("SVGImageElement")}}{{domxref("HTMLVideoElement")}}{{domxref("HTMLCanvasElement")}}{{domxref("ImageBitmap")}} 或者{{domxref("OffscreenCanvas")}}</dd>
 <dt><code>sx</code>{{optional_inline}}</dt>
 <dd>需要绘制到目标上下文中的,<code>image</code>的矩形(裁剪)选择框的左上角 X 轴坐标。</dd>
 <dt><code>sy</code>{{optional_inline}}</dt>
 <dd>需要绘制到目标上下文中的,<code>image</code>的矩形(裁剪)选择框的左上角 Y 轴坐标。</dd>
 <dt><code>sWidth</code>{{optional_inline}}</dt>
 <dd>需要绘制到目标上下文中的,<code>image</code>的矩形(裁剪)选择框的宽度。如果不说明,整个矩形(裁剪)从坐标的<code>sx</code><code>sy</code>开始,到<code>image</code>的右下角结束。</dd>
 <dt><code>sHeight</code>{{optional_inline}}</dt>
 <dd>需要绘制到目标上下文中的,<code>image</code>的矩形(裁剪)选择框的高度。</dd>
 <dt><code>dx</code></dt>
 <dd><code>image</code>的左上角在目标canvas上 X 轴坐标。</dd>
 <dt><code>dy</code></dt>
 <dd><code>image</code>的左上角在目标canvas上 Y 轴坐标。</dd>
 <dt><code>dWidth</code>{{optional_inline}}</dt>
 <dd><code>image</code>在目标canvas上绘制的宽度。 允许对绘制的<code>image</code>进行缩放。 如果不说明, 在绘制时<code>image</code>宽度不会缩放。</dd>
 <dt><code>dHeight</code>{{optional_inline}}</dt>
 <dd><code>image</code>在目标canvas上绘制的高度。 允许对绘制的<code>image</code>进行缩放。 如果不说明, 在绘制时<code>image</code>高度不会缩放。</dd>
</dl>

<h3 id="抛出异常">抛出异常</h3>

<dl>
 <dt><code>INDEX_SIZE_ERR</code></dt>
 <dd>如果 canvas 或者图像矩形区域的宽度或高度为0 。</dd>
 <dt><code>INVALID_STATE_ERR</code></dt>
 <dd>图像没有数据。</dd>
 <dt><code>TYPE_MISMATCH_ERR</code></dt>
 <dd>提供的原始元素不支持。</dd>
 <dt><code>NS_ERROR_NOT_AVAILABLE</code></dt>
 <dd>图像尚未加载。使用<code>.complete === true</code><code>.onload</code>确定何时准备就绪。</dd>
</dl>

<h2 id="示例">示例</h2>

<h3 id="使用_drawImage_方法">使用 <code>drawImage</code> 方法</h3>

<p>这是一段使用 <code>drawImage</code> 方法的简单的代码片段。</p>

<h4 id="HTML">HTML</h4>

<pre class="brush: html">&lt;canvas id="canvas"&gt;&lt;/canvas&gt;
&lt;div style="display:none;"&gt;
  &lt;img id="source" src="https://mdn.mozillademos.org/files/5397/rhino.jpg"
       width="300" height="227"&gt;
&lt;/div&gt;
</pre>

<h4 id="JavaScript">JavaScript</h4>

<pre class="brush: js; highlight:[5]">var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image = document.getElementById('source');

ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
</pre>

<div class="hidden">
<h2 id="Drawing_an_image_to_the_canvas">Drawing_an_image_to_the_canvas</h2>

<h3 id="HTML_2">HTML</h3>

<pre class="brush: html">&lt;canvas id="canvas"&gt;&lt;/canvas&gt;
&lt;div style="display:none;"&gt;
  &lt;img id="source"
       src="https://mdn.mozillademos.org/files/5397/rhino.jpg"
       width="300" height="227"&gt;
&lt;/div&gt;</pre>



<h3 id="JavaScript_2">JavaScript</h3>

<pre class="brush: js">const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = document.getElementById('source');

image.addEventListener('load', e =&gt; {
  ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
});
</pre>
</div>

<h4 id="结果">结果</h4>

<div style="display: none;">
<h6 id="Playable_code">Playable code</h6>

<pre class="brush: html">&lt;canvas id="canvas" width="400" height="200" class="playable-canvas"&gt;&lt;/canvas&gt;
&lt;div style="display:none;"&gt;
  &lt;img id="source" src="https://mdn.mozillademos.org/files/5397/rhino.jpg" width="300" height="227"&gt;
&lt;/div&gt;
&lt;div class="playable-buttons"&gt;
  &lt;input id="edit" type="button" value="Edit" /&gt;
  &lt;input id="reset" type="button" value="Reset" /&gt;
&lt;/div&gt;
&lt;textarea id="code" class="playable-code"&gt;
ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);&lt;/textarea&gt;
</pre>

<pre class="brush: js">var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image = document.getElementById('source');
var textarea = document.getElementById("code");
var reset = document.getElementById("reset");
var edit = document.getElementById("edit");
var code = textarea.value;

function drawCanvas() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  eval(textarea.value);
}

reset.addEventListener("click", function() {
  textarea.value = code;
  drawCanvas();
});

edit.addEventListener("click", function() {
  textarea.focus();
})

textarea.addEventListener("input", drawCanvas);
window.addEventListener("load", drawCanvas);
</pre>
</div>

<p>{{ EmbedLiveSample('Drawing_an_image_to_the_canvas', 700, 180) }}</p>

<h3 id="理解源元素大小">理解源元素大小</h3>

<p><code>drawImage()</code>方法在绘制时使用源元素的CSS大小。</p>

<p>例如,如果加载图像并在其构造函数中指定可选的大小参数,则必须使用所创建实例的<code>naturalWidth</code><code>naturalHeight</code>属性来正确计算裁剪和缩放区域等内容,而不是<code>element.width</code><code>element.height</code>。如果元素是{{htmlelement("video")}} 元素,则<code>videoWidth</code><code>videoHeight</code>也是如此,依此类推。</p>

<h4 id="HTML_3">HTML</h4>

<pre class="brush: html"><code>&lt;canvas id="canvas"&gt;&lt;/canvas&gt;</code></pre>

<h4 id="JavaScript_3">JavaScript</h4>

<pre class="brush: js"><code>const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const image = new Image(60, 45); // Using optional size for image
image.onload = drawImageActualSize; // Draw when image has loaded

// Load an image of intrinsic size 300x227 in CSS pixels
image.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';

function drawImageActualSize() {
  // Use the intrinsic size of image in CSS pixels for the canvas element
  canvas.width = this.naturalWidth;
  canvas.height = this.naturalHeight;

  // Will draw the image as 300x227, ignoring the custom size of 60x45
  // given in the constructor
  ctx.drawImage(this, 0, 0);

  // To use the custom size we'll have to specify the scale parameters
  // using the element's width and height properties - lets draw one
  // on top in the corner:
  ctx.drawImage(this, 0, 0, this.width, this.height);
}</code>
</pre>

<div class="hidden">
<h2 id="Understanding_source_element_size">Understanding_source_element_size</h2>

<h3 id="HTML_4">HTML</h3>

<pre class="brush: html">&lt;canvas id="canvas"&gt;&lt;/canvas&gt;
</pre>

<h3 id="JavaScript_4">JavaScript</h3>

<pre class="brush: js">const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const image = new Image(60, 45); // Using optional size for image
image.onload = drawImageActualSize; // Draw when image has loaded

// Load an image of intrinsic size 300x227 in CSS pixels
image.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';

function drawImageActualSize() {
  // Use the intrinsic size of image in CSS pixels for the canvas element
  canvas.width = this.naturalWidth;
  canvas.height = this.naturalHeight;

  // Will draw the image as 300x227, ignoring the custom size of 60x45
  // given in the constructor
  ctx.drawImage(this, 0, 0);

  // To use the custom size we'll have to specify the scale parameters
  // using the element's width and height properties - lets draw one
  // on top in the corner:
  ctx.drawImage(this, 0, 0, this.width, this.height);
}
</pre>
</div>

<h4 id="结果_2">结果</h4>

<p>{{EmbedLiveSample('Understanding_source_element_size', 700, 260)}}</p>

<h2 id="规范说明">规范说明</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('HTML WHATWG', "scripting.html#dom-context-2d-drawimage", "CanvasRenderingContext2D.drawImage")}}</td>
   <td>{{Spec2('HTML WHATWG')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容性">浏览器兼容性</h2>

<p>{{Compat("api.CanvasRenderingContext2D.drawImage")}}</p>

<h3 id="兼容性注解">兼容性注解</h3>

<ul>
 <li>在 Gecko 5.0 {{geckoRelease("5.0")}}中,支持通过给 sw 和 sh 赋负值,对图像进行翻转。</li>
 <li>{{geckoRelease("5.0")}} 开始,<code>drawImage()</code> 按照规范处理负参数,沿着合适的轴翻转矩形。</li>
 <li>{{geckoRelease("5.0")}}开始,当<span style="font-family: consolas,monaco,andale mono,monospace;">drawImage()</span>调用 <code>null</code> 或者 <code>undefined</code> 图像时,会抛出 <code>TYPE_MISMATCH_ERR</code> 异常。</li>
 <li>在 Gecko 7.0 {{ geckoRelease("7.0") }}之前, 如果坐标值是非规定值或者是0,Firefox 会抛出一个异常。 按照规范描述,这种情况不会再发生。</li>
 <li>Gecko 9.0 {{ geckoRelease("9.0") }}现在完全支持 CORS 跨域绘制图像,不需要<a href="/en/CORS_Enabled_Image#What_is_a_.22tainted.22_canvas.3F" title="en/CORS_Enabled_Image#What_is_a_.22tainted.22_canvas.3F">污染的 canvas</a>.</li>
 <li>Gecko 11.0 {{ geckoRelease("11.0") }} 现在允许 SVG 作为图像被绘制到 canvas ,不需要 <a href="/en/CORS_Enabled_Image#What_is_a_.22tainted.22_canvas.3F" title="en/CORS_Enabled_Image#What_is_a_.22tainted.22_canvas.3F">污染的 canvas</a>.</li>
</ul>

<h2 id="Notes">Notes</h2>

<ul>
 <li><code>drawImage()</code>需要在{{domxref("HTMLVideoElement")}}工作时,仅当{{domxref("HTMLMediaElement.readyState")}}大于1时<code>drawImage()</code>才能正常工作。</li>
 <li>在绘制,裁剪和/或缩放时,<code>drawImage()</code> 将始终使用CSS像素中源元素的固有尺寸。</li>
 <li><code>drawImage()</code>将忽略图像中的所有EXIF元数据,包括方向。 此行为在iOS设备上尤其麻烦。 您应该自己检测方向并使用<code>rotate()</code>使其正确。</li>
</ul>

<h2 id="参见">参见</h2>

<ul>
 <li>接口定义, {{domxref("CanvasRenderingContext2D")}}.</li>
</ul>