Generate canvas poster using JSON configuration
Check out the nuggets article juejin.cn/post/684490…
Method of use
*/ const poster = new poster ('demo', 300, 500, this.config, true); poster.init(); poster.listen('progressChange', () => { console.log(poster.progress); // Poster loading progress});Copy the code
Renderings are displayed
Support text newline with coolzjy@v2ex to provide regular regexr.com/4f12l, text, background gradient, CSS layout, progress monitoring, border drawing
class Poster { constructor(... args) { this.parentNode = document.getElementById(args[0]); this.width = args[1] || 0; this.height = args[2] || 0; this.canvas = this.initCanvasContext(this.width, this.height); this.defaultConfig = this.setDefault(args[3] || {}); this.inlineBlockConfig = this.setInlineBlock(this.defaultConfig, 1); this.widthConfig = this.setWidth(this.inlineBlockConfig); this.heightConfig = this.setHeight(this.widthConfig); this.originConfig = this.setOrigin(this.heightConfig); this.images = this.getImages(this.originConfig); this.progress = 0; / / schedule this. BoxShow = args [4] | | false; }}Copy the code
- 1. Initialize canvas(initCanvasContext)
When we initialize the width and height of the canvas, there may be blur, so we need to obtain the pixel ratio of the device to expand the canvas and ensure that it can be displayed in high definition
initCanvasContext() {
var ratio = devicePixelRatio / backingStoreRatio;
canvas.width = width * ratio;
canvas.height = height * ratio;
}
Copy the code
- 2. Set some base defaults (setDefault)
We need to add some padding to the JSON configuration object, such as the default color, line height, padding, etc. It is up to you
setDefault(config) {
//do something...
return config
}
Copy the code
- 3. Change layout arrangement (setInlineBlock)
A new, empty div is created by aggregating the contiguous inline-block nodes into its original location and the inline-block nodes are inserted as children.
SetInlineBlock (config) {config.children. ForEach (item => {//do somgthing... setInlineBlock(item) }) return config }Copy the code
- 4. Calculate the width(setWidth) of the box model again, and calculate the width of various box models by combining CSS properties such as margin and border.
SetWidth (config) {do something return config} setWidth(config) {Copy the code
- 5. Calculate the height of the box model (setHeight), calculate the height of all nodes with the same width without inheriting the height of the parent node
SetWidth (config) {// do something return config}Copy the code
- 6. SetOrigin calculates the drawing position X of all nodes,
SetOrigin (config) {// do something return config}Copy the code
Now that we have a computed JSON configuration, let’s start drawing
- Since it takes time to load pictures, we can wait until the pictures are loaded before drawing, which gives us a better experience. Moreover, we can monitor how many pictures are loaded to calculate the progress
async loadAllImages(images) { var that = this; let count = 0; for (var i = 0; i < images.length; i++) { const item = images[i]; const img = await this.loadImage(item.url); count++; that.progress = count / images.length; item.img = img; } return images; } loadImage(url) { return new Promise(resolve => { const img = new Image(); Img. onload = () => {setTimeout(() => {resolve(img); }, 0); }; img.setAttribute('crossOrigin', 'Anonymous'); img.src = url; }); } /** If (type == 'progressChange') {object.defineProperty (this, Set: function(v) {this._progress = v; Console. log('progress changed ', v); callBack(v); }, get: function() { return this._progress; }}); }Copy the code
We can call the encapsulated drawCanvas to draw, perform type discrimination and perform different drawing
DrawCanvas (config) {if (config.type == 'text') {this.drawParagraph(config); } if (config.type == 'div') { config.custom(this.ctx, config); } if (config.type == 'image') { this.drawImage(config); } if (config.children) { config.children.forEach(item => { this.drawCanvas(item); }); }}Copy the code
As for the specific drawing process, you can see my code, but you can first look at the drawing method of canvas, ctx.save(); Ctx.restore () is critical
The code repository address is at github.com/kukudedaxia…