微信小程序海报插件Painter 2.0(canvas画图)使用并保存图片到相册案例

一、下载与引入

Painter通过 json 数据形式,来进行动态渲染并绘制出图片。

Painter 的优势

  • 功能全,支持文本、图片、矩形、qrcode 类型的 view 绘制
  • 布局全,支持多种布局方式,如 align(对齐方式)、rotate(旋转)
  • 支持圆角,其中图片,矩形,和整个画布支持 borderRadius 来设置圆角
  • 支持边框,同时支持 solid、dashed、dotted 三种类型
  • 支持渐变色,包括线性渐变与径向渐变。
  • 支持 box-shadow 和 text-shadow,统一使用 shadow 表示。
  • 支持文字背景、获取宽度、主动换行
  • 支持自定义字体
  • 支持图片 mode
  • 支持元素的相对定位方法
  • 杠杠的性能优化,我们对网络素材图片加载实现了一套 LRU 存储机制,不用重复下载素材图片。
  • 杠杠的容错,因为某些特殊情况会导致 Canvas 绘图不完整。我们对此加入了对结果图片进行检测机制,如果绘图出错会进行重绘。
  • 生成的图片支持分辨率调节
  • 支持使用拖动等操作动态编辑绘制内容

文件源码和文档地址:https://gitee.com/jackhunx/Painter

下载文件保存到components文件夹下

javascript 复制代码
//在需要使用的页面json中引入
"usingComponents": {
    "painter":"/components/painter/painter"
}

二、使用

wxml

javascript 复制代码
<!-- 海报弹框 -->
<van-popup show="{{isPosterShow}}" bind:close="closePosterFn" custom-style="background: none;">
    <view class="poster">
        <image bind:tap="saveImageFn" src="{{posterImageUrl}}" mode=""/>
        <text>点击图片,保存至手机相册</text>
    </view>
</van-popup>

<painter palette="{{posterData}}" bind:imgOK="onImageOK" />

js

javascript 复制代码
var app = getApp();
Page({

    /**
     * 页面的初始数据
     */
    data: {
        isPosterShow: false,//海报弹框
        qrCodeUrl: "",//二维码图片路径
        posterData: {},//海报数据
        posterImageUrl: "",//海报图片
    },
    //绘制海报
    drawPosterFn(){
    	wx.showLoading({
            title: '生成中',
        })
        this.setData({
             posterData: {
                 background: '背景颜色或背景图片地址',
                 width: '1164rpx',
                 height: '1548rpx',
                 views: [
                     {
                         type: "text",
                         text: "文字内容",
                         css: {
                             top: "256rpx",
                             left: "82rpx",
                             width: "1000rpx",
                             fontSize: "72rpx",
                             color: "#0159BB",
                             maxLines: 2,
                             lineHeight: "108rpx",
                             textAlign: "center",
                             fontWeight: "bold"
                         }
                     },
                     {
                         type: 'image',
                         url: "二维码图片地址",
                         css: {
                             top: '680rpx',
                             left: '264rpx',
                             width: '640rpx',
                             height: '640rpx',
                         },
                     }
                 ],
             }
         })
    },
    //监听海报是否生成成功
    onImageOK(e){
        wx.hideLoading();
        this.setData({
            isPosterShow: true,
            posterImageUrl: e.detail.path
        })
    },
    //保存图片到本地
    saveImageFn(){
        let that = this
        wx.saveImageToPhotosAlbum({
            filePath: this.data.posterImageUrl,
            success(res) {
                wx.hideLoading()
                wx.showToast({
                    title: '保存成功',
                    icon: "success",
                    duration: 1000
                })
            },
            fail(err) {
                console.log(err)
                if(err.errMsg == "saveImageToPhotosAlbum:fail auth deny"){
                    wx.showModal({
                        content: '检测到您没有授权保存到相册权限,是否去设置打开?',
                        confirmText: "确认",
                        cancelText: "取消",
                        success: function(res) {
                            //点击"确认"时打开设置页面
                            if (res.confirm) {
                                wx.openSetting({
                                    success () {
                                        that.savePhoto();
                                    }
                                })
                            } else {
                                
                            }
                        }
                    });
                }else if(err.errMsg == "saveImageToPhotosAlbum:fail privacy permission is not authorized"){
					app.showMsg("没有同意用户隐私协议!");
                }else if(err.errMsg == "saveImageToPhotosAlbum:fail privacy permission is not authorized in gap"){
                    app.showMsg("保存失败!");
                }else{
                    app.showMsg(err.errMsg);
                }
            }
        })
    },
    //下载图片地址并保存到相册,提示保存成功
    savePhoto() {
        wx.saveImageToPhotosAlbum({
            filePath: this.data.posterImageUrl,
            success(res) {
                wx.hideLoading()
                wx.showToast({
                    title: '保存成功',
                    icon: "success",
                    duration: 1000
                })
            },
            fail() {
                wx.showToast({
                    title: '保存失败',
                    icon: "error",
                    duration: 1000
                })
            }
        })
    },
    //关闭海报弹框
    closePosterFn(){
        this.setData({
            isPosterShow: false
        })
    },
    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady() {
        this.drawPosterFn()
    },
})
相关推荐
IT_陈寒11 小时前
Python的切片赋值把我坑惨了,这不是bug是特性
前端·人工智能·后端
掘金酱11 小时前
【社区公告】致每一位掘友:关于这次调整, 想再说几句
前端·人工智能
CoderLiu11 小时前
程序化工具调用(PTC)与动态工作流引擎:深入大模型工具调用的架构演进与实践
前端·人工智能·后端
码农胖大海12 小时前
我的第一个产品,只有一段提示词
前端·ai编程·产品
邋遢道12 小时前
# 企业级 Agent 从 0 到 1(二):技术选型与最小骨架
前端·chrome
计算机魔术师12 小时前
我看了 OpenAI 首席科学家的最新长文,把原来的认知推翻了一遍
前端
乱码三千13 小时前
使用ComfyUI+MinMax-H3音视频模型生成视频
前端·后端·github
Coder_Ke13 小时前
代码我都定位了,Codex 还在考古:于是我写了个 VS Code 插件
前端
LiaCode14 小时前
别让 AI 把仓库写成“代码平行宇宙”:从 Deslop 看生成前查重
前端·后端·github
nice先生的狂想曲14 小时前
javascript高级程序设计(六)——2026.9.5
前端·javascript