index.vue 3.9 KB

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