当前位置: 首页 > 工具软件 > X-Canvas > 使用案例 >

微信小程序---canvas

宗政洋
2023-12-01

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绘制图片

 api-drawImage:CanvasContext.drawImage(string imageResource, number sx, number sy, number sWidth, number sHeight, number dx, number dy, number dWidth, number dHeight) | 微信开放文档

网络图片: 首先需要通过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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 类似资料: