index.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <!-- 海报弹窗 -->
  2. <template>
  3. <su-popup :show="show" round="10" @close="onClosePoster" type="center" class="popup-box">
  4. <view class="ss-flex-col ss-col-center ss-row-center">
  5. <image
  6. v-if="!!painterImageUrl"
  7. class="poster-img"
  8. :src="painterImageUrl"
  9. :style="{
  10. height: poster.css.height+ 'px',
  11. width: poster.css.width + 'px',
  12. }"
  13. :show-menu-by-longpress="true"
  14. />
  15. </view>
  16. <view
  17. class="poster-btn-box ss-m-t-20 ss-flex ss-row-between ss-col-center"
  18. v-if="!!painterImageUrl"
  19. >
  20. <button class="cancel-btn ss-reset-button" @tap="onClosePoster">取消</button>
  21. <button class="save-btn ss-reset-button ui-BG-Main" @tap="onSavePoster">
  22. {{
  23. ['wechatOfficialAccount', 'H5'].includes(sheep.$platform.name)
  24. ? '长按图片保存'
  25. : '保存图片'
  26. }}
  27. </button>
  28. </view>
  29. <!-- 海报画板:默认隐藏只用来生成海报。生成方式为主动调用 -->
  30. <l-painter
  31. isCanvasToTempFilePath
  32. pathType="url"
  33. @success="setPainterImageUrl"
  34. hidden
  35. ref="painterRef"
  36. />
  37. </su-popup>
  38. </template>
  39. <script setup>
  40. /**
  41. * 海报生成和展示
  42. * 提示:小程序码默认跳转首页,由首页进行 spm 参数解析后跳转到对应的分享页面
  43. * @description 用于生成分享海报,如:分享商品海报。
  44. * @tutorial https://ext.dcloud.net.cn/plugin?id=2389
  45. * @property {Boolean} show 弹出层控制
  46. * @property {Object} shareInfo 分享信息
  47. */
  48. import { reactive, ref, unref } from 'vue';
  49. import sheep from '@/sheep';
  50. import { getPosterData } from '@/sheep/components/s-share-modal/canvas-poster/poster';
  51. const props = defineProps({
  52. show: {
  53. type: Boolean,
  54. default: false,
  55. },
  56. shareInfo: {
  57. type: Object,
  58. default: () => {
  59. },
  60. },
  61. });
  62. const poster = reactive({
  63. css: {
  64. // 根节点若无尺寸,自动获取父级节点
  65. width: sheep.$platform.device.windowWidth * 0.9,
  66. height: 550,
  67. },
  68. views: [],
  69. });
  70. const emits = defineEmits(['success', 'close']);
  71. const onClosePoster = () => {
  72. emits('close');
  73. };
  74. const painterRef = ref(); // 海报画板
  75. const painterImageUrl = ref(); // 海报 url
  76. // 渲染海报
  77. const renderPoster = async () => {
  78. await painterRef.value.render(unref(poster));
  79. };
  80. // 获得生成的图片
  81. const setPainterImageUrl = (path) => {
  82. painterImageUrl.value = path;
  83. };
  84. // 保存海报图片
  85. const onSavePoster = () => {
  86. if (['WechatOfficialAccount', 'H5'].includes(sheep.$platform.name)) {
  87. sheep.$helper.toast('请长按图片保存');
  88. return;
  89. }
  90. // 非H5 保存到相册
  91. uni.saveImageToPhotosAlbum({
  92. filePath: painterImageUrl.value,
  93. success: (res) => {
  94. onClosePoster();
  95. sheep.$helper.toast('保存成功');
  96. },
  97. fail: (err) => {
  98. sheep.$helper.toast('保存失败');
  99. console.log('图片保存失败:', err);
  100. },
  101. });
  102. };
  103. // 获得海报数据
  104. async function getPoster() {
  105. painterImageUrl.value = undefined
  106. poster.views = await getPosterData({
  107. width: poster.css.width,
  108. shareInfo: props.shareInfo,
  109. });
  110. await renderPoster();
  111. }
  112. defineExpose({
  113. getPoster,
  114. });
  115. </script>
  116. <style lang="scss" scoped>
  117. .popup-box {
  118. position: relative;
  119. }
  120. .poster-title {
  121. color: #999;
  122. }
  123. // 分享海报
  124. .poster-btn-box {
  125. width: 600rpx;
  126. position: absolute;
  127. left: 50%;
  128. transform: translateX(-50%);
  129. bottom: -80rpx;
  130. .cancel-btn {
  131. width: 240rpx;
  132. height: 70rpx;
  133. line-height: 70rpx;
  134. background: $white;
  135. border-radius: 35rpx;
  136. font-size: 28rpx;
  137. font-weight: 500;
  138. color: $dark-9;
  139. }
  140. .save-btn {
  141. width: 240rpx;
  142. height: 70rpx;
  143. line-height: 70rpx;
  144. border-radius: 35rpx;
  145. font-size: 28rpx;
  146. font-weight: 500;
  147. }
  148. }
  149. .poster-img {
  150. border-radius: 20rpx;
  151. }
  152. </style>