In daily uniApp and small program development, whenever I need to draw a poster at work, it gives me a headache. I need to put my previous code (downloadFile asynchronous package, CTX drawing method….) Copied, and then introduce one by one, or I can’t find it, and go to baidu, then it will be a long day so wasted, so in order to reduce the introduction of these tools I made a dedicated to create a poster of a tool library, so that it can reduce my workload (HHH can touch fish swimming again. The following is the introduction of the plug-in library, we can have a look, the current function has been all perfect
Brief description of poster drawing tool
- Create and draw a poster
canvas
Rectangle method, built-in picture drawing, rounded rectangle drawing, newline font drawing and other methods. - Close to a native development experience, fast to work with, with only business logic to worry about and nothing else.
- Has good syntax structure, will not draw
uni/wx
Rectangle falls into callback hell. - Support native applets, with
uniapp
Multiterminal applications. When the environment is native applets, automatically switch to better performancetype2d
Drawing mode. - Combine complex logic into simple methods that are extensible and usable
use|useCtx
Introduce extensions. - support
typescript
To supportvue3
Template, specific use referenceuseDrawPoster.
API documentation: U-draw-Poster
Plug-in market: Dcloud/U-draw-Poster
NPM installs plug-ins
npm i --save-dev u-draw-poster
Copy the code
Enable UNI conditional compilation for this plug-in (critical)
// vue.config.js
module.exports = {
transpileDependencies: ['u-draw-poster']};Copy the code
1. Create a poster drawing tool
<! -- #ifdef MP-WEIXIN -->
<canvas id="canvas" type="2d" style="width:100rpx; height:100rpx" />
<! -- #endif -->
<! -- #ifndef MP-WEIXIN -->
<canvas canvas-id="canvas" id="canvas" style="width:100rpx; height:100rpx" />
<! -- #endif -->
Copy the code
// error: '@/js_sdk/u-draw-poster'; // error: '@/js_sdk/u-draw-poster';
import DrawPoster from 'u-draw-poster'
async onReady() {
// Initialize the drawing tool by passing in the selector (note that # is not needed). Type2d drawing will be automatically enabled when wechat applet is used
const dp = await DrawPoster.build("canvas")}Copy the code
2. Set the canvas size
// Set the height of the rectangle to 100px
dp.canvas.width = 100
dp.canvas.height = 100
Copy the code
3. Draw anything
// Draw the background and text
dp.draw((ctx) = > {
ctx.fillStyle = "#F4F4F4";
ctx.fillRect(0.0, dp.canvas.width, dp.canvas.height);
ctx.textBaseline = "top";
ctx.textAlign = "start";
ctx.fillStyle = "white";
ctx.font = `bold The ${22}px sans-serif`;
ctx.fillText('Mr Zhou', dp.canvas.width/2.38.5);
})
// Draw the image content
dp.draw(async (ctx) => {
/ /...
})
Copy the code
Note that the draw method automatically executes ctx.save/ctx.restore without manipulating the drawing stack.
dp.draw((ctx) = > {/ *... * /})
/ / equivalent to
ctx.save()
/ *... * /
ctx.restore()
Copy the code
4. Draw
Dp.draw does not draw immediately, but simply adds the task to the stack, using the dp.awaitCreate function, which pops up all tasks when it is drawn. Dp. awaitCreate In a non-2D drawing, the ctx.draw method is automatically executed after the drawing task is completed, and the draw drawing is asynchronous.
dp.draw((ctx) = > {/ *... * /})
dp.draw(async (ctx) => {/ *... * /})
// Since each task may have an asynchronous draw task, we need to await it with await
const result = await dp.awaitCreate();
// Successful drawing returns an array of drawing status for each task
console.log("Draw status :", result); // draw state: [true]
Copy the code
5. Generate the local address of the image
If you want to save as an image, you can use dp.createimgURL to create a local address for the image and save it in the WX or UNI API.
dp.draw(async (ctx) => {/ *... * /})
const result = await dp.awaitCreate();
const posterImgUrl = await dp.createImagePath();
console.log("Draw status :", result); // [true]
console.log("Draw generate local address :", posterImgUrl); / /... tmp...
Copy the code
You can also skip the dp.awaitCreate method and automatically check the list of tasks when calling dp.createImagePath and create the address after the drawing task if it exists.
dp.draw(async (ctx) => {/ *... * /})
// Skip drawposter.awaitCreate to generate the address directly
const posterImgUrl = await dp.createImagePath();
console.log("Draw generate local address :", posterImgUrl);
Copy the code
Draw extension API
When a drawPoster is created, extension methods are automatically added/overwritten to CTX (brushes) to build the poster rectangle.
dp.draw(async (ctx) => {
// ctx.drawImage | ctx.drawRoundImage | ctx.fillWarpText | ....
})
Copy the code
DrawImage (ctx.drawImage)
ctx.drawImage(url, x, y, w, h)
DrawPoster is different from native drawing. CTX. DrawImage already has a built-in downloadFile and only needs to pass in the local/network address. Supports 2D and non-2D drawing in the same way. Need await to be drawn.
Note: When the drawing environment is H5, uniApp should not use large images when using local images for painting, otherwise it will fail to generate images.
dp.draw(async (ctx)=>{
const url = "/static/logo.png"
// const url = "https://...."
await ctx.drawImage(url, 88.174.94.198.98.36);
})
Copy the code
parameter | describe |
---|---|
url | Network picture address, or local/static Image path. |
The x, y, | The coordinates of the upper left corner of the picture. |
Width, height | The size of the picture. |
Newline font (ctx.fillwarptext)
ctx.fillWarpText(options)
Pass in a configuration object and draw a newline font. The following are configurable items.
interface FillWarpTextOpts {
// Draw a string, mandatory
text: string;
// Draw the maximum height, 100px by defaultmaxWidth? : number;// Draw the line height. Default is the default width of the current fontlineHeight? : number;// Draw the number of rows, the default limit is 2 layerslayer? : number;// Draw the X-axis, default 0x? : number;// Draw the Y-axis, default 0y? : number;/ / set the newline characters. The default is empty, such as setting, maxWidth | layer will be invalidatedsplitText? : string;// Do not draw immediatelynotFillText? : boolean; }// When 'notFillText' is' true ', no drawing is done and the function returns a draw queue
// Is used to represent the drawing information corresponding to each font line. Here is the structure information returned, which you can use to calculate
// The width of the newline font can also be drawn using array.forEach and ctx.fillText.[{text: string, y: number, x: number}
/ /...
]
Copy the code
Rounded rectangle (ctx.fillroundrect)
ctx.fillWarpText(x, y, w, h, r)
dp.draw(async (ctx)=>{
// Set the rectangle color
ctx.fillStyle = "#fff";
// Draw
ctx.fillRoundRect(15.179.345.365.5.10);
})
Copy the code
parameter | describe |
---|---|
The x, y, | Coordinates of the top left corner of the rectangle. |
Width, height | The size of the rectangle. |
r | Radians of the rectangle. |
Rounded rectangle border (CTx.strokeroundrect)
ctx.strokeRoundRect(x, y, w, h, r)
parameter | describe |
---|---|
The x, y, | Coordinates of the top left corner of the rectangle. |
Width, height | The size of the rectangle. |
r | Radians of the rectangle. |
Rounded corner image (CTx.drawroundimage)
ctx.drawRoundImage(url, x, y, w, h, r)
dp.draw(async (ctx) => {
const url = "static/logo.png"
// const url = "https://...."
await ctx.drawRoundImage(url, 0.0.100.100.50);
});
Copy the code
parameter | describe |
---|---|
url | Network picture address, or local/static Image path. |
The x, y, | The coordinates of the upper left corner of the picture. |
Width, height | The size of the picture. |
r | The radian radius of the image. |
DrawQrCode (ctx.drawqrcode)
Generate two-dimensional code extension, the source code used uQRCode and changed, the file is relatively large, so as an extension plug-in, use to introduce the plug-in first.
// error: '@/js_sdk/u-draw-poster'; // error: '@/js_sdk/u-draw-poster';
import DrawPoster from 'u-draw-poster'
import drawQrCode from 'u-draw-poster/dist/extends/draw-qr-code'
// Introduce a plug-in to draw a QR code
DrawPoster.useCtx(drawQrCode)
async onReady() {
const dp = await DrawPoster.build("canvas")
dp.canvas.width = 200; dp.canvas.height = 200
dp.draw(ctx= >{
ctx.drawQrCode({
x: (dp.canvas.width / 2) - 50.y: (dp.canvas.height / 2) - 50.text: "http://www.baidu.com".size: 100}); })}Copy the code
parameter | type | mandatory | instructions |
---|---|---|---|
x | number | no | Horizontal offset length |
y | number | no | Offset length in vertical direction |
text | String | is | Content of TWO-DIMENSIONAL code |
size | Number | no | Two-dimensional code size |
margin | Number | no | Margin, the actual size of the TWO-DIMENSIONAL code will be scaled according to the set margin value (default:0 ) |
backgroundColor | String | no | Background color, if set to transparent background,fileType Should be set to'png' And set the background color to'rgba(255,255,255,0)' (Default:'#ffffff' ) |
foregroundColor | String | no | Foreground (Default:'# 000000' ) |
errorCorrectLevel | Number | no | Error correction level, includingerrorCorrectLevel.L ,errorCorrectLevel.M ,errorCorrectLevel.Q ,errorCorrectLevel.H Four levels,L : Up to 7% of errors can be corrected;M : Up to 15% of errors can be corrected;Q : up to 25% of errors can be corrected;H : Up to 30% of errors can be corrected. |
Global instance API
Build (drawposter.build)
DrawPoster.build(string|object)
When the string is configured, the canvas of the string is queried directly. When the object is configured, object-selector is required. The following is the configuration item of options. Returns drawing the build object dp.
/** drawposter. build build configuration */
interface DrawPosterBuildOpts {
// Query string (mandatory), be careful not to miswrite the corresponding canvas ID, no need to pass the # symbol
selector: string;
// Select the component rangecomponentThis? : any;// The type is 2D drawing, which is enabled by default and dynamically loaded in wechat applettype2d? : boolean;// Whether to display the loading box during the drawing processloading? : boolean,// When drawing a picture, wait for the drawing to complete (ms), only in AppdrawImageTime? :100.// Load prompt textloadingText? :'Drawing the poster... '.// Create image loading prompt textcreateText? :'Generate the picture... '
}
Copy the code
Multidrawing builds (drawposter.buildall)
DrawPoster.buildAll(Array<string|object>)
Build multiple drawing tools, to build function parameter string | options array that return multiple object composed of drawing tools. Key is canvasId and value is the build object.
Mount the global extension (drawposter.use)
DrawPoster.use(object)
Passing in the mount configuration object and adding the global extension method can generally be used to encapsulate the poster drawing template. When different pages have the same poster template, the amount of code can be effectively reduced. The usage is as follows.
1. Add extensions anywhere (recommended in main.js)
import DrawPoster from 'u-draw-poster'
// Global added extension implementation to draw personal posters
DrawPoster.use({
name: "createMyCardImagePath".// dp is the current instance, and other parameters are custom incoming parameters
handle: async (dp, opts) => {
/ /.. Custom build content..
return await dp.createImagePath()
}
})
Copy the code
Use custom extensions in pages
import DrawPoster from 'u-draw-poster'
async onReady() {
const dp = await DrawPoster.build("canvas")
dp.canvas.width = 100; dp.canvas.height = 100
const posterImg = await dp.createMyCardImagePath({/ *... * /})}Copy the code
Mount the Draw extension (drawposter.usectx)
DrawPoster.useCtx(object)
Pass in the mount configuration object and add the global draw extension method to customize the definition of the draw method as follows.
1. Add extensions anywhere (recommended in main.js)
// Global add draw TWO-DIMENSIONAL code drawing extension implementation
DrawPoster.useCtx({
name: "drawQrCode".Canvas (draw node), CTX (draw brush), the rest of the parameters are custom passed parameters
handle: async (canvas, ctx, url, x, y, w, h) => {
/ /.. Custom draw content..}});Copy the code
Use custom extensions in drawing
dp.draw(ctx= > {
const url = 'http://www.baidu.com'
await ctx.drawQrCode(url, 0.0.50.50)})Copy the code
Draw a node (dp.canvas)
dp.canvas | dp.canvas.width | dp.canvas.height | ...
Dp. canvas is the global drawing root node and has an exclusive API in wechat applet. It will be used as a global width and height container on other ends. When dp. CreateImagePath incoming parameters, not default to dp. Canvas. Width | dp. Canvas. Height to create pictures, the following is a dp. API that exist in the canvas object and attributes.
interface Canvas {
width: number;
height: number;
// The rest of the parameters are the wechat applet exclusive API, only the wechat applet has the API
/ / specific reference WeChat small program documentation: https://developers.weixin.qq.com/miniprogram/dev/api/canvas/Canvas.html
}
Copy the code
Create draw (DP.draw)
dp.draw(async callback(ctx))
Renderer, receiving actuator function, added to the renderer container, can be modified as an asynchronous function to handle picture rendering, or can be a synchronous function.
Global Brush (DP.ctx)
dp.ctx
Global drawing brush. Special cases can be used. It is recommended to use only the dP. draw function for drawing.
Waiting to draw (dp.awaitCreate)
dp.awaitCreate()
Asynchronously draws the renderer stack, emptythe renderer container on success, and returns an array of stack status for success (Boolean []).
Stop painting (dp.stop)
dp.stop()
Stop the current drawing stack, call will cease to dp. AwaitCreate | dp. CreateImagePath execution.
Create an image (dp.createImagepath)
dp.createImagePath(options)
If the stack is not empty, dp.awaitCreate() will be called automatically to empty the stack. CreateImagePath creates the image based on canvas.width and canvas.height. If you want to customize the parameters, the awaitCreate method can take a configuration object and return the image address, as shown below.
interface CreateImagePathOptions { x? : number; y? : number; width? : number; height? : number; destWidth? : number; destHeight? : number; }Copy the code
Use advice
Canvas should be regarded as a generation tool in poster generation, and its function is only to draw posters. The generated resources should be saved and used, and the image image component should be used for display. The reason is that it is convenient for operation, such as adjusting size, or holding down the H5 end to save or identify, so canvas should put it in a place where it cannot be seen. Can’t use the display: none; overflow:hidden; Hide, otherwise blank is generated. The hidden style code of canvas is recommended here, which is the description provided by uQRCode, as well as u-draw-poster
.canvas-hide {
/ * 1 * /
position: fixed;
right: 100vw;
bottom: 100vh;
/ * 2 * /
z-index: -9999;
/ * * / 3
opacity: 0;
}
Copy the code
Q&A
Wechat mini program mobile phone browsing blank
If pictures are drawn, you need to add the downloadFile domain name in the background and restart the developer tool.
Micro channel small program can not be real machine debugging
Developers.weixin.qq.com/community/d…
H5 image clipping is abnormal
When two or more ctx.drawRoundImage rounded corner images are drawn on the H5 end, the local base64 created is displayed incorrectly. It is recommended that you limit rounded corner images to one when the H5 environment is used, or uni dynamically compilers display the IMG label.
No effect after drawing
Note that DrawPoster. Build does not check whether the canvasId you selected is correct, so make sure it is the same as canvas in canvas-ID and HTML. On the apet side, it will automatically switch to Type2D, so dynamic compilation must be added.
<! -- #ifdef MP-WEIXIN -->
<canvas id="canvas" type="2d" style="width: 300px; height: 300px" />
<! -- #endif -->
<! -- #ifndef MP-WEIXIN -->
<canvas canvas-id="canvas" id="canvas" style="width: 300px; height: 300px" />
<! -- #endif -->
Copy the code
Drawing multiple images is slow to load
If you feel that multiple picture drawing await is slow to load, you can use promise. all to synchronously draw part of the image that does not need to handle layer overlay.
dp.draw(async (ctx) => {
// // User profile picture
await ctx.drawRoundImage(headImgUrl, 39.790.90.90.100);
await Promise.all([
ctx.drawImage('/static/logo1.png'.20.20.35.35),
ctx.drawImage('/static/tp.png'.19.86.612.459),
ctx.drawImage('/static/bw.png'.188.559.274.50),
// // user's QR code
ctx.drawImage(codeImgUrl, 518.780.92.92),]); });Copy the code
Note that ctx.drawRoundImage cannot be placed in promise. all, because ctx.drawRoundImage will call ctx.clip internally, which will conflict with other image rendering in promise. all. This causes the fillet to fail.
My blog: Mr.Mao’ Blog
Contact: [email protected]