小程序海报绘制方案(原生,Uniapp,Taro)

背景

  1. 小程序海报绘制方案有很多,但是大多数都是基于canvas的,而且都是自己封装的,不够通用,不够灵活,不够简单,不够好用。
  2. 本方使用一个开源的小程序海报绘制,非常灵活,扩展性非常好,仅布局就能得到一张海报。

准备工作

安装依赖,也可以把源码下载到本地,源码地址。

shell 复制代码
npm install wxml2canvas

布局

无论哪种方案,布局都是一致的,需要注意一些暂未支持的属性:

  1. 变形:transform,但是节点元素使能读取此属性,但是库不支持,所以不要使用
  2. 圆角,border-radius,同上,不要使用,圆形图片有特定的属性去实现,除此之外无法实现其他类型的圆角

布局示例:

注意,除了uniapp,原生和Taro要使用原生组件的方式绘制canvas,因为Taro不支持data-xx的属性绑定方式,这一点很糟糕

html 复制代码
<!-- 外层wrap用于fixed定位,使得整个布局离屏,离屏canvas暂未支持 -->
<view class='wrap'>
  <!-- canvas id,一会 new 的时候需要 -->
  <canvas canvas-id="poster-canvas"></canvas>
  <view class="container">
    <view data-type="text" data-text="测试文字绘制" class='text'>测试文字绘制</view>
    <image data-type="image" data-src="https://img.yzcdn.cn/vant/cat.jpeg" class='image'></image>
    <image data-type="radius-image" data-src="https://img.yzcdn.cn/vant/cat.jpeg" class='radius-image'></image>
  </view>
</view>

原生小程序

js 复制代码
import Wxml2Canvas from 'wxml2canvas'

Component({
  methods: {
    paint() {
      wx.showLoading({ title: '生成海报' });
      // 创建绘制实例
       const drawInstance = new Wxml2canvas({
        // 组件的this指向,组件内使用必传
        obj: this,
        // 画布宽高
        width: 275,
        height: 441,
        // canvas-id
        element: 'poster-canvas',
        // 画布背景色
        background: '#f0f0f0',
        // 成功回调
        finish: (url) => {
          console.log('生成的海报url,开发者工具点击可预览', url);
          wx.hideLoading();
        },
        // 失败回调
        error: (err) => {
          console.error(err);
          wx.hideLoading();
        },
      });
      // 节点数据
      const data = {
        list: [
          {
            // 此方式固定 wxml
            type: 'wxml',
            class: '.text', // draw_canvas指定待绘制的元素
            limit: '.container', // 限定绘制元素的范围,取指定元素与它的相对位置计算
          }
          {
            // 此方式固定 wxml
            type: 'wxml',
            class: '.image', // draw_canvas指定待绘制的元素
            limit: '.container', // 限定绘制元素的范围,取指定元素与它的相对位置计算
          }
          {
            // 此方式固定 wxml
            type: 'wxml',
            class: '.radius-image', // draw_canvas指定待绘制的元素
            limit: '.container', // 限定绘制元素的范围,取指定元素与它的相对位置计算
          }
        ]
      }
     // 调用绘制方法
     drawInstance.draw(data);
    }
  }
})

Uniapp

uniapp 主要讲Vue3的版本,因为涉及 this,需要获取 this 以及时机

js 复制代码
import {  getCurrentInstance} from 'vue';
// 调用时机 setup内,不能在其他时机
// @see https://github.com/dcloudio/uni-app/issues/3174
const instance = getCurrentInstance();


function paint() {
  uni.showLoading({ title: '生成海报' });
  const drawInstance = new Wxml2Canvas({
    width: 290, // 宽, 以iphone6为基准,传具体数值,其他机型自动适配
    height: 430, // 高
    element: 'poster-canvas', // canvas-id
    background: '#f0f0f0',
    obj: instance,
    finish(url: string) {
      console.log('生成的海报url,开发者工具点击可预览', url);
      uni.hideLoading();
    },
    error(err: Error) {
      console.error(err);
      uni.hideLoading();
    },
  });
  // 节点数据
  const data = {
    list: [
      {
        // 此方式固定 wxml
        type: 'wxml',
        class: '.text', // draw_canvas指定待绘制的元素
      }
      {
        // 此方式固定 wxml
        type: 'wxml',
        class: '.image', // draw_canvas指定待绘制的元素
      }
      {
        // 此方式固定 wxml
        type: 'wxml',
        class: '.radius-image', // draw_canvas指定待绘制的元素
      }
    ]
  }
  // 调用绘制方法
  drawInstance.draw(data);
}

Taro

Taro 比较特殊,框架层面的设计缺陷导致了 Taro 组件增加的 data-xx 属性在编译的时候是会清除的,因此Taro要使用这个库要用原生小程序的方式编写组件。

代码和原生的一样,只是要用原生的方式编写组件,然后在 Taro 中使用。 参考原生的代码,原生小程序js参考这

假设原生组件名为 draw-poster,那么首先需要再Taro的页面中引入这个组件,然后在页面中使用这个组件,然后在组件中使用这个库。

js 复制代码
export default {
  navigationBarTitleText: '',
  usingComponents: {
    'draw-poster': '../../components/draw-poster/index',
  },
};
jsx 复制代码
  const draw = useCallback(() => {
    const { page } = Taro.getCurrentInstance();
    // 拿到目标组件实例调用里面的方法
    const instance = page!.selectComponent('#draw_poster');
    // 调用原生组件绘制方法
    instance.paint();
  }, []);
 return <draw-poster id="draw_poster"/>

总结

对比原生的canvas绘制方案,布局的方式获取节点的方式都是一样的,只是绘制的时候不一样,原生的是直接绘制到canvas上,而这个库是先把布局转换成canvas,然后再绘制到canvas上,所以这个库的性能会比原生的差一些,但是这个库的优势在于布局的方式,不需要自己去计算位置,只需要布局,然后调用绘制方法就可以了,非常方便,而且扩展性非常好,可以自己扩展一些布局方式,比如说flex布局,grid布局等等,这些都是可以的,只需要在布局的时候把布局转换成canvas的布局就可以了,这个库的布局方式是参考的微信小程序的布局方式,所以布局的时候可以参考微信小程序的布局方式,这样就可以很方便的布局了。

相关推荐
福兮说12 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理13 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66613 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)14 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan14 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_15 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒15 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技15 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
星光开发者15 小时前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express
yivifu16 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub