Skip to content

mp-share-modal 分享卡片弹窗

介绍文档:分享海报组件

代码演示

vue
<script setup>
import {onShow} from '@dcloudio/uni-app'
import {useToggle} from '@vueuse/core'
import {sleep} from 'licia'
import {onMounted, ref} from 'vue'

const [shareModalVisible, toggleShareModalVisible] = useToggle(false)
const [shareModalVisible1, toggleShareModalVisible1] = useToggle(false)

let shared = false

const CANVAS_WIDTH = ref(250)
const CANVAS_HEIGHT = ref(250)
const percent = 0.7
const canvasImagePath = ref('')

onMounted(() => {
  drawCanvas()
})

async function drawCanvas() {
  const ctx = uni.createCanvasContext('myCanvas')

  ctx.fillStyle = 'rgba(255, 255, 255, 0)'

  // 圆环
  ctx.beginPath()
  ctx.arc(CANVAS_WIDTH.value / 2, CANVAS_HEIGHT.value / 2, 112, 0, 2 * Math.PI)
  ctx.lineWidth = 15
  ctx.lineCap = 'round'
  ctx.strokeStyle = '#eee'
  ctx.stroke()

  // 进度条
  ctx.beginPath()
  ctx.arc(
    CANVAS_WIDTH.value / 2,
    CANVAS_HEIGHT.value / 2,
    112,
    -Math.PI / 2,
    -Math.PI / 2 + percent * (Math.PI * 2),
    false
  )
  ctx.lineWidth = 15
  ctx.lineCap = 'round'
  ctx.strokeStyle = 'rgb(255, 127, 105)'
  ctx.stroke()

  ctx.draw()

  await sleep(300)

  const {tempFilePath} = await uni.canvasToTempFilePath({
    canvasId: 'myCanvas',
    x: 0,
    y: 0,
    width: CANVAS_WIDTH.value,
    height: CANVAS_HEIGHT.value,
  })

  canvasImagePath.value = tempFilePath
}

const onClickSheet = sheet => {
  if (sheet.type === 'share') {
    // eslint-disable-next-line no-console
    console.log('点击分享给好友按钮')

    shared = true
  }
}

onShow(() => {
  if (shared) {
    // eslint-disable-next-line no-console
    console.log('分享给好友成功')
    shared = false
  }
})
</script>

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

  <button @click="toggleShareModalVisible(true)">显示分享弹窗(附加自定义 canvas 内容)</button>
  <button @click="toggleShareModalVisible1(true)">显示分享弹窗(纯图片)</button>

  <mp-share-modal v-model:visible="shareModalVisible" @clickSheet="onClickSheet">
    <!-- 绘制容器,必须 -->
    <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"
      />
      <image
        class="draw canvas-image"
        data-type="image"
        :data-url="canvasImagePath"
        :src="canvasImagePath"
      />
    </view>
  </mp-share-modal>

  <mp-share-modal
    v-model:visible="shareModalVisible1"
    containerStyle="border-radius: 10rpx;"
    image="https://cloud-minapp-37888.cloud.ifanrusercontent.com/1r2or2zNZwp1cJJT.png"
    imageStyle="width: 550rpx; height: 1960rpx;"
    @clickSheet="onClickSheet"
  />

  <view>canvas 内容</view>
  <canvas
    id="myCanvas"
    canvas-id="myCanvas"
    class="canvas"
    :class="{hide: shareModalVisible || shareModalVisible1}"
    :style="{
      width: `${CANVAS_HEIGHT}px`,
      height: `${CANVAS_WIDTH}px`,
    }"
  />
</template>

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

.share-bg {
  width: 100%;
  height: 100%;
}

.canvas-image {
  position: absolute;
  right: 20rpx;
  bottom: 6rpx;
  width: 180rpx;
  height: 180rpx;
}

.hide {
  position: absolute;
  top: 0;
  left: -200%;
}
</style>

自定义操作按钮

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

const [shareModalVisible, toggleShareModalVisible] = useToggle(false)

const $shareModal = ref(null)

const customSheets = computed(() => {
  if (!$shareModal.value) return []

  const defaultSheets = $shareModal.value.getDefaultSheets()

  return [
    ...defaultSheets,
    {
      icon: 'https://cloud-minapp-41177.cloud.ifanrusercontent.com/1qLIRTsoCUkDlROq.png',
      text: '自定义按钮',
      event: async () => {
        // 绘制图片
        const image = await $shareModal.value.draw()

        // eslint-disable-next-line no-console
        console.log('result', image)

        $shareModal.value.close()
      },
    },
  ]
})
</script>

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

  <button @click="toggleShareModalVisible(true)">显示分享弹窗(自定义操作按钮)</button>

  <mp-share-modal ref="$shareModal" v-model:visible="shareModalVisible" :sheets="customSheets">
    <!-- 绘制容器,必须 -->
    <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 {
  position: relative;
  width: 550rpx;
  height: 960rpx;
}

.share-bg {
  width: 100%;
  height: 100%;
}

.canvas-image {
  position: absolute;
  right: 20rpx;
  bottom: 6rpx;
  width: 180rpx;
  height: 180rpx;
}

.hide {
  position: absolute;
  top: 0;
  left: -200%;
}
</style>

API

Props

Prop nameDescriptionTypeValuesDefault
visible v-model显示弹窗boolean-
sheets分享菜单array|null-null
backgroundColor背景颜色,不传默认为 #fffstring-''
image自定义图片,适用于无需生成,仅保存分享的情况string-''
imageStyle自定义图片样式,配合 image 属性使用string|object-''
containerStyle容器样式string|object-''

Expose

draw

() => void

生成图片

open

() => void

显示弹窗

close

() => void

关闭弹窗

getDefaultSheets

() => object[]

获取默认按钮菜单

Events

Event namePropertiesDescription
close关闭时触发
click-sheetsheet object - 被点击的菜单按钮项点击分享菜单按钮

Slots

NameDescriptionBindings
default绘制内容,如有设置 image 属性则该 slot 不起作用
share-sheet自定义菜单

源码

组件示例