In the world of apps, the ability to generate pictures and share them on moments is so glamorous that every app has come to kneel at her feet. Unfortunately, Wechat Dad doesn’t provide us with very good and convenient tools; Instead, screenshots were cruelly consigned to the dustbin of history, leaving only a Canvas component and the abyss surrounding it.

Therefore, we have prepared a set of tools called Painter, which provides a simple and practical solution for developers to “draw” pictures, allowing developers to freely generate their own image files.

Github portal: github.com/Kujiale-Mob…

Drawing on canvas is definitely a sour experience, with out-of-control code and numerous sinkholes. Let’s start with a list of the pits we’ve stepped on in the canvas and how we can work around them (or get around them).

The pit of canvas

In terms of implementation, Painter uses canvas of small program as the carrier to realize the above functions. Canvas has a lot of famous craters. Some pits, we carefully around the past; Some pit, we are still happy to step on the foot…

  1. On some ios models with wechat version 6.6.6, the Canvas clip() method cannot be restored. As a result, fillet cutting cannot be performed on these models. We were forced to discard these models during development and used an if statement to neuter the rounding function of these machines…
  2. The canvas of the applet provides measuretText(), which measures text width but not height. So some element alignment requirements can’t be pretty.
  3. When drawing pictures, there is a chance that a very magical performance will occur, that is, the overall position of canvas drawing will be deviated, resulting in incomplete pictures. This happens most of the time with onLoad calling painter. The way we deal with it is to check the width and high proportion of the image, and if there is an anomaly, draw it again.
  4. Canvas cannot draw network pictures. The canvas.drawImage(URL) method, which passes a web link to the URL, works perfectly on the emulator, but doesn’t draw on the real machine. In Painter, we have introduced a set of our own mechanism of drawing network pictures after downloading, and added LRU storage management mechanism.
  5. The Canvas is a native component that is always at the top of the view and has no z-index setting for it. I won’t go into that. I think a lot of people have.
  6. To draw a Canvas, the Canvas component must actually be written to the page, and its Wx :if cannot be false. However, it is possible to place the Canvas component outside the screen, such as position: Fixed; left:750rpx; . This is a dark technology that can solve 5,6 problems

The function of the Painter

As is shown in

Through a few lines of code on the right, which is similar to CSS and somewhat like JSON, but actually it is JS, we draw the graph on the left, including background picture, text, picture, two-dimensional code, these four commonly used elements.

After Painter reads the code, draws the image, and sends the link back to us. At this point, we can upload the image, save it locally, or display it on the screen.

It makes it easy to customize the image you want, and can change the style of the image dynamically.

In addition, the canvas.drawImage() applet cannot draw network images on the real machine. And Painter can solve this problem, if there is a need to draw network pictures can also consider using Painter.

Other advantages of Painter

  1. Painter can download network images to the local, and perform LRU management on the downloaded network content. Currently, the maximum local storage allowed by the applet is 10m. By default, the local storage painter can use is 6m, and the local storage will be cleaned up if it exceeds. If you need to custom, can be in/painter/lib/downloader. Changes in js MAX_SPACE_IN_B properties.

  2. The CSS properties of subviews currently support object or array. Allows you to extract CSS properties common to several views.

  3. Since the Palette is json hosted by JS, you can easily add your own logic to each attribute. Some attributes can also be extracted separately and shared by multiple palette to be modular.

use

Download the demo

The Demo project is managed as a subModule and therefore needs to be run during Clone

git clone https://github.com/Kujiale-Mobile/Painter.git --recursive
Copy the code

When clone is complete, you can see the directory. Where, /pages/example stores the usage example, and /components/ Painter is the function component we introduce. There is also a Palette directory, which will store the drawing code we need. In practice, The Painter takes the information in card.js and draws the corresponding pattern on the image, much like a paintbrush that dips paint on a palette and creates on a canvas.

Introduce Painter into your project

You can copy and paste the Painter from the demo into your own project, or you can run it more elegantly:

git submodule add https://github.com/Kujiale-Mobile/PainterCore.git painter
Copy the code

It will place the Painter tool in your current directory. What we recommend is to put it under your components.

The introduction of the component

Like any other component, add the following to the.json file where Painter is introduced:

"usingComponents":{
  "painter":"/components/painter/painter"
}
Copy the code

Component calls

The Painter component is called in the XML file of the page, passing in the data for the Pallete rule, and the callback after the drawing is done.

<painter palette="{{data}}" bind:imgOK="onImgOK" bind:imgErr="onImgErr"/>
Copy the code

Palette is our palette data, which is created in JSON form according to certain specifications. Please refer to the following for details.

Draw the callback

bind:imgOK="onImgOK"
bind:imgErr="onImgErr"
Copy the code

