draw-demo.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <!--
  2. * @Description: 生成海报组件
  3. * @Version: 1.0.0
  4. * @Autor: hch
  5. * @Date: 2020-08-07 14:48:41
  6. * @LastEditors: Please set LastEditors
  7. * @LastEditTime: 2021-07-30 09:25:07
  8. * 保存海报按钮和关闭按钮 在html代码中写出来 绑定点击方法然后透明 再用canvas 覆盖
  9. -->
  10. <template>
  11. <view class="content">
  12. <view class="btn" @tap="handleDraw('square1')">正方形</view>
  13. <view class="btn" @tap="handleDraw('square2')">圆角方形</view>
  14. <view class="btn" @tap="handleDraw('square3')">圆形</view>
  15. <view class="btn" @tap="handleDraw('pic1')">图片</view>
  16. <view class="btn" @tap="handleDraw('text1')">左对齐文本</view>
  17. <view class="btn" @tap="handleDraw('text2')">居中对齐文本</view>
  18. <view class="btn" @tap="handleDraw('text3')">右对齐文本</view>
  19. <view
  20. class="canvas-content"
  21. v-show="canvasShow"
  22. :style="'width:' + system.w + 'px; height:' + system.h + 'px;'"
  23. >
  24. <!-- 遮罩层 -->
  25. <view class="canvas-mask"></view>
  26. <!-- :width="system.w" :height="system.h" 支付宝必须要这样设置宽高才有效果 -->
  27. <canvas
  28. class="canvas"
  29. :canvas-id="canvasId"
  30. :id="canvasId"
  31. :style="'width:' + system.w + 'px; height:' + system.h + 'px;'"
  32. :width="system.w"
  33. :height="system.h"
  34. ></canvas>
  35. <view class="button-wrapper">
  36. <!-- 保存海报按钮 -->
  37. <!-- #ifndef MP-QQ -->
  38. <!-- cover-view 标签qq小程序有问题 -->
  39. <cover-view class="save-btn cancel-btn" @tap="handleCancel">取消</cover-view>
  40. <!-- #endif -->
  41. <!-- #ifdef MP-QQ -->
  42. <view class="save-btn cancel-btn" @tap="handleCancel">取消</view>
  43. <!-- #endif -->
  44. </view>
  45. </view>
  46. </view>
  47. </template>
  48. <script>
  49. import { drawSquarePic, drawTextReturnH, getSystem } from './utils'
  50. export default {
  51. data() {
  52. return {
  53. canvasId: 'canvas',
  54. system: {},
  55. canvasShow: false,
  56. square1: {
  57. //正方形
  58. x: 40,
  59. y: 40,
  60. r: 0, //圆角半径
  61. w: 80, //宽度
  62. h: 80 //高度
  63. },
  64. square2: {
  65. //圆角方形
  66. x: 40,
  67. y: 40,
  68. r: 10, //圆角半径
  69. w: 80, //宽度
  70. h: 80 //高度
  71. },
  72. square3: {
  73. //圆形
  74. x: 40,
  75. y: 40,
  76. r: 40, //圆角半径
  77. w: 80, //宽度
  78. h: 80 //高度
  79. },
  80. pic1: {
  81. x: 40,
  82. y: 40,
  83. url: 'https://huangchunhongzz.gitee.io/imgs/poster/product.png',
  84. r: 0, //圆角半径
  85. w: 250, //宽度
  86. h: 200 //高度
  87. },
  88. text1: {
  89. x: 0,
  90. y: 40,
  91. text: '今日上新水果,牛奶草莓',
  92. fontSize: 16, //字体大小
  93. color: '#000', //颜色
  94. lineHeight: 25, //行高
  95. mt: 0 //margin-top
  96. },
  97. text2: {
  98. x: 0,
  99. y: 40,
  100. text: '今日上新水果,牛奶草莓',
  101. fontSize: 16, //字体大小
  102. color: 'blue', //颜色
  103. lineHeight: 25, //行高
  104. mt: 0, //margin-top
  105. align: 'center' //对齐方式
  106. },
  107. text3: {
  108. x: 0,
  109. y: 40,
  110. text: '今日上新水果,牛奶草莓',
  111. fontSize: 16, //字体大小
  112. color: 'red', //颜色
  113. lineHeight: 25, //行高
  114. mt: 0, //margin-top
  115. align: 'right' //对齐方式
  116. }
  117. }
  118. },
  119. created() {
  120. // 获取设备信息
  121. this.system = getSystem()
  122. },
  123. methods: {
  124. /**
  125. * @description: 展示海报
  126. * @param {type}
  127. * @return {type}
  128. * @author: hch
  129. */
  130. handleDraw(type) {
  131. console.log('handleDraw -> type', type)
  132. this.canvasShow = true
  133. this.draw(type)
  134. },
  135. /**
  136. * @description: 绘制
  137. * @author: hch
  138. */
  139. draw(type) {
  140. uni.showLoading({
  141. title: '绘制中...'
  142. })
  143. if (this.ctx) {
  144. this.ctx.clearRect(0, 0, this.system.w, this.system.h) //清空之前的海报
  145. this.ctx.restore() //恢复之前被切割的canvas,否则切割之外的就没办法用
  146. } else {
  147. this.ctx = uni.createCanvasContext(this.canvasId, this)
  148. }
  149. let drawData = this[type]
  150. if (type === 'square1' || type === 'square2' || type === 'square3' || type === 'pic1') {
  151. // 绘制图像/图片
  152. drawSquarePic(
  153. this.ctx,
  154. drawData.x,
  155. drawData.y,
  156. drawData.w,
  157. drawData.h,
  158. drawData.r,
  159. drawData.url
  160. )
  161. } else {
  162. // 绘制文本
  163. let textY = drawTextReturnH(
  164. this.ctx,
  165. drawData.text,
  166. drawData.x,
  167. drawData.y,
  168. this.system.w,
  169. drawData.fontSize,
  170. drawData.color,
  171. drawData.lineHeight,
  172. drawData.align
  173. )
  174. }
  175. uni.hideLoading()
  176. },
  177. /**
  178. * @description: 取消海报
  179. * @param {type}
  180. * @return {type}
  181. * @author: hch
  182. */
  183. handleCancel() {
  184. this.canvasShow = false
  185. }
  186. }
  187. }
  188. </script>
  189. <style lang="scss">
  190. .content {
  191. margin-bottom: 80rpx;
  192. overflow: hidden;
  193. border-bottom: 1rpx solid $uni-border-color;
  194. .btn {
  195. float: left;
  196. width: 30%;
  197. margin: 10rpx;
  198. font-size: 30rpx;
  199. line-height: 72rpx;
  200. color: #fff;
  201. text-align: center;
  202. background: $uni-btn-color;
  203. border-radius: 45rpx;
  204. border-radius: 36rpx;
  205. }
  206. }
  207. .canvas-content {
  208. position: absolute;
  209. top: 0;
  210. z-index: 9;
  211. .canvas-mask {
  212. position: fixed;
  213. top: 0;
  214. right: 0;
  215. bottom: 0;
  216. left: 0;
  217. z-index: 9;
  218. width: 100%;
  219. height: 100%;
  220. background: $uni-btn-color;
  221. }
  222. .canvas {
  223. z-index: 10;
  224. }
  225. .button-wrapper {
  226. position: fixed;
  227. bottom: 20rpx;
  228. z-index: 16;
  229. display: flex;
  230. width: 100%;
  231. height: 72rpx;
  232. justify-content: space-around;
  233. }
  234. .save-btn {
  235. z-index: 16;
  236. width: 40%;
  237. height: 100%;
  238. font-size: 30rpx;
  239. line-height: 72rpx;
  240. color: #fff;
  241. text-align: center;
  242. background: $uni-btn-color;
  243. border-radius: 45rpx;
  244. border-radius: 36rpx;
  245. }
  246. .cancel-btn {
  247. color: $uni-btn-color;
  248. background: #fff;
  249. }
  250. .canvas-close-btn {
  251. position: fixed;
  252. top: 30rpx;
  253. right: 0;
  254. z-index: 12;
  255. width: 60rpx;
  256. height: 60rpx;
  257. padding: 20rpx;
  258. }
  259. }
  260. </style>