最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 使用puppeteer在node中绘图

    正文概述 掘金(lgldl)   2021-04-28   705

    前言

    笔者在项目中需要用到 node 绘图并返回,查询了市面上的 node 的绘图库

    绘图库不想用的理由
    canvas这个库吧安装要求,太多了,Python 版本要求 2.7,还要安装 GTK,gyp 什么的,因为已经安装了 py3.0 了改来改去也太麻烦了~。gm因为没找到这个库的渐变怎么做的资料,其他看起来挺好用的

    找来找去我想到可以利用 puppeteer进行绘图

    介绍

    使用puppeteer在node中绘图

    大白话就是一个跑在 node 内部的浏览器,可以在这个浏览器中进行一些 node 不能做的操作,比如:生成网页的 PDF, 网页性能测试,模拟表单提交,爬取网页数据等等, 当然还有这篇文章的主题用puppeteer在 node 中绘图

    gogogo

    npm i puppeteer
    

    1.封装一下获取浏览器实例

    const puppeteer = require('puppeteer')
    const mainConfig = require('./mainConfig')
    class BrowserManage {
    	browserDestructionTimeout //清理浏览器实例
    	browserInstance //浏览器实例
    	browserState = 'closed' //浏览器状态
    	/**
    	 * 用于长时间未进行操作时关闭浏览器实例
    	 */
    	scheduleBrowserForDestruction() {
    		clearTimeout(this.browserDestructionTimeout)
    		this.browserDestructionTimeout = setTimeout(async () => {
    			if (this.browserInstance) {
    				this.browserState = 'closed'
    				await this.browserInstance.close() //关闭浏览器实例
    			}
    		}, 5000)
    	}
    	/**
    	 * 用于长时间未进行操作时关闭浏览器实例
    	 */
    	async getBrowser() {
    		return new Promise(async (resolve, reject) => {
    			if (this.browserState === 'closed') {
    				this.browserInstance = await puppeteer.launch(mainConfig.config.puppeteer) //开启浏览器实例
    				this.browserState = 'open'
    				resolve(this.browserInstance)
    			}
    			if (this.browserState === 'open') {
    				if (this.browserInstance) {
    					resolve(this.browserInstance)
    				}
    			}
    		})
    	}
    }
    module.exports = new BrowserManage()
    

    这里的 mainConfig.config.puppeteer

    {
    	args: ['--no-sandbox', '--disable-setuid-sandbox']
    }
    

    因为只用绘制功能所以,不会进行网页的跳转所以这里没有配置沙箱,如果你涉及了页面的跳转强烈建议你配置沙箱

    2.定义 绘图函数

    这里以绘制文字为例

    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 || '阿巴阿巴',
    			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) {
    			//实现渐变颜色
    			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 {
    			// 默认颜色
    			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)
    	})
    }
    

    3.获取并使用浏览器页面实例

    const browser = await browserManage.getBrowser()
    const page = (await browser.pages())[0]
    await page.setOfflineMode(true) //因为我们不需要进行网络资源读取,这样可以节省我可怜服务器的带宽
    page.on('console', (msg) => console.log(msg.type(), msg.text())) //监听页面console事件
    const base64 = await page.evaluate(toImgData, passedOptions)
    browserManage.scheduleBrowserForDestruction()
    const buffer = Buffer.from(base64, 'base64')
    return buffer //返回Base64 编码的图片
    

    这里注意 page.evaluate函数

    所以toImgData中的getColorX写在了内部

    当然也可以把getColorX函数抽离然后这样调用

    await page.evaluate(getColorX) //就相当于把getColorX声明并定义
    const base64 = await page.evaluate(toImgData, passedOptions)
    
    • 效果如下

    使用puppeteer在node中绘图

    总结

    本文介绍了 node 使用 puppeteer 进行绘图。

    要注意的地方是如果在 linux 中绘制中文会出现空白的情况 因为在 linux 中默认是没有安装中文字符的进行安装即可

    并且在 linux 中直接 npm i puppeteer是启动不了的 需要自己安装 chromium 或者

    sudo apt-get install gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 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 wget
    

    然后

    const browser = await puppeteer.launch({
            executablePath: "/usr/bin/chromium-browser", //通过executablePath配置Chromium 的路径
            ......
    

    报错这个

      (node:28469) UnhandledPromiseRejectionWarning: Error: Failed to launch chrome!
    [1025/150325.817887:ERROR:zygote_host_impl_linux.cc(89)]
    

    是因为没配置沙箱,这样以无沙箱模式启动

    const browser = await puppeteer.launch({
      args: ['--no-sandbox', '--disable-setuid-sandbox']}
      ......
    

    建议配置沙箱

    例子 git 地址 github.com/lgldlk/pupp…

    欢迎加入前端学习讨论群 qq 群号: 530496237


    下载网 » 使用puppeteer在node中绘图

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元