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




No bounds and no bounds

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

  1. 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…