【uni-app】微信小程序使用lime-painter生成海报

302 阅读3分钟

lime-painter是一个专为 UniApp 设计的插件,用于优雅地生成海报,并支持下载海报图片。它支持在多个平台中使用,并且提供了盒子、文字、图片、二维码等配置选项,允许开发者根据项目需求按照UI设计稿对海报进行高度还原。本文将介绍如何使用 lime-painter 插件在 UniApp 中实现海报的生成及下载。

技术栈:uni-app、Vue3(3.4.21)、TypeScript(4.9.5)、wot-design-uni(1.2.26)、UnoCSS(0.58.9)、pyh-nv

运行环境:微信小程序

image.png

平台兼容性

image.png

image.png

  • 非uni_modules方式:🈚️
  • 基本用法

  • 方式1:Template形式

  • 提供l-painter-viewl-painter-textl-painter-imagel-painter-qrcode四种类型组件
  • 通过 css 属性绘制样式,与 style 使用方式保持一致。(这里需要注意并非所有原生CSS样式都能生效,下面配置项会介绍可传的样式。)
<l-painter>
//如果使用Template出现顺序错乱,可使用`template` 等所有变量完成再显示
<template v-if="show">
    <l-painter-view
        css="background: #07c160; height: 120rpx; width: 120rpx; display: inline-block"
    ></l-painter-view>
    <l-painter-view
        css="background: #1989fa; height: 120rpx; width: 120rpx; border-top-right-radius: 60rpx; border-bottom-left-radius: 60rpx; display: inline-block; margin: 0 30rpx;"
    ></l-painter-view>
    <l-painter-view
        css="background: #ff9d00; height: 120rpx; width: 120rpx; border-radius: 50%; display: inline-block"
    ></l-painter-view>
<template>
</l-painter>

  • 方式2:JSON配置形式

  • 在 json 里四种类型组件的typeviewtextimageqrcode
  • 通过 board 设置海报所需的 JSON 数据进行绘制或ref获取组件实例调用组件内的render(json)
<l-painter :board="poster"/>

const poster = ref({
  css: {
    // 根节点若无尺寸,自动获取父级节点
    width: '750rpx',
  },
  views: [
    {
      css: {
        background: '#07c160',
        height: '120rpx',
        width: '120rpx',
        display: 'inline-block',
      },
      type: 'view',
    },
    {
      css: {
        background: '#1989fa',
        height: '120rpx',
        width: '120rpx',
        borderTopRightRadius: '60rpx',
        borderBottomLeftRadius: '60rpx',
        display: 'inline-block',
        margin: '0 30rpx',
      },
      views: [],
      type: 'view',
    },
    {
      css: {
        background: '#ff9d00',
        height: '120rpx',
        width: '120rpx',
        borderRadius: '50%',
        display: 'inline-block',
      },
      views: [],
      type: 'view',
    },
  ],
})

  • 配置项

  • Props参数说明

image.png

  • CSS

image.png

image.png

image.png

  • 事件Events及暴露函数 Expose

image.png

实现步骤

  • poster子组件

  • template中编写页面代码

