Skip to content

分享海报组件 - mp-share-modal

分享海报在项目开发中是一个非常常见的需求,通常我们使用 Painter 来实现海报的绘制。然而,Painter 需要通过 JSON 进行配置,这在布局实现时可能不如 HTML + CSS 那样灵活和便捷,并且除了绘制图片本身,还通常需要搭配弹窗、分享、保存等动作。

因此,我们开发这个组件,快速实现弹窗、根据 HTML + CSS 生成图片、分享或保存等功能。

强烈建议在项目中使用,以确保风格的一致性。

TIP

HTML + CSS 转换 Painter 配置部分我们是基于 Wxml2Json 实现的,通常我们更推荐使用现有组件,只有当现有组件无法满足需求时,才考虑使用 Wxml2Json 自行实现。

基本用法

引入 painter

你需要先在项目中引入这个组件,可以拷贝 previewer,然后在 pages.json

json
"globalStyle": {
  "usingComponents": {
    "painter": "/wxcomponents/painter/painter"
  }
}
"globalStyle": {
  "usingComponents": {
    "painter": "/wxcomponents/painter/painter"
  }
}

使用 mp-share-modal

通常我们的分享海报弹窗长这样:

这个弹窗可以分为两个部分「海报图片」和「底部按钮」,而「底部按钮」包括分享按钮和保存图片按钮。

通过 visible 属性来控制弹窗的显示状态,而 sheets 属性用于控制底部按钮列表。如果不传入 sheets,则会使用默认的两个按钮。此外,你还可以通过 slot#share-sheet 来自定义底部按钮的渲染方式。

值得注意的是,默认的两个按钮都有内置的逻辑。分享按钮会触发分享操作(使用 open-type=share),而保存按钮会根据 slot 的内容进行绘制,获取图片地址并保存。因此,如果你需要自定义按钮,不管是通过 sheets 还是通过 slot#share-sheet,你需要完全自行实现按钮的逻辑。

vue
<script setup>
import {useToggle} from '@vueuse/core'

const [shareModalVisible, toggleShareModalVisible] = useToggle(false)
</script>

<template>
  <mp-nav-bar title="mp-share-modal"></mp-nav-bar>

  <button @click="toggleShareModalVisible(true)">显示分享弹窗</button>

  <mp-share-modal v-model:visible="shareModalVisible">
    <!-- 绘制容器,必须 -->
    <view class="draw-container">
      <!-- 绘制节点,必须有 .draw CSS 类名,data-type 必填 -->
      <image
        class="draw share-bg"
        data-type="image"
        data-url="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
        src="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
      />
    </view>
  </mp-share-modal>
</template>

<style scoped>
.draw-container {
  width: 550rpx;
  height: 960rpx;
}

.share-bg {
  width: 100%;
  height: 100%;
}
</style>
<script setup>
import {useToggle} from '@vueuse/core'

const [shareModalVisible, toggleShareModalVisible] = useToggle(false)
</script>

<template>
  <mp-nav-bar title="mp-share-modal"></mp-nav-bar>

  <button @click="toggleShareModalVisible(true)">显示分享弹窗</button>

  <mp-share-modal v-model:visible="shareModalVisible">
    <!-- 绘制容器,必须 -->
    <view class="draw-container">
      <!-- 绘制节点,必须有 .draw CSS 类名,data-type 必填 -->
      <image
        class="draw share-bg"
        data-type="image"
        data-url="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
        src="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
      />
    </view>
  </mp-share-modal>
</template>

<style scoped>
.draw-container {
  width: 550rpx;
  height: 960rpx;
}

.share-bg {
  width: 100%;
  height: 100%;
}
</style>

WARNING

注意,.draw-container 和 .draw 只能写在同一个组件中,例如以下代码会导致图片无法生成:

vue
<!-- act-share.vue 假设项目封装了这个组件 -->
<template>
  <mp-share-modal v-model:visible="shareModalVisible">
    <!-- ❌ 不起作用 -->
    <view class="draw-container">
      <!-- 假设所需绘制节点由外部通过 slot 传入 -->
      <slot />
    </view>

    <!-- ✅ 起作用 -->
    <view class="draw-container">
      <image
        class="draw share-bg"
        data-type="image"
        data-url="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
        src="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
      />
    </view>
  </mp-share-modal>
</template>
<!-- act-share.vue 假设项目封装了这个组件 -->
<template>
  <mp-share-modal v-model:visible="shareModalVisible">
    <!-- ❌ 不起作用 -->
    <view class="draw-container">
      <!-- 假设所需绘制节点由外部通过 slot 传入 -->
      <slot />
    </view>

    <!-- ✅ 起作用 -->
    <view class="draw-container">
      <image
        class="draw share-bg"
        data-type="image"
        data-url="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
        src="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
      />
    </view>
  </mp-share-modal>
</template>

这是因为 mp-share-modal 内部依赖 wx.createSelectorQuery,上述代码会导致 context 无法正确获取节点,请知悉。

相关文档