After the data is passed in, Painter will start painting, and whether the drawing succeeds or fails, it will get relevant information in the corresponding callback method, such as:

Pallette

After all, Painter is a brush tool, and it’s up to us, the clever programming monkeys, to tell it what to paint. Tell it what to draw, where to draw, what pose to use when drawing… And so on. This requires some other means, because scientific experiments have proved that trying to communicate with it in Mandarin is not effective.

Palette properties

Each palette has its own overall properties, which generally dictate the size, style, background, and so on of the entire drawing range

It is the outermost layer of the entire JSON file and requires the following attributes:

attribute explain
background Background, can be a color value, can also be a picture link, support local picture link and network picture link
width The width of the
height highly
borderRadius Rounded corners
views Other elements that need to be drawn on the diagram are allowed to be empty but not omitted

Sample code:

{
      background: 'https://qhyxpicoss.kujiale.com/2018/06/12/LMPUSDAKAEBKKOASAAAAAAY8_981x600.png',
      width: '654rpx',
      height: '400rpx',
      borderRadius: '20rpx',
      views: []
 }
Copy the code

The view attribute

After drawing the overall properties of the palette, you can add some elements to the views. The element supports four types, distinguished by the Type field. Different types of views require different data. For example, the image element needs to provide its URL, and the text element needs to provide text content:

type content description Private CSS properties
image url Image resource address, local or network
text text Text elements, written text FontSize: fontSize, color: text color
rect There is no rectangular Color: Fill color
qrcode content Painting qr code Background: Background color, transparent by default

In addition to the private attributes of each view, a view has a few public attributes that can be set:

attribute role
left, top, right, bottom Position of elements
rotate Angle of rotation, in 360 degrees
borderRadius Rounded corners. If you want to set the image as original, set this property to half width or height
align Horizontal alignment of elements, used with left, can be left, center, right, default left.
rotate

Control the rotation of the element, as shown below, to rotate a line of text 6 degrees clockwise.

{type: 'text', text: 'cool ', CSS: {left: '20rpx', top: '50rpx', fontSize: '40rpx'},},Copy the code

Effect:

borderRadius

Code (circle) :

        {
          type: 'image'.url: this.cardInfo.avatar,
          css: {
            top: '48rpx'.left: '448rpx'.width: '192rpx'.height: '192rpx'.borderRadius:'96rpx',}},Copy the code

Square –>8rpx rounded –> circle

align

This is an interesting attribute value that is used to set the alignment of elements horizontally with respect to position Settings.

What does that mean?

For example, if you set the left of an element to 100rpx and set the align attribute to left, the left of the element will be aligned with 100rpx. If align is set to center, the axis of the element is aligned with 100rpx.

In the following example, the left of the three lines is 230rpx, and the align is left, center, and right respectively. The red line is the 230rpx axis.

That is, when the align attribute is set, the left value represents the position of align in the element attribute.

Code:

		{
          type: 'text'.text: 'Krocer Mobile Front End'.css: {
            left: '330rpx'.top: '100rpx'.fontSize: '40rpx',}}, {type: 'text'.text: 'Krocer Mobile Front End'.css: {
            left: '330rpx'.top: '200rpx'.fontSize: '40rpx'.align: 'center'}, {},type: 'text'.text: 'Krocer Mobile Front End'.css: {
            left: '330rpx'.top: '300rpx'.fontSize: '40rpx'.align: 'right'}},Copy the code

With this property, you can set the alignment of elements to accomplish the following layout requirements:

Note: The align attribute must be used with the left attribute. Setting the right value will cause an error.

Align with the rotate

When the align attribute and the rotate attribute exist together, the rotation of an element is centered around the element’s center point.

Size of the unit

Currently, Painter supports two size units, PX and RPX, which represent the same meaning as in the miniprogram. The use of percentages is not currently well supported.

Save picture demo

After obtaining the URL of the image, you can set a click button and click Save to local

  onImgOK(e) {
    this.imagePath = e.detail.path;
  },

  saveImage() {
    wx.saveImageToPhotosAlbum({
      filePath: this.imagePath,
    })
  },
Copy the code

Button binding saveImage method, click to save:

Create moments to share pictures

Finally, Painter tool can be used to generate sharing pictures of friends circle of different styles (below is part of screenshot of wechat mini program Kuka business card online version)

conclusion

Painter is a set of tools made by Kukule front-end in the actual development of small programs. Currently, it is used in sharing in moments of friends, skin template replacement and other aspects, and I feel that it has mixed advantages and disadvantages when used. Open source for everyone to share. If it helps anyone, we’re happy. We are also very welcome and grateful to mention issure or PR to tell us something we didn’t think of on our own, or to help solve the big and small holes in Painter:

Portal one more time: github.com/Kujiale-Mob…