preface
I need to use node drawing in the project and return, query the market node drawing library
Drawing library | Reasons you don’t want to use it |
---|---|
canvas | GTK, GYp, and so on, because py3.0 is already installed and it’s too cumbersome to change. |
gm | Did not find the library to do the gradient information, other looks good to use |
After a bit of digging I thought I could use puppeteer for drawing
introduce
Puppeteer is an official Google Node library that controls Headless Chrome through the DevTools protocol.
You can directly control Chrome through the apis provided by Puppeteer to simulate most user actions to perform UI tests or to crawl pages to collect data.
First, Puppeteer provides many functions to execute code in the Page DOM Environment,
Second, Puppeteer provides ElementHandle and JsHandle to encapsulate elements and objects in the Page DOM Environment into corresponding Node.js objects. In this way, the Page DOM can be manipulated directly by the encapsulation functions of these objects
Puppeteer is a browser that runs inside node and allows you to do things that node can’t, such as generating PDFS for web pages, testing web performance, simulating form submission, crawling web data, etc., as well as puppeteer drawing in Node
gogogo
npm i puppeteer
Copy the code
1. Wrap to get the browser instance
const puppeteer = require('puppeteer')
const mainConfig = require('./mainConfig')
class BrowserManage {
browserDestructionTimeout // Clean up the browser instance
browserInstance // Browser instance
browserState = 'closed' // Browser status
/** * Close the browser instance */ when no operation has been performed for a long time
scheduleBrowserForDestruction() {
clearTimeout(this.browserDestructionTimeout)
this.browserDestructionTimeout = setTimeout(async() = > {if (this.browserInstance) {
this.browserState = 'closed'
await this.browserInstance.close() // Close the browser instance}},5000)}/** * Close the browser instance */ when no operation has been performed for a long time
async getBrowser() {
return new Promise(async (resolve, reject) => {
if (this.browserState === 'closed') {
this.browserInstance = await puppeteer.launch(mainConfig.config.puppeteer) // Start the browser instance
this.browserState = 'open'
resolve(this.browserInstance)
}
if (this.browserState === 'open') {
if (this.browserInstance) {
resolve(this.browserInstance)
}
}
})
}
}
module.exports = new BrowserManage()
Copy the code
Here the mainConfig. Config. Puppeteer
{
args: ['--no-sandbox'.'--disable-setuid-sandbox']}Copy the code
There’s no sandbox here because it’s only drawing so it doesn’t jump to the page, but it’s highly recommended that you sandbox if you’re involved in jumping to the page
reference
Developers.google.com/web/tools/p…
Stackoverflow.com/questions/6…
2. Define the drawing function
Take drawing text as an example
exports.toImgData = async (options) => {
let fontConfig = {
baseLine: 5
}
function getColorX(i, colors) {
if (colors instanceof Array) {
return (i / (colors.length - 1)).toFixed(2)}}return new Promise((resolve, reject) = > {
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d'),
font = options.text || 'Abba abba',
fontSize = Number(options.fontSize || 32),
fontFamily = options.fontFamily,
lineHeight = fontSize + fontSize / fontConfig.baseLine
canvas.width = fontSize * font.length
canvas.height = lineHeight
gradient = ctx.createLinearGradient(0.0, canvas.width, 0)
ctx.shadowColor = options.shadowColor || ' '
ctx.shadowOffsetX = options.shadowOffsetX || 2
ctx.shadowOffsetY = options.shadowOffsetY || 2
if (options.colors instanceof Array) {
// Implement the gradient color
for (let i = 0; i < options.colors.length; i++) {
gradient.addColorStop(getColorX(i, options.colors), options.colors[i])
}
} else if (typeof options.colors == 'string') {
gradient.addColorStop(0, options.colors)
} else {
// Default color
gradient.addColorStop(0.'rgba(241,158,194,1)')
}
ctx.font = fontSize + 'px ' + fontFamily
if(! options.mode || options.mode =='1') {
//mode ==1
ctx.fillStyle = gradient
ctx.fillText(font, 0, fontSize)
} else if (options.mode == '2') {
//mode ==2
ctx.strokeStyle = gradient
ctx.strokeText(font, 0, fontSize)
}
ctx.restore()
const dataURI = canvas.toDataURL('image/png')
const base64 = dataURI.substr(22) // 22 =`data:image/png; base64,`.length
resolve(base64)
})
}
Copy the code
3. Obtain and use the browser page instance
const browser = await browserManage.getBrowser()
const page = (await browser.pages())[0]
await page.setOfflineMode(true) // Since we don't need to read network resources, this saves bandwidth on my poor server
page.on('console'.(msg) = > console.log(msg.type(), msg.text())) // Listen for the page console event
const base64 = await page.evaluate(toImgData, passedOptions)
browserManage.scheduleBrowserForDestruction()
const buffer = Buffer.from(base64, 'base64')
return buffer // Return the Base64 encoded image
Copy the code
Note the page. Evaluate function here
page.evaluate(pageFunction[, …args])
PageFunction < XSL: | string > to be executed in page instance context method
. args <… The Serializable | JSHandle > to pageFunction parameters
Return: <Promise> pageFunction result of execution
This function is equivalent to an internal eval call to the JS function in the retrieved page instance
So getColorX in toImgData is written inside
You can also pull out getColorX and call it this way
await page.evaluate(getColorX) // declare and define getColorX
const base64 = await page.evaluate(toImgData, passedOptions)
Copy the code
- Results the following
conclusion
This article describes node drawing using puppeteer.
Note that if you draw Chinese characters in Linux, it will be blank because by default, Chinese characters are not installed in Linux
Installation can refer to the article www.huaweicloud.com/articles/f6…
In Linux, puppeteer cannot be started directly by NPM I. You need to install Chromium or puppeteer
Sudo apt-get install gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-3 Libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango 1.0-0 Libpangocairo -1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wgetCopy the code
then
const browser = await puppeteer.launch({
executablePath: "/usr/bin/chromium-browser".// Configure the Chromium path from executablePath.Copy the code
An error in the
(node:28469) UnhandledPromiseRejectionWarning: Error: Failed to launch chrome! [1025/150325.817887: ERROR: zygote_host_impl_linux. Cc (89)]Copy the code
Because no sandbox is configured, so it starts in no-sandbox mode
const browser = await puppeteer.launch({
args: ['--no-sandbox'.'--disable-setuid-sandbox']}...Copy the code
Sandbox configuration is recommended
Reference github.com/puppeteer/p…
Example git address github.com/lgldlk/pupp…
Welcome to join the front-end learning discussion group QQ group number: 530496237