评论

[拆弹时刻]使用官方wxml-to-canvas组件生成海报的注意事项和坑点

在使用官方组件过程遇到一些困惑,在这里记录下来并分享给大家,希望大家少踩坑

使用官方组件wxml-to-canvas的背景

由于现在很多小程序业务都需要生成海报 保存成图片便于用户分享,以往生成canvas的海报需要用户手写canvas对应的JS比较麻烦,所以官方提供了一个组件wxml-to-canvas,的确方便了不少,但也有一些坑和注意事项。

基础注意事项

  1. 默认尺寸为400*300,需要在引入的标签里自定义修改。
<wxml-to-canvas class="widget" height="996" width="500"></wxml-to-canvas>
  1. canvas 支持最大尺寸为 4096,实际像素 < 4096,实际高度需 < 4096/3 = 1356
  2. 只支持textviewimage三种标签,textimage标签必须指定 width 和 height 属性,否则会导致布局错误。view可以只制定宽度
  3. 文字 必须放在text中,放在view中无法显示
  4. 如果你要设置背景颜色,请使用backgroundColor,而非backgroundborder同理~
  5. 多个absolute元素时,因为没有z-index,template元素自上而下渲染,对应z-index依次增高
  6. 导出图片过大,可以通过canvasToTempFilePath({fileType, quality})配置里面的quality字段来减小

解决一些坑

1、wxml-to-canvas组件只支持临时地址和网络地址,不支持base64和本地图片,可以通过writeFile 把base64转成临时地址

const fs = wx.getFileSystemManager();
let qrcodeBase64 = QRresult.data;
let qrcodeLink = `${wx.env.USER_DATA_PATH}/qrcodeLink.gif`;
fs.writeFile({
    filePath: qrcodeLink,
    data: qrcodeBase64,
    encoding: 'base64',
    success: res => {
        console.log(res)
        shopJson.qrcode = qrcodeLink;
        this.renderToCanvas();
    },
    fail(res) {
        console.error(res)
    }
})

2、text设置不同style不是连续inline-block效果,而是block的换行效果

这个只能通过计算字数来设置text的width,将不同css的文字连续在一起。

上代码!

  1. 样式构建代码(仅供参考)
//DEMO.JS  部分参数外部传入
const style = {
    canvas_box: {
        width: 330,
        height: 420,
        borderRadius: 20,
        backgroundColor: '#fff',
        padding: 20,
    },
    pop_img: {
        width: 290,
        height: 146,
        borderRadius: 20,
        overflow: "hidden",
        display: "block"
    },
    pop_h3: {
        lineHeight: 24,
        height: 24,
        paddingTop: 10,
        fontSize: 16,
        color: "#333",
        width: 290,
    },
    pop_border_bottom: {
        width: 290,
        height: 1,
        backgroundColor: '#eee',
    },
    pop_h4: {
        lineHeight: 20,
        paddingTop:10,
        width:300,
        fontSize: 14,
        color: "#666",
        paddingBottom: 10,
    },
    pop_h4_text: {
        width: 300,
        height: 20,
    },
    pop_h5: {
        lineHeight: 20,
        paddingTop: 12,
        fontSize: 12,
        width: 290,
        position: "relative",
        zIndex: 2,
    },
    pop_h5_txt: {
        fontSize: 12,
        color: "#000",
        height: 20,
    },
    pop_orange: {
        fontSize: 12,
        color: "#FD6805",
        height: 20,
    },
    pop_hint: {
        position: "absolute",
        right: 20,
        bottom: 20,
        width: 290,
        height: 20,
        display: "block",
    },
    pop_hint_txt: {
        height: 20,
        width: 290,
        fontSize: 12,
        color: "#999",
    },
    pop_QRcode: {
        position: "absolute",
        right: 20,
        bottom: 20,
        width: 90,
        height: 90,
        display: "block",
        zIndex: 1,
    },
}
const poster = (shop: any) => {
    if (shop) {
        console.log(shop.address.length)
        //判断文字是否过长
        if(shop.address && shop.address.length > 20){
            shop.allAddress = `<view class="pop_h4"><text class="pop_h4_text">${shop.address.slice(0, 20)}</text><text class="pop_h4_text">${shop.address.slice(20)}</text></view>`
        }else {
            shop.allAddress = `<view class="pop_h4"><text class="pop_h4_text">${shop.address}</text></view>`
        }
        const wxml = `
            <view class="canvas_box">
                <image class="pop_img" mode="widthFix" src="${shop.img}" />
                <view class="pop_h3"><text class="pop_h3">这里是名字</text></view>
                ${shop.allAddress}
                <view class="pop_border_bottom"></view>
                <view class="pop_h3"><text class="pop_h3">这里是title</text></view>
                <image class="pop_QRcode" src="${shop.qrcode}" />
                <view class="pop_h5"><text class="pop_h5_txt">最新活动请扫码</text><text class="pop_orange">扫描二维码享受店家专属折扣!</text></view>
                <view class="pop_hint"><text class="pop_hint_txt">神秘社区强力支持</text></view>
            </view>`
        return {
            wxml,
            style
        };
    }
}
module.exports = {
    poster,
}

let shopJson = {
  name: "皮卡球",
  address: "阿罗拉阿罗拉",
  img: "https://aaa.png",
  qrcode: "https://aaa.png",
};
page({
    renderToCanvas() {
        let { wxml, style } = poster(shopJson);
        const p1 = this.widget.renderToCanvas({ wxml, style })
        console.log(p1)
        p1.then((res: any) => {
          console.log('container', res.layoutBox)
          this.container = res
        })
    },
})
  1. 将转化好的canvas保存到手机中
const p2 = this.widget.canvasToTempFilePath();
p2.then((res: any) => {
    console.log(res.tempFilePath);
    //保存到本地
    wx.saveImageToPhotosAlbum({
        filePath: res.tempFilePath,
        success(res) {
            console.log(res);
            wx.showToast({
                title: "保存成功",
                icon: "success",
                duration: 2000,
            });
        },
        //被拒绝后的操作
        fail(res) {
            console.log(res);
            wx.showModal({
                title: "提示",
                content: "保存失败,重新打开",
                success(res) {
                    if (res.confirm) {
                        console.log("用户点击确定");
                        wx.getSetting({
                            success(res) {
                                console.log(res.authSetting);
                            },
                        });
                    }
                },
            });
        },
    });
});

官方地址

https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/extended/component-plus/wxml-to-canvas.html

代码片段

https://developers.weixin.qq.com/s/r6UBlEm17pc6

最后一次编辑于  2023-10-20  
点赞 3
收藏
评论
登录 后发表内容