Recently did a demand, meet a problem, small program drawing currently only supports the px unit, the design is generally a iphone6 reference design, if the size of the strict iphone6 code, on the other size of the equipment, is definitely not enough, so need to be carried out in accordance with the equipment such as compatibility, two solutions are given here

Let’s start with a hypothetical requirement. Here’s how it worked out (based on the iphone6). Let’s expand from there

The whole page is covered by canvas component (375×603 in iphone6). The blue one in the middle is a picture with a line of flexible canvas on it

classrem

The solution to the equal-scale scaling unit is to use one size as a base, such as the iPhone 6, and then scale other devices according to this standard, while keeping the width of the device fully covered

The code to draw is simple:

const ctx = wx.createCanvasContext('shareCard')
ctx.drawImage('.. /58a.png'.this.remSize(85), this.remSize(100), this.remSize(205), this.remSize(250))
ctx.setFontSize(this.remSize(16))
ctx.setFillStyle('yellowgreen')
ctx.fillText('flexible canvas'.this.remSize(100), this.remSize(130))
ctx.draw()
Copy the code

The remSize method is used to scale the size equally

remSize (num) {
  return num * scale
}
Copy the code

Scale is the ratio of the width of the current device to that of the design benchmark device, the iphone6

scale = wx.getSystemInfoSync().windowWidth / 375
Copy the code

The current goal is to spread the full width of the device, so the height is not concerned, that is, the width as a reference, height auto

So that’s basically implementing the requirements, it’s pretty simple, it’s usually a consistent solution because the requirements in the example are simple, so it doesn’t seem to be a problem, it’s perfect, but if the actual requirements, the more complex ones, are a little bit less beautiful what’s not so beautiful about them? Is to convert the size, each size to call a remSize method, a little more complex demand may have dozens of need to convert the size, it is necessary to write dozens of remSize, of course, write can write, but always feel where is not quite right

Pictures instead of

This method does not need frequent size conversion, and finally unified overall conversion, the principle is very simple

  • In accordance with theiphone6Dimension drawing

First of all, no matter what the size of the current device is, don’t worry about it. First, think the current device is iphone6, then create canvas and draw on it. However, you can’t show the canvas to the user, because the current device is not necessarily iphone6, but you can directly identify it as iphone6. And draw it with the size of iphone6. The drawn effect is definitely different from the designed effect, so it cannot be seen by users. You can use the Ccover-view component to cover the Canvas component

Note: If you want to set opacity: 0, opacity: hidden, etc., on the canvas to hide it, according to actual measurements, it will not work on most mobile phones, that is, it will still be visible, display: None; The canvas is completely removed from the document stream (if it is a document stream) and cannot be drawn, so it is better to use a cover-view to cover it

  • I’ll draw itcanvasOutput as image

Canvas to draw, draw them into images stored in a local store, you can get the image in the local temporary path, then the image on the page, and give the image size set style, the width of the image is equal to the width of the equipment, height with width of scaling, finally let the user see this picture, Because of equal scale scaling, the visual effect is exactly the same as on the design

There are a couple of things to note here

  • ctx.drawAsynchronous operation

Always thought that this method is a synchronous method, so after calling this method immediately output the picture, sometimes the picture error situation, later found that this is asynchronous operation, this is the result of not carefully read the document

ctx.draw(false, () = > {// Save as a local temporary file
  this.saveImageToLocal()
})
Copy the code
  • drawcanvasPhase, to allow page horizontal overflow

Since canvas was drawn according to iphone6 standard at the beginning, the width of canvas may be larger than that of the device on some devices with a width smaller than iphone6 (if you draw a full screen canvas), but the root element page of the applet page, The default setting is overflow-x: hiddne; , resulting in incomplete drawing, so we need to overwrite this style:

page {
  overflow-x: scroll;
}
Copy the code
  • After drawing, avoid horizontal page overflow

When the canvas is drawn in the previous step and the picture is successfully drawn on the page, if the width of the current device is smaller than iPhone 6 and overflow-x is set for the page element in the previous step: So the canvas element will definitely enlarge the page and make a horizontal scroll bar appear on the page, while the width of the picture seen by the user is the same as the width of the device, which should not happen

To solve the problem, one is to delete the canvas element directly by using the conditional statement wX-if, but the error of E. canvasid is undefined may be reported on the base library of the earlier version (although according to the actual measurement, it does not seem to affect the normal function). The other is to reduce the size of canvas. Anyway, I’ve already drawn the image, and I don’t need it anymore, and the user can’t see it, so I can reduce the size as MUCH as I want. What I do is I just set the width and height to 0, so I don’t have any bugs

// Avoid spillage on small devices
this.setData({
  canvasWidth: 0.canvasHeight: 0
})
Copy the code

Above, two methods can choose, each has its own advantages and disadvantages, the first one needs to write a lot of REM transformation, the second one needs to do more operations, each has its advantages and disadvantages, according to the real needs of the choice.

This article can run the example code has been put on Github, interested can see, the comments are very detailed, if you like the star oh ~