index.vue 4.8 KB

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