index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <template>
  2. <div class="simple-share" v-if="shareFlag">
  3. <!-- 分享按钮 -->
  4. <div class="share__btns" @click="handleShare"></div>
  5. <!-- 分享弹窗 -->
  6. <div class="share__dialog" v-if="showDialog">
  7. <div class="share__dialog_wrapper">
  8. <div class="share__dialog__item" @click="handleShareWechat">
  9. <i class="icon icon-share-wechat"></i>
  10. <span>分享给好友</span>
  11. </div>
  12. <template v-if="showImage">
  13. <div class="share__dialog__item">
  14. <i class="icon icon-share-download"></i>
  15. <span>保存相册</span>
  16. </div>
  17. </template>
  18. <template v-else>
  19. <div class="share__dialog__item" @click="handleGenerateImage">
  20. <i class="icon icon-share-code"></i>
  21. <span>生成二维码</span>
  22. </div>
  23. </template>
  24. </div>
  25. <div class="share-concel" @click="handleCancel">取消</div>
  26. </div>
  27. <!-- 图片预览 -->
  28. <div class="share__image" v-if="showImage"><img :src="imageUrl" /></div>
  29. <!-- 遮罩层 -->
  30. <div class="share__mask" :class="maskClass" v-if="showMask" @click="handleCancel"></div>
  31. <!-- 画布 -->
  32. <canvas ref="canvas"></canvas>
  33. </div>
  34. </template>
  35. <script>
  36. import { loadImage } from '~/utils'
  37. import QRCode from 'qrcode'
  38. import { isWeChat } from '~/utils/validator'
  39. export default {
  40. data() {
  41. return {
  42. shareFlag: false,
  43. showDialog: false,
  44. showImage: false,
  45. showMask: false,
  46. imageUrl: '/share-code-bg.png',
  47. shareGuide: false,
  48. shareImageGuide: false,
  49. }
  50. },
  51. computed: {
  52. maskClass() {
  53. return {
  54. 'share-guide': this.shareGuide,
  55. 'share-image-guide': this.shareImageGuide,
  56. }
  57. },
  58. },
  59. created() {
  60. this.shareFlag = isWeChat()
  61. },
  62. methods: {
  63. // 分享弹窗
  64. handleShare() {
  65. this.showDialog = true
  66. this.showMask = true
  67. },
  68. // 取消
  69. handleCancel() {
  70. this.showDialog = false
  71. this.showImage = false
  72. this.showMask = false
  73. this.shareGuide = false
  74. this.shareImageGuide = false
  75. },
  76. // 生成图片
  77. handleGenerateImage() {
  78. this.drawImage()
  79. this.showDialog = false
  80. },
  81. handleShareWechat() {
  82. this.shareGuide = true
  83. this.showDialog = false
  84. },
  85. async drawImage() {
  86. const canvas = document.createElement('canvas')
  87. canvas.width = 800
  88. canvas.height = 1200
  89. const ctx = canvas.getContext('2d')
  90. const image = await loadImage('/share-code-bg.png')
  91. ctx.drawImage(image, 0, 0, 800, 1200)
  92. const url = window.location.href
  93. const qrcodeUrl = await QRCode.toDataURL(url, { version: 5 })
  94. const qrcodeImage = await loadImage(qrcodeUrl)
  95. ctx.drawImage(qrcodeImage, 190, 600, 420, 420)
  96. this.imageUrl = canvas.toDataURL('image/jpg')
  97. this.showImage = true
  98. this.shareImageGuide = true
  99. },
  100. },
  101. }
  102. </script>
  103. <style lang="scss" scoped>
  104. @media screen and (min-width: 768px) {
  105. .simple-share {
  106. display: none;
  107. }
  108. }
  109. @media screen and (max-width: 768px) {
  110. .simple-share {
  111. position: relative;
  112. .share__mask {
  113. position: fixed;
  114. z-index: 19;
  115. width: 100vw;
  116. height: 100vh;
  117. left: 0;
  118. top: 0;
  119. background: rgba(0, 0, 0, 0.8);
  120. &.share-guide {
  121. background-image: url(/icon-share-guide1.png);
  122. background-repeat: no-repeat;
  123. background-position: top right;
  124. background-size: 70vw;
  125. z-index: 1000;
  126. }
  127. &.share-image-guide {
  128. background-image: url(/icon-share-guide2.png);
  129. background-repeat: no-repeat;
  130. background-position: center 90%;
  131. background-size: 50vw;
  132. }
  133. }
  134. .share__btns {
  135. position: fixed;
  136. right: 4vw;
  137. bottom: 32vw;
  138. width: 12vw;
  139. height: 12vw;
  140. background: url(/icon-share.png) no-repeat center;
  141. background-size: 12vw;
  142. border-radius: 50%;
  143. z-index: 19;
  144. }
  145. .share__image {
  146. width: 80vw;
  147. height: 120.2vw;
  148. position: fixed;
  149. left: 10vw;
  150. top: 50%;
  151. transform: translateY(-50%);
  152. z-index: 20;
  153. img {
  154. display: block;
  155. width: 100%;
  156. height: 100%;
  157. }
  158. }
  159. .share__dialog {
  160. position: fixed;
  161. width: 100%;
  162. left: 0;
  163. bottom: 0;
  164. background: #fff;
  165. z-index: 21;
  166. padding: 7.2vw 0;
  167. .share-concel {
  168. padding: 5.6vw 0;
  169. margin-top: 5.6vw;
  170. border-top: 0.1vw solid #e1e1e1;
  171. text-align: center;
  172. color: #333333;
  173. font-size: 3.6vw;
  174. }
  175. .share__dialog_wrapper {
  176. display: flex;
  177. align-items: center;
  178. justify-content: space-evenly;
  179. .share__dialog__item {
  180. display: flex;
  181. align-items: center;
  182. flex-direction: column;
  183. width: 24%;
  184. span {
  185. font-size: 3.6vw;
  186. color: #333333;
  187. margin-top: 2.4vw;
  188. }
  189. .icon {
  190. display: block;
  191. width: 8.8vw;
  192. height: 8.8vw;
  193. background-size: 8.8vw;
  194. background-repeat: no-repeat;
  195. background-position: center;
  196. &.icon-share-wechat {
  197. background-image: url('~assets/image/share-icon-wechat.png');
  198. }
  199. &.icon-share-code {
  200. background-image: url('~assets/image/share-icon-code.png');
  201. }
  202. &.icon-share-download {
  203. background-image: url('~assets/image/share-icon-download.png');
  204. }
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }
  211. </style>