0
# Canvas APIs
1
2
Canvas drawing and manipulation APIs providing basic HTML5 Canvas operations with Mini Program compatibility for 2D graphics and image processing.
3
4
## Capabilities
5
6
### Canvas Context Creation
7
8
Create and manage canvas contexts for drawing operations.
9
10
```typescript { .api }
11
/**
12
* Create canvas context for drawing operations
13
* @param canvasId - Canvas element ID
14
* @param componentInstance - Component instance (optional in H5)
15
* @returns Canvas rendering context
16
*/
17
function createCanvasContext(canvasId: string, componentInstance?: any): CanvasContext;
18
19
interface CanvasContext {
20
// Drawing operations
21
fillRect(x: number, y: number, width: number, height: number): void;
22
strokeRect(x: number, y: number, width: number, height: number): void;
23
clearRect(x: number, y: number, width: number, height: number): void;
24
25
// Path operations
26
beginPath(): void;
27
closePath(): void;
28
moveTo(x: number, y: number): void;
29
lineTo(x: number, y: number): void;
30
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
31
32
// Styles
33
setFillStyle(color: string): void;
34
setStrokeStyle(color: string): void;
35
setLineWidth(lineWidth: number): void;
36
37
// Text
38
fillText(text: string, x: number, y: number, maxWidth?: number): void;
39
strokeText(text: string, x: number, y: number, maxWidth?: number): void;
40
setFontSize(fontSize: number): void;
41
42
// Images
43
drawImage(imageResource: string, x: number, y: number): void;
44
drawImage(imageResource: string, x: number, y: number, width: number, height: number): void;
45
46
// Execute drawing
47
draw(reserve?: boolean, callback?: () => void): void;
48
}
49
```
50
51
### Canvas Image Operations
52
53
Extract and manipulate image data from canvas elements.
54
55
```typescript { .api }
56
/**
57
* Convert canvas content to temporary file path
58
* @param options - Canvas export configuration
59
* @returns Promise resolving to temporary file path
60
*/
61
function canvasToTempFilePath(options: CanvasToTempFilePathOption): Promise<CanvasToTempFilePathResult>;
62
63
/**
64
* Get image data from canvas
65
* @param options - Image data retrieval configuration
66
* @returns Promise resolving to image data
67
*/
68
function canvasGetImageData(options: CanvasGetImageDataOption): Promise<CanvasGetImageDataResult>;
69
70
/**
71
* Put image data to canvas
72
* @param options - Image data insertion configuration
73
* @returns Promise that resolves when data is inserted
74
*/
75
function canvasPutImageData(options: CanvasPutImageDataOption): Promise<void>;
76
77
interface CanvasToTempFilePathOption extends CallbackOptions {
78
/** Canvas element ID */
79
canvasId: string;
80
/** Image file type (default: 'png') */
81
fileType?: 'jpg' | 'png';
82
/** Image quality (0-1, for jpg only) */
83
quality?: number;
84
/** Export width (default: canvas width) */
85
destWidth?: number;
86
/** Export height (default: canvas height) */
87
destHeight?: number;
88
}
89
90
interface CanvasToTempFilePathResult {
91
/** Temporary file path */
92
tempFilePath: string;
93
}
94
95
interface CanvasGetImageDataOption extends CallbackOptions {
96
/** Canvas element ID */
97
canvasId: string;
98
/** Start x coordinate */
99
x: number;
100
/** Start y coordinate */
101
y: number;
102
/** Width of image data area */
103
width: number;
104
/** Height of image data area */
105
height: number;
106
}
107
108
interface CanvasGetImageDataResult {
109
/** Image data array */
110
data: Uint8ClampedArray;
111
/** Image width */
112
width: number;
113
/** Image height */
114
height: number;
115
}
116
117
interface CanvasPutImageDataOption extends CallbackOptions {
118
/** Canvas element ID */
119
canvasId: string;
120
/** Image data array */
121
data: Uint8ClampedArray;
122
/** Start x coordinate */
123
x: number;
124
/** Start y coordinate */
125
y: number;
126
/** Image width */
127
width: number;
128
/** Image height */
129
height: number;
130
}
131
```
132
133
**Usage Examples:**
134
135
```typescript
136
import {
137
createCanvasContext,
138
canvasToTempFilePath,
139
canvasGetImageData,
140
canvasPutImageData
141
} from "@tarojs/taro-h5";
142
143
// Basic canvas drawing
144
function drawOnCanvas() {
145
const ctx = createCanvasContext('myCanvas');
146
147
// Set styles
148
ctx.setFillStyle('#ff0000');
149
ctx.setStrokeStyle('#00ff00');
150
ctx.setLineWidth(2);
151
152
// Draw shapes
153
ctx.fillRect(10, 10, 100, 100);
154
ctx.strokeRect(120, 10, 100, 100);
155
156
// Draw circle
157
ctx.beginPath();
158
ctx.arc(75, 200, 50, 0, 2 * Math.PI);
159
ctx.setFillStyle('#0000ff');
160
ctx.fill();
161
162
// Draw text
163
ctx.setFontSize(20);
164
ctx.setFillStyle('#000000');
165
ctx.fillText('Hello Canvas', 10, 300);
166
167
// Execute drawing
168
ctx.draw();
169
}
170
171
// Export canvas as image
172
async function exportCanvas() {
173
try {
174
const result = await canvasToTempFilePath({
175
canvasId: 'myCanvas',
176
fileType: 'png',
177
quality: 1.0
178
});
179
180
console.log('Canvas exported to:', result.tempFilePath);
181
return result.tempFilePath;
182
} catch (error) {
183
console.error('Canvas export failed:', error);
184
}
185
}
186
187
// Image data manipulation
188
async function manipulateImageData() {
189
try {
190
// Get image data
191
const imageData = await canvasGetImageData({
192
canvasId: 'myCanvas',
193
x: 0,
194
y: 0,
195
width: 300,
196
height: 300
197
});
198
199
// Modify pixel data (invert colors)
200
const data = new Uint8ClampedArray(imageData.data);
201
for (let i = 0; i < data.length; i += 4) {
202
data[i] = 255 - data[i]; // Red
203
data[i + 1] = 255 - data[i + 1]; // Green
204
data[i + 2] = 255 - data[i + 2]; // Blue
205
// Alpha channel (i + 3) unchanged
206
}
207
208
// Put modified data back
209
await canvasPutImageData({
210
canvasId: 'myCanvas',
211
data: data,
212
x: 0,
213
y: 0,
214
width: imageData.width,
215
height: imageData.height
216
});
217
218
console.log('Image data modified successfully');
219
} catch (error) {
220
console.error('Image data manipulation failed:', error);
221
}
222
}
223
```
224
225
### Not Implemented Canvas APIs
226
227
The following canvas APIs are not available in the H5 environment:
228
229
```typescript
230
// ❌ Not implemented - Advanced canvas features
231
declare function createOffscreenCanvas(): never;
232
```
233
234
**Note**: `createOffscreenCanvas` is not supported in the H5 environment due to browser compatibility limitations. Use regular canvas elements with `createCanvasContext` instead.
235
236
## Advanced Canvas Patterns
237
238
Complex canvas operations and optimization techniques.
239
240
```typescript
241
// Canvas drawing manager
242
class CanvasManager {
243
private context: CanvasContext;
244
private canvasId: string;
245
246
constructor(canvasId: string) {
247
this.canvasId = canvasId;
248
this.context = createCanvasContext(canvasId);
249
}
250
251
// Batch drawing operations
252
batchDraw(operations: (() => void)[], reserve = false): Promise<void> {
253
return new Promise((resolve) => {
254
operations.forEach(op => op());
255
this.context.draw(reserve, () => resolve());
256
});
257
}
258
259
// Draw image with error handling
260
async drawImageSafe(imageSrc: string, x: number, y: number, width?: number, height?: number): Promise<boolean> {
261
return new Promise((resolve) => {
262
try {
263
if (width !== undefined && height !== undefined) {
264
this.context.drawImage(imageSrc, x, y, width, height);
265
} else {
266
this.context.drawImage(imageSrc, x, y);
267
}
268
this.context.draw(false, () => resolve(true));
269
} catch (error) {
270
console.error('Failed to draw image:', error);
271
resolve(false);
272
}
273
});
274
}
275
276
// Clear canvas
277
clear(width: number, height: number): Promise<void> {
278
return new Promise((resolve) => {
279
this.context.clearRect(0, 0, width, height);
280
this.context.draw(false, () => resolve());
281
});
282
}
283
284
// Export canvas
285
async exportAsImage(options: Partial<CanvasToTempFilePathOption> = {}): Promise<string | null> {
286
try {
287
const result = await canvasToTempFilePath({
288
canvasId: this.canvasId,
289
fileType: 'png',
290
quality: 1.0,
291
...options
292
});
293
return result.tempFilePath;
294
} catch (error) {
295
console.error('Canvas export failed:', error);
296
return null;
297
}
298
}
299
}
300
301
// Usage
302
const canvasManager = new CanvasManager('drawingCanvas');
303
304
// Batch drawing
305
await canvasManager.batchDraw([
306
() => {
307
canvasManager.context.setFillStyle('#ff0000');
308
canvasManager.context.fillRect(0, 0, 100, 100);
309
},
310
() => {
311
canvasManager.context.setFillStyle('#00ff00');
312
canvasManager.context.fillRect(100, 0, 100, 100);
313
}
314
]);
315
316
// Safe image drawing
317
const success = await canvasManager.drawImageSafe('/path/to/image.png', 50, 50, 200, 200);
318
if (success) {
319
console.log('Image drawn successfully');
320
}
321
```
322
323
### Performance Optimization
324
325
Best practices for canvas performance in web environments.
326
327
```typescript
328
// Optimized canvas operations
329
class OptimizedCanvas {
330
private context: CanvasContext;
331
private operations: (() => void)[] = [];
332
private drawPending = false;
333
334
constructor(canvasId: string) {
335
this.context = createCanvasContext(canvasId);
336
}
337
338
// Queue operations for batch execution
339
queueOperation(operation: () => void): void {
340
this.operations.push(operation);
341
this.scheduleDraw();
342
}
343
344
private scheduleDraw(): void {
345
if (this.drawPending) return;
346
347
this.drawPending = true;
348
requestAnimationFrame(() => {
349
// Execute all queued operations
350
this.operations.forEach(op => op());
351
this.operations = [];
352
353
// Single draw call
354
this.context.draw();
355
this.drawPending = false;
356
});
357
}
358
359
// Immediate drawing (use sparingly)
360
drawImmediate(operation: () => void): Promise<void> {
361
return new Promise((resolve) => {
362
operation();
363
this.context.draw(false, () => resolve());
364
});
365
}
366
}
367
368
// Image caching for better performance
369
class ImageCache {
370
private cache = new Map<string, boolean>();
371
372
async preloadImage(src: string): Promise<boolean> {
373
if (this.cache.has(src)) {
374
return true;
375
}
376
377
return new Promise((resolve) => {
378
const img = new Image();
379
img.onload = () => {
380
this.cache.set(src, true);
381
resolve(true);
382
};
383
img.onerror = () => {
384
resolve(false);
385
};
386
img.src = src;
387
});
388
}
389
390
isImageLoaded(src: string): boolean {
391
return this.cache.has(src);
392
}
393
394
async preloadImages(sources: string[]): Promise<boolean[]> {
395
return Promise.all(sources.map(src => this.preloadImage(src)));
396
}
397
}
398
```
399
400
## Error Handling
401
402
Canvas operations can fail due to invalid parameters, missing resources, or browser limitations.
403
404
```typescript
405
// Safe canvas operations
406
async function safeCanvasOperation<T>(
407
operation: () => Promise<T>,
408
fallback?: () => T,
409
errorMessage = 'Canvas operation failed'
410
): Promise<T | null> {
411
try {
412
return await operation();
413
} catch (error: any) {
414
console.error(errorMessage, error);
415
416
await showToast({
417
title: errorMessage,
418
icon: 'error'
419
});
420
421
return fallback ? fallback() : null;
422
}
423
}
424
425
// Usage
426
const imagePath = await safeCanvasOperation(
427
() => canvasToTempFilePath({
428
canvasId: 'myCanvas',
429
fileType: 'png'
430
}).then(result => result.tempFilePath),
431
() => '', // Fallback to empty string
432
'Failed to export canvas'
433
);
434
```
435
436
## Types
437
438
```typescript { .api }
439
interface CallbackOptions {
440
success?: (res: any) => void;
441
fail?: (err: any) => void;
442
complete?: (res: any) => void;
443
}
444
445
type ImageFileType = 'jpg' | 'png';
446
type FillStyle = string | CanvasGradient | CanvasPattern;
447
type StrokeStyle = string | CanvasGradient | CanvasPattern;
448
```