<template>
  <wd-popup
    v-model="show"
    position="bottom"
    :z-index="999"
    custom-style="background: transparent;"
    @close="handleClose"
  >
    <view class="center flex-col">
      <view v-if="show" class="poster">
        <l-painter
          ref="poster"
          css="width: 530rpx;"
          :custom-style="`filter: blur(10px);background: rgba(0,0,0,0.4);background-image: url(${info.actInfoImg});background-size: cover;`"
          pathType="url"
          performance
          style="width: 530rpx"
          :is-canvas-to-temp-file-path="true"
          @fail="painterFail"
          @done="painterDone"
          @success="painterSuccess"
        >
          <l-painter-view css="background: #fff;padding: 23rpx 30rpx;margin: 30rpx;">
            <l-painter-text
              :text="info.actName"
              css="font-size: 27rpx; color: #000; line-height: 38rpx; margin-top: 23rpx; line-clamp: 1;"
            />
            <l-painter-view css="display: flex; justify-content: space-between; margin-top: 11rpx;">
              <l-painter-text
                :text="`2024.12.15 19:30 周日`"
                css="font-size: 23rpx; color: #777F86; line-height: 27rpx;margin-bottom: 23rpx;"
              />
            </l-painter-view>
            <l-painter-image
              :src="info.actInfoImg"
              css="object-fit: cover; object-position: 50% 50%; width: 412rpx; height: 549rpx;border-radius: 15rpx;"
            />

            <l-painter-view
              css="border-top: 1rpx solid #BCC5CD; margin-top: 23rpx;"
            ></l-painter-view>
            <l-painter-view
              css="padding-top: 17rpx; display: flex; justify-content: space-between;"
            >
              <l-painter-view>
                <l-painter-view css="margin-top: 10rpx;">
                  <l-painter-text
                    text="保存图片到相册"
                    css="font-size: 19rpx; color: #777F86; line-height: 27rpx;"
                  />
                </l-painter-view>
                <l-painter-view css="margin-top: 10rpx;">
                  <l-painter-text
                    text="扫码可见"
                    css="font-size: 19rpx; color: #777F86; line-height: 27rpx;"
                  />
                </l-painter-view>
              </l-painter-view>
              <l-painter-view css="padding: 7rpx; background: #FFFFFF; border-radius: 7rpx;">
                <l-painter-qrcode
                  css="width: 69rpx; height: 69rpx;"
                  :text="postCode"
                ></l-painter-qrcode>
              </l-painter-view>
            </l-painter-view>
          </l-painter-view>
        </l-painter>
      </view>
      <view class="main">
        <view class="footer">
          <view
            class="w-100% h-80rpx bg-#eb1818 color-#fff flex center backdrop-blur-10rpx"
            @tap="downloadPoster"
          >
            保存图片
          </view>
        </view>
      </view>
    </view>
  </wd-popup>
</template>

  • 编写script脚本,保存海报图片地址

海报渲染成功时事件会返回生成图片的地址。注意:需要l-painter组件设置参数:is-canvas-to-temp-file-path="true"

const posterTempFilePath = ref<string>('')

const painterSuccess = (path) => {
  posterTempFilePath.value = path
}

其他一些交互上的细节,如生成中、生成失败、关闭海报等。

const painterFail = (e) => {
  uni.hideLoading()
  uni.showToast({
    title: `生成失败,请重试: ${e}`,
    icon: 'none',
  })
}

const painterDone = () =>{
  uni.hideLoading()
}

const handleClose = () => {
  show.value = false
}

watch(
  () => show.value,
  (val) => {
    if (val) {
      uni.showLoading({ title: '海报生成中', mask: true })
    } else {
      posterTempFilePath.value = ''
    }
  },
)

  • 保存海报图片到本地

注意本次是在微信小程序上运行,不适用H5下载的情况。

const downloadPoster = () => {
  uni.saveImageToPhotosAlbum({
    filePath: posterTempFilePath.value,
    success(res) {
      uni.showToast({
        title: '已保存到相册',
        icon: 'success',
        duration: 2000,
      })
    },
    fail: (err) => {
      uni.showToast({
        title: `保存失败: ${JSON.stringify(err)}`,
        icon: 'none',
      })
    },
  })
}

实现效果

点击顶部导航栏分享按钮,开始生成海报:

​编辑

允许保存图片到相册:

​编辑

保存图片成功:

​编辑

细节注意

  • 当需要设置海报背景毛玻璃效果时,不能通过传参css设置filter,因为该插件所支持的CSS样式有限。若需要自定义样式,需要在l-painter传参数custom-style。注意:该参数样式作用于canvas 父view元素。
  • 虽然在custom-style上设置filter目前视觉效果还可以,但是下载图片会发现海报丢失细节。建议在css参数中设置的背景图即为毛玻璃效果后的图片。或者用渐变背景色替代。
  • 二维码text属性是需要生成二维码的文本
  • 使用网络图片时:小程序需要去公众平台配置 downloadFile 域名,H5 需要决跨域问题
  • 更多细节可查看插件详情:海报画板 - DCloud 插件市场

以上就是使用lime-painter生成海报的介绍啦^-^