canvas官网:CanvasRenderingContext2D.canvas - Web APIs | MDN
小程序-canvas组件:canvas | 微信开放文档
1、两种cavnas获取上下文方式
老版本 createCanvasContext 方式
createCanvasContext
是微信提供的获取 canvas
实例的老得接口,使用方式如下。
wxml
<canvas style="width: 300px; height: 200px;" canvas-id="firstCanvas"></canvas>
美好的一天从写一个hello,world
开始。
js中这么写
onReady(){
/* 使用 wx.createContext 获取绘图上下文 context , firstCanvas 与 canvas 属性中的canvas-id一一对应 */
const context = wx.createCanvasContext('firstCanvas')
/* 设置字体大小 */
context.setFontSize(20)
/* 设置字体颜色 */
context.setFillStyle('pink')
/* 设置文本内容,位置 */
context.fillText('hello,world', 0, 0)
context.draw()
}
老版本是使用createCanvasContext
传入 canvas
标签中的 canvas-id
属性,来获取canvas
实例,老版本的使用起来说实话,不够灵活,很多对canvas
线条,颜色的设置,都封装成方法了,每次改变需要调用方法。
新版本 getContext 上下文方式(2.9.0)
新的方式,则是先通过 createSelectorQuery
获取 canvas
元素节点, 然后通过 getContext
获取上下文。
wxml
<canvas type="2d" id="myCanvas"></canvas>
js
const query = wx.createSelectorQuery()
query.select('#myCanvas')
.fields({
node: true,
size: true
})
.exec((res)=>{
const { node } = res[0]
if (!node) return
/* 获取 canvas 实例 */
const context = node.getContext('2d')
context.fillStyle = 'pink'
/* 设置字体样式 大小 字体类别 */
context.font = 'normal 400 12px PingFangSC-Regular',
context.fillText('hello,world', 0, 0)
})
这种方式和第一种 createSelectorQuery
方式,在api使用方式上会有微妙的差别,这种写法更像原生的DOM
写法,设置颜色,样式,直接改变context
属性,而不再需要调用对应的api
。
1、关于canvas 宽高以及缩放比问题,绘制的元素变形,画布的高度真得等于cavans标签设置的宽高么?
容器宽高: 我们给canvas
标签设置的宽高,就是如上代码中的 canvasStyle
,是canvas
容器的宽高。
画布宽高: 而我们画布的宽高,在新版本api
中,是通过获取node
节点,动态设置的node.width
和 node.height
的值。
容器宽高≠画布宽度
小程序的canvas
画布有一个原始的画布宽高,以及缩放比,而且是按照一倍像素来的,当我们给canvas
容器设定容器宽高之后,如果没有对应设置canvas
画布的画布宽高以及scale
,画出的画布就会严重的变形。如果我们期望将整个屏幕作为画布,对于不同手机,屏幕尺寸都会有差别,所以要动态获取设备的宽高。
2、canvas绘制图片
网络图片: 首先需要通过getImageInfo
来获取图片的临时路径。用getImageInfo
绘制网络资源的时候请注意配置一下合法的下载域名,要不然我们是无法成功获取图片信息的。我们首先需要在小程序后台配置downloadFile
合法域名。
api-getImageInfp:wx.getImageInfo(Object object) | 微信开放文档
/* backGroundImageUrl 是我们要画的网络图片的地址 */
this.getImageInfo(backGroundImageUrl).then(res=>{
const {
width, /* 宽度 */
height,
path /* 临时路径 */
} = res1
/* 第二步: 绘图 */
this.drawImage(context, node, path, 0, 0, width, height, 0, 0, 0, 0)
})
本地图片: 直接通过canvas
提供的drawImage
进行绘制。
const image = node.createImage();
image.src = url image.onload = () => {
context.drawImage(image,x,y,width,height,dx,dy,dwidth,dheight)
}
canvas怎么绘制叠在一起的两张图片,并控制层级?
首先想到的是层级问题,我们期望背景图片放在下面,但是在画布中没有控制zIndex
层级的属性。实际在canvas
中,绘制的先后顺序 就是画布层级顺序,后画的在先画的上层,那么对于这种层级问题呢,我们只要保证层级高的元素后画,层级低的元素先画就可以完美解决。
3、如何用canvas绘制,多行文本?
一个一个字的绘制到canvas中,然后把每个字的宽度相加,如果总宽度大于容器宽度,就另取一行从新绘制
/** 画多行文本
* @param ctx canvas 上下文
* @param str 多行文本
* @param initHeight 容器初始 top值
* @param initWidth 容器初始 left值
* @param canvasWidth 容器宽度
*/
drawRanksTexts(ctx, str, initHeight, initWidth, canvasWidth) {
let lineWidth = 0;
let lastSubStrIndex = 0;
/* 设置文字样式 */
ctx.fillStyle = "#303133"
ctx.font = 'normal 400 15px PingFangSC-Regular'
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width
if (lineWidth > canvasWidth) { /* 换行 */
ctx.fillText(str.substring(lastSubStrIndex, i), initWidth, initHeight)
initHeight += 20
lineWidth = 0
lastSubStrIndex = i
}
if (i == str.length - 1) { /* 无需换行 */
ctx.fillText(str.substring(lastSubStrIndex, i + 1), initWidth, initHeight)
}
}
},
调用
/* TODO: 复制多行文本 */
const rowsText = await this.geDomPostion('#context', true)
this.drawRanksTexts(context, this.skuName, rowsText.top, rowsText.left, rowsText.width)
4、保存海报
把当前画布指定区域的内容导出生成指定大小的图片
api-canvasToTempFilePath:wx.canvasToTempFilePath(Object object, Object this) | 微信开放文档
保存图片到系统相册
api-saveImageToPhotosAlbum:wx.saveImageToPhotosAlbum(Object object) | 微信开放文档
作者:我不是外星人
链接:https://juejin.cn/post/6930404573043490830
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。