0
# Canvas and Graphics
1
2
2D Canvas and WebGL rendering contexts for graphics, animations, and game development in WeChat Mini Programs.
3
4
## Capabilities
5
6
### Canvas Context Creation
7
8
Create 2D rendering contexts for drawing operations.
9
10
```typescript { .api }
11
interface Wx {
12
/** Create 2D canvas rendering context */
13
createCanvasContext(
14
canvasId: string,
15
componentInstance?: any
16
): CanvasRenderingContext2D;
17
18
/** Convert canvas to temporary file */
19
canvasToTempFilePath(options: CanvasToTempFilePathOption): void;
20
21
/** Get canvas image data */
22
canvasGetImageData(options: CanvasGetImageDataOption): void;
23
24
/** Put canvas image data */
25
canvasPutImageData(options: CanvasPutImageDataOption): void;
26
}
27
28
interface CanvasToTempFilePathOption {
29
/** Canvas component instance */
30
canvas?: any;
31
/** Canvas ID */
32
canvasId?: string;
33
/** Image format */
34
fileType?: 'png' | 'jpg';
35
/** Image quality (0-1) */
36
quality?: number;
37
/** Crop rectangle */
38
x?: number;
39
y?: number;
40
width?: number;
41
height?: number;
42
/** Success callback */
43
success?(res: { tempFilePath: string }): void;
44
/** Failure callback */
45
fail?(res: any): void;
46
/** Completion callback */
47
complete?(res: any): void;
48
}
49
```
50
51
**Usage Examples:**
52
53
```typescript
54
// Create canvas context
55
Page({
56
onReady() {
57
const ctx = wx.createCanvasContext('myCanvas', this);
58
59
// Draw rectangle
60
ctx.fillStyle = '#FF0000';
61
ctx.fillRect(10, 10, 100, 50);
62
63
// Draw text
64
ctx.fillStyle = '#000000';
65
ctx.font = '16px Arial';
66
ctx.fillText('Hello Canvas', 10, 80);
67
68
// Draw to canvas
69
ctx.draw();
70
},
71
72
saveCanvas() {
73
wx.canvasToTempFilePath({
74
canvasId: 'myCanvas',
75
success(res) {
76
wx.saveImageToPhotosAlbum({
77
filePath: res.tempFilePath,
78
success() {
79
wx.showToast({ title: 'Saved to album' });
80
}
81
});
82
}
83
}, this);
84
}
85
});
86
```
87
88
### 2D Canvas Rendering Context
89
90
Complete 2D drawing API with paths, shapes, text, images, and transformations.
91
92
```typescript { .api }
93
interface CanvasRenderingContext2D {
94
/** Canvas width */
95
canvas: {
96
width: number;
97
height: number;
98
};
99
100
// Drawing state
101
/** Fill style (color, gradient, pattern) */
102
fillStyle: string | CanvasGradient | CanvasPattern;
103
/** Stroke style */
104
strokeStyle: string | CanvasGradient | CanvasPattern;
105
/** Line width */
106
lineWidth: number;
107
/** Line cap style */
108
lineCap: 'butt' | 'round' | 'square';
109
/** Line join style */
110
lineJoin: 'miter' | 'round' | 'bevel';
111
/** Miter limit */
112
miterLimit: number;
113
/** Global alpha */
114
globalAlpha: number;
115
/** Global composite operation */
116
globalCompositeOperation: string;
117
118
// Path methods
119
/** Begin new path */
120
beginPath(): void;
121
/** Close current path */
122
closePath(): void;
123
/** Move to point */
124
moveTo(x: number, y: number): void;
125
/** Line to point */
126
lineTo(x: number, y: number): void;
127
/** Quadratic curve to */
128
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
129
/** Bezier curve to */
130
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
131
/** Arc */
132
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
133
/** Arc to */
134
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
135
/** Rectangle path */
136
rect(x: number, y: number, width: number, height: number): void;
137
138
// Drawing methods
139
/** Fill current path */
140
fill(): void;
141
/** Stroke current path */
142
stroke(): void;
143
/** Fill rectangle */
144
fillRect(x: number, y: number, width: number, height: number): void;
145
/** Stroke rectangle */
146
strokeRect(x: number, y: number, width: number, height: number): void;
147
/** Clear rectangle */
148
clearRect(x: number, y: number, width: number, height: number): void;
149
150
// Text methods
151
/** Font style */
152
font: string;
153
/** Text alignment */
154
textAlign: 'left' | 'center' | 'right' | 'start' | 'end';
155
/** Text baseline */
156
textBaseline: 'top' | 'middle' | 'bottom' | 'alphabetic' | 'hanging' | 'ideographic';
157
/** Fill text */
158
fillText(text: string, x: number, y: number, maxWidth?: number): void;
159
/** Stroke text */
160
strokeText(text: string, x: number, y: number, maxWidth?: number): void;
161
/** Measure text */
162
measureText(text: string): { width: number };
163
164
// Image methods
165
/** Draw image */
166
drawImage(
167
image: any,
168
dx: number,
169
dy: number
170
): void;
171
drawImage(
172
image: any,
173
dx: number,
174
dy: number,
175
dWidth: number,
176
dHeight: number
177
): void;
178
drawImage(
179
image: any,
180
sx: number,
181
sy: number,
182
sWidth: number,
183
sHeight: number,
184
dx: number,
185
dy: number,
186
dWidth: number,
187
dHeight: number
188
): void;
189
190
// Transform methods
191
/** Scale */
192
scale(x: number, y: number): void;
193
/** Rotate */
194
rotate(angle: number): void;
195
/** Translate */
196
translate(x: number, y: number): void;
197
/** Transform */
198
transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
199
/** Set transform */
200
setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
201
202
// State methods
203
/** Save state */
204
save(): void;
205
/** Restore state */
206
restore(): void;
207
208
// Gradient and pattern methods
209
/** Create linear gradient */
210
createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
211
/** Create radial gradient */
212
createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
213
/** Create pattern */
214
createPattern(image: any, repetition: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'): CanvasPattern | null;
215
216
// Image data methods
217
/** Get image data */
218
getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;
219
/** Put image data */
220
putImageData(imageData: ImageData, dx: number, dy: number): void;
221
/** Create image data */
222
createImageData(sw: number, sh: number): ImageData;
223
224
// WeChat-specific methods
225
/** Draw to canvas (WeChat Mini Program specific) */
226
draw(reserve?: boolean, callback?: () => void): void;
227
/** Set line dash */
228
setLineDash(segments: number[]): void;
229
/** Get line dash */
230
getLineDash(): number[];
231
/** Line dash offset */
232
lineDashOffset: number;
233
}
234
235
interface CanvasGradient {
236
/** Add color stop */
237
addColorStop(offset: number, color: string): void;
238
}
239
240
interface CanvasPattern {
241
/** Set transform */
242
setTransform?(transform: any): void;
243
}
244
245
interface ImageData {
246
/** Pixel data */
247
readonly data: Uint8ClampedArray;
248
/** Image width */
249
readonly width: number;
250
/** Image height */
251
readonly height: number;
252
}
253
```
254
255
**Usage Examples:**
256
257
```typescript
258
const ctx = wx.createCanvasContext('gameCanvas', this);
259
260
// Draw gradient background
261
const gradient = ctx.createLinearGradient(0, 0, 0, 300);
262
gradient.addColorStop(0, '#FF6B6B');
263
gradient.addColorStop(1, '#4ECDC4');
264
ctx.fillStyle = gradient;
265
ctx.fillRect(0, 0, 300, 300);
266
267
// Draw shapes with transforms
268
ctx.save();
269
ctx.translate(150, 150);
270
ctx.rotate(Math.PI / 4);
271
ctx.fillStyle = '#FFFFFF';
272
ctx.fillRect(-25, -25, 50, 50);
273
ctx.restore();
274
275
// Draw text with custom font
276
ctx.font = 'bold 24px Arial';
277
ctx.textAlign = 'center';
278
ctx.fillStyle = '#000000';
279
ctx.fillText('Game Score: 1500', 150, 50);
280
281
// Draw image
282
const img = canvas.createImage();
283
img.onload = () => {
284
ctx.drawImage(img, 100, 100, 100, 100);
285
ctx.draw();
286
};
287
img.src = '/images/sprite.png';
288
289
// Animation loop
290
let frame = 0;
291
function animate() {
292
ctx.clearRect(0, 0, 300, 300);
293
294
// Animated circle
295
ctx.beginPath();
296
ctx.arc(150 + Math.sin(frame * 0.1) * 50, 150, 20, 0, Math.PI * 2);
297
ctx.fillStyle = '#FF6B6B';
298
ctx.fill();
299
300
ctx.draw(false, () => {
301
frame++;
302
requestAnimationFrame(animate);
303
});
304
}
305
animate();
306
```
307
308
### WebGL Context
309
310
WebGL 1.0 and 2.0 support for advanced 3D graphics.
311
312
```typescript { .api }
313
// WebGL context interfaces (standard WebGL APIs)
314
interface WebGLRenderingContext {
315
// Viewport and drawing
316
viewport(x: number, y: number, width: number, height: number): void;
317
clear(mask: number): void;
318
clearColor(red: number, green: number, blue: number, alpha: number): void;
319
clearDepth(depth: number): void;
320
321
// Buffer operations
322
createBuffer(): WebGLBuffer | null;
323
bindBuffer(target: number, buffer: WebGLBuffer | null): void;
324
bufferData(target: number, data: ArrayBuffer | ArrayBufferView, usage: number): void;
325
326
// Shader operations
327
createShader(type: number): WebGLShader | null;
328
shaderSource(shader: WebGLShader, source: string): void;
329
compileShader(shader: WebGLShader): void;
330
createProgram(): WebGLProgram | null;
331
attachShader(program: WebGLProgram, shader: WebGLShader): void;
332
linkProgram(program: WebGLProgram): void;
333
useProgram(program: WebGLProgram | null): void;
334
335
// Drawing
336
drawArrays(mode: number, first: number, count: number): void;
337
drawElements(mode: number, count: number, type: number, offset: number): void;
338
339
// Constants
340
readonly VERTEX_SHADER: number;
341
readonly FRAGMENT_SHADER: number;
342
readonly ARRAY_BUFFER: number;
343
readonly ELEMENT_ARRAY_BUFFER: number;
344
readonly STATIC_DRAW: number;
345
readonly TRIANGLES: number;
346
}
347
348
interface WebGL2RenderingContext extends WebGLRenderingContext {
349
// WebGL 2.0 specific methods
350
drawArraysInstanced(mode: number, first: number, count: number, instanceCount: number): void;
351
drawElementsInstanced(mode: number, count: number, type: number, offset: number, instanceCount: number): void;
352
353
// Transform feedback
354
createTransformFeedback(): WebGLTransformFeedback | null;
355
deleteTransformFeedback(transformFeedback: WebGLTransformFeedback): void;
356
bindTransformFeedback(target: number, transformFeedback: WebGLTransformFeedback | null): void;
357
beginTransformFeedback(primitiveMode: number): void;
358
endTransformFeedback(): void;
359
360
// Uniform buffer objects
361
bindBufferBase(target: number, index: number, buffer: WebGLBuffer | null): void;
362
getUniformBlockIndex(program: WebGLProgram, uniformBlockName: string): number;
363
uniformBlockBinding(program: WebGLProgram, uniformBlockIndex: number, uniformBlockBinding: number): void;
364
365
// Vertex array objects
366
createVertexArray(): WebGLVertexArrayObject | null;
367
deleteVertexArray(vertexArray: WebGLVertexArrayObject): void;
368
bindVertexArray(vertexArray: WebGLVertexArrayObject | null): void;
369
370
// Texture features
371
texStorage2D(target: number, levels: number, internalformat: number, width: number, height: number): void;
372
texStorage3D(target: number, levels: number, internalformat: number, width: number, height: number, depth: number): void;
373
}
374
```
375
376
**Usage Examples:**
377
378
```typescript
379
// Get WebGL context
380
Component({
381
onReady() {
382
const canvas = this.selectComponent('#glCanvas').node;
383
const gl = canvas.getContext('webgl');
384
385
if (!gl) {
386
console.error('WebGL not supported');
387
return;
388
}
389
390
// Vertex shader source
391
const vertexShaderSource = `
392
attribute vec4 a_position;
393
void main() {
394
gl_Position = a_position;
395
}
396
`;
397
398
// Fragment shader source
399
const fragmentShaderSource = `
400
precision mediump float;
401
void main() {
402
gl_Color = vec4(1.0, 0.0, 0.0, 1.0);
403
}
404
`;
405
406
// Create and compile shaders
407
const vertexShader = this.createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
408
const fragmentShader = this.createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
409
410
// Create program
411
const program = this.createProgram(gl, vertexShader, fragmentShader);
412
413
// Set up geometry
414
const positions = [
415
0.0, 0.5,
416
-0.5, -0.5,
417
0.5, -0.5
418
];
419
420
const positionBuffer = gl.createBuffer();
421
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
422
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
423
424
// Render
425
gl.viewport(0, 0, canvas.width, canvas.height);
426
gl.clearColor(0, 0, 0, 1);
427
gl.clear(gl.COLOR_BUFFER_BIT);
428
429
gl.useProgram(program);
430
431
const positionLocation = gl.getAttribLocation(program, 'a_position');
432
gl.enableVertexAttribArray(positionLocation);
433
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
434
435
gl.drawArrays(gl.TRIANGLES, 0, 3);
436
},
437
438
createShader(gl, type, source) {
439
const shader = gl.createShader(type);
440
gl.shaderSource(shader, source);
441
gl.compileShader(shader);
442
return shader;
443
},
444
445
createProgram(gl, vertexShader, fragmentShader) {
446
const program = gl.createProgram();
447
gl.attachShader(program, vertexShader);
448
gl.attachShader(program, fragmentShader);
449
gl.linkProgram(program);
450
return program;
451
}
452
});
453
```
454
455
### Image Processing
456
457
```typescript { .api }
458
interface Wx {
459
/** Get canvas image data */
460
canvasGetImageData(options: {
461
canvasId: string;
462
x: number;
463
y: number;
464
width: number;
465
height: number;
466
success?(res: { data: Uint8ClampedArray; width: number; height: number }): void;
467
fail?(res: any): void;
468
complete?(res: any): void;
469
}): void;
470
471
/** Put canvas image data */
472
canvasPutImageData(options: {
473
canvasId: string;
474
data: Uint8ClampedArray;
475
x: number;
476
y: number;
477
width: number;
478
height: number;
479
success?(): void;
480
fail?(res: any): void;
481
complete?(res: any): void;
482
}): void;
483
}
484
```
485
486
**Usage Examples:**
487
488
```typescript
489
// Image processing
490
function applyFilter() {
491
wx.canvasGetImageData({
492
canvasId: 'imageCanvas',
493
x: 0,
494
y: 0,
495
width: 300,
496
height: 300,
497
success(res) {
498
const imageData = res.data;
499
500
// Apply grayscale filter
501
for (let i = 0; i < imageData.length; i += 4) {
502
const r = imageData[i];
503
const g = imageData[i + 1];
504
const b = imageData[i + 2];
505
const gray = r * 0.299 + g * 0.587 + b * 0.114;
506
507
imageData[i] = gray; // Red
508
imageData[i + 1] = gray; // Green
509
imageData[i + 2] = gray; // Blue
510
// Alpha channel (i + 3) remains unchanged
511
}
512
513
// Put processed data back
514
wx.canvasPutImageData({
515
canvasId: 'imageCanvas',
516
data: imageData,
517
x: 0,
518
y: 0,
519
width: res.width,
520
height: res.height
521
});
522
}
523
}, this);
524
}
525
```
526
527
## Types
528
529
```typescript { .api }
530
// Canvas context type
531
interface CanvasRenderingContext2D {
532
// Complete 2D rendering context interface
533
canvas: { width: number; height: number };
534
fillStyle: string | CanvasGradient | CanvasPattern;
535
strokeStyle: string | CanvasGradient | CanvasPattern;
536
lineWidth: number;
537
font: string;
538
textAlign: string;
539
globalAlpha: number;
540
541
// Methods for drawing, transforms, state management
542
beginPath(): void;
543
fill(): void;
544
stroke(): void;
545
fillRect(x: number, y: number, width: number, height: number): void;
546
fillText(text: string, x: number, y: number): void;
547
drawImage(image: any, dx: number, dy: number): void;
548
scale(x: number, y: number): void;
549
rotate(angle: number): void;
550
translate(x: number, y: number): void;
551
save(): void;
552
restore(): void;
553
554
// WeChat-specific
555
draw(reserve?: boolean, callback?: () => void): void;
556
}
557
558
// WebGL types
559
interface WebGLRenderingContext {
560
viewport(x: number, y: number, width: number, height: number): void;
561
clear(mask: number): void;
562
drawArrays(mode: number, first: number, count: number): void;
563
}
564
565
// Canvas option types
566
interface CanvasToTempFilePathOption {
567
canvasId?: string;
568
canvas?: any;
569
x?: number;
570
y?: number;
571
width?: number;
572
height?: number;
573
destWidth?: number;
574
destHeight?: number;
575
fileType?: 'png' | 'jpg';
576
quality?: number;
577
success?(res: { tempFilePath: string }): void;
578
fail?(res: any): void;
579
complete?(res: any): void;
580
}
581
```