Dynamic Poster Generation in WeChat Mini Programs Using Painter
Creating dynamic posters in WeChat Mini Programs often involves complex Canvas API operations. Painter simplifies this by utilizing a JSON-based configuration approach, similar to CSS, to render elements onto a <canvas> and export an image directly.
- Repository: https://github.com/manycore-maas/Painter
- Documentation: https://painterjs.github.io/docs.html
Integration
- Clone or download the repository from GitHub.
- Copy the
components/painterdirectory into your project'scomponentsfolder (e.g.,your-miniprogram/components/painter).
Core Cnocepts
Unlike traditional web Canvas libraries that manipulate the drawing context directly, Painter generates an image file based on a provided JSON schema. This resulting image is then displayed using the standard <image> component.
Component Registration
Include the component in your page's JSON configuration file.
// pages/poster/poster. { "usingComponents": { "painter": "/components/painter/painter" } }
Layout and Data Binding
The WXML template requires both the <painter> component (which remains invisible) and an <image> component to display the output.
xml <painter palette="{{posterSchema}}" bind:imgOK="onImageReady" />
palette: Accepts the JSON data structure defining the poster layout.bind:imgOK: Triggered when the image is successfully generated, returning the file path.src: Binds to the generated image's local path.
Page Logic
Construct the JSON schema in the JavaScript file and handle the image generation callback.
javascript // pages/poster/poster.js Page({ data: { posterSchema: {}, outputImageUrl: '', canvasWidth: 600, canvasHeight: 800 },
onImageReady(e) { const { path } = e.detail; this.setData({ outputImageUrl: path }); },
buildSchema() {
return {
width: ${this.data.canvasWidth}px,
height: ${this.data.canvasHeight}px,
background: '#e0e0e0',
views: [
{
type: 'text',
text: 'Hello World',
css: {
fontSize: '80px',
color: '#333333'
}
}
]
};
},
onLoad() { this.setData({ posterSchema: this.buildSchema() }); } });
The palette object requires three primary fields:
width: Canvas width (e.g.,'600px').height: Canvas height (e.g., `'800px'').views: An array of elements to render.
Fixing Aspect Ratio
The native <image> component defaults to 320px by 240px, which may distort the generated poster. To maintain the correct proportions, bind the canvas dimensions directly to the image element's style.
xml
Supported Elements
The views array supports various element types, defined by the type and css properties.
Text
Set type to "text" and provide the string via the text property.
javascript views: [ { type: 'text', text: 'Main Title', css: { top: '150px', left: '80px', fontSize: '60px', color: 'blue', rotate: '15' } }, { type: 'text', text: 'Subtitle', css: { top: '250px', left: '80px', fontSize: '40px', color: 'gray' } } ]
Image
Set type to "image" and provide the source via url. Network URLs require the domain to be whitelsited in the Mini Program backend.
javascript views: [ { type: 'image', url: '/assets/images/banner.png', css: { top: '50px', right: '30px', width: '200px' // Height scales automatically } } ]
Rectangle
Set type to "rect". Both width and height are mandatory. Use color to fill the shape (not backgroundColor). Circular shapes can be achieved using borderRadius.
javascript views: [ { type: 'rect', css: { width: '400px', height: '200px', color: 'green', borderRadius: '100px' } } ]
QR Code
Set type to "qrcode". The content property holds the encoded data. Dimensions are required.
javascript views: [ { type: 'qrcode', content: 'https://example.com/invite', css: { width: '250px', height: '250px', color: 'darkblue' } } ]