wm-poster.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <template>
  2. <view>
  3. <canvas :canvas-id="CanvasID" :style="{ width: canvasW + 'px', height: canvasH + 'px' }"></canvas>
  4. </view>
  5. </template>
  6. <script>
  7. var _this;
  8. export default {
  9. name: 'wm-poster',
  10. props: {
  11. CanvasID:{ //CanvasID 等同于 canvas-id
  12. Type:String,
  13. default:'PosterCanvas'
  14. },
  15. imgSrc:{ //展示图
  16. Type:String,
  17. default:''
  18. },
  19. QrSrc:{ //二维码
  20. Type:String,
  21. default:''
  22. },
  23. Title:{ //文本内容
  24. Type:String,
  25. default:''
  26. },
  27. TitleColor:{ //标题颜色
  28. Type:String,
  29. default:'#333333'
  30. },
  31. LineType:{ //标题显示行数 (注超出2行显示会导致画布布局絮乱)
  32. Type:[String,Boolean],
  33. default:true
  34. },
  35. PriceTxt:{ //价格值
  36. Type:String,
  37. default:''
  38. },
  39. PriceColor:{ //价格颜色
  40. Type:String,
  41. default:'#e31d1a'
  42. },
  43. OriginalTxt:{ //原价值
  44. Type:String,
  45. default:''
  46. },
  47. OriginalColor:{ //默认颜色(如原价与扫描二维码颜色)
  48. Type:String,
  49. default:'#b8b8b8'
  50. },
  51. Width:{ //画布宽度 (高度根据图片比例计算 单位upx)
  52. Type:String,
  53. default:1500
  54. },
  55. CanvasBg:{ //canvas画布背景色
  56. Type:String,
  57. default:'#ffffff'
  58. },
  59. Referrer:{ //推荐人信息
  60. Type:String,
  61. default:''
  62. },
  63. ViewDetails:{ //描述提示文字
  64. Type:String,
  65. default:'长按或扫描识别二维码'
  66. }
  67. },
  68. data() {
  69. return {
  70. canvasW:0,
  71. canvasH: 0,
  72. canvasImgSrc:'',
  73. ctx:null
  74. };
  75. },
  76. methods: {
  77. async OnCanvas() {
  78. _this.ctx = uni.createCanvasContext(_this.CanvasID,this);
  79. const C_W = uni.upx2px(_this.Width), //canvas宽度
  80. C_P = uni.upx2px(60), //canvas Paddng 间距
  81. C_Q = uni.upx2px(300); //二维码或太阳码宽高
  82. let _strlineW = 0; //文本宽度
  83. let _imgInfo = await _this.getImageInfo({ imgSrc: _this.imgSrc }); //广告图
  84. let _QrCode = await _this.getImageInfo({ imgSrc: _this.QrSrc }); //二维码或太阳码
  85. let r = [_imgInfo.width, _imgInfo.height];
  86. let q = [_QrCode.width, _QrCode.height];
  87. let imgW = C_W - C_P * 2;
  88. if (r[0] != imgW) {
  89. r[1] = Math.floor((imgW / r[0]) * r[1]);
  90. r[0] = imgW;
  91. }
  92. if (q[0] != C_Q) {
  93. q[1] = Math.floor((C_Q / q[0]) * q[1]);
  94. q[0] = C_Q;
  95. }
  96. _this.canvasW = C_W;
  97. _this.canvasH = r[1] + q[1] + 256;
  98. _this.ctx.setFillStyle(_this.CanvasBg); //canvas背景颜色
  99. _this.ctx.fillRect(0, 0, C_W, _this.canvasH); //canvas画布大小
  100. //添加图片展示
  101. _this.ctx.drawImage(_imgInfo.path, C_P, C_P, r[0], r[1]);
  102. //添加图片展示 end
  103. //设置文本
  104. _this.ctx.setFontSize(uni.upx2px(56)); //设置标题字体大小
  105. _this.ctx.setFillStyle(_this.TitleColor); //设置标题文本颜色
  106. let _strLastIndex = 0; //每次开始截取的字符串的索引
  107. let _strHeight = r[1] + C_P * 2 + 20; //绘制字体距离canvas顶部的初始高度
  108. let _num=1;
  109. for (let i = 0; i < _this.Title.length; i++) {
  110. _strlineW += _this.ctx.measureText(_this.Title[i]).width;
  111. if (_strlineW > r[0]) {
  112. if(_num == 2&&_this.LineType){
  113. //文字换行数量大于二进行省略号处理
  114. _this.ctx.fillText(_this.Title.substring(_strLastIndex, i-8)+'...', C_P, _strHeight);
  115. _strlineW = 0;
  116. _strLastIndex = i;
  117. _num++;
  118. break;
  119. }else{
  120. _this.ctx.fillText(_this.Title.substring(_strLastIndex, i), C_P, _strHeight);
  121. _strlineW = 0;
  122. _strHeight += 40;
  123. _strLastIndex = i;
  124. _num++;
  125. }
  126. }else if (i == _this.Title.length - 1) {
  127. _this.ctx.fillText(_this.Title.substring(_strLastIndex, i + 1), C_P, _strHeight);
  128. _strlineW = 0;
  129. }
  130. }
  131. //设置文本 end
  132. //设置价格
  133. _strlineW = C_P;
  134. _strHeight += uni.upx2px(120);
  135. if(_num==1){
  136. _strHeight += 40; //单行标题时占位符
  137. }
  138. if(_this.PriceTxt !=''){ //判断是否有销售价格
  139. _this.ctx.setFillStyle(_this.PriceColor);
  140. _this.ctx.setFontSize(uni.upx2px(76));
  141. _this.ctx.fillText(_this.PriceTxt, _strlineW, _strHeight); //商品价格
  142. _strlineW += _this.ctx.measureText(_this.PriceTxt).width + uni.upx2px(20);
  143. }
  144. if(_this.PriceTxt !='' && _this.OriginalTxt !=''){ //判断是否有销售价格且原价
  145. _this.ctx.setFillStyle(_this.OriginalColor);
  146. _this.ctx.setFontSize(uni.upx2px(48));
  147. _this.ctx.fillText(_this.OriginalTxt, _strlineW, _strHeight); //商品原价
  148. }
  149. _this.ctx.strokeStyle = _this.OriginalColor;
  150. _this.ctx.moveTo(_strlineW, _strHeight - uni.upx2px(20)); //起点
  151. _this.ctx.lineTo(_strlineW + _this.ctx.measureText(_this.OriginalTxt).width, _strHeight - uni.upx2px(20)); //终点
  152. _this.ctx.stroke();
  153. //设置价格 end
  154. //添加二维码
  155. _strHeight += uni.upx2px(40);
  156. _this.ctx.drawImage(_QrCode.path, r[0] - q[0] + C_P, _strHeight, q[0], q[1]);
  157. //添加二维码 end
  158. //添加推荐人与描述
  159. _this.ctx.setFillStyle(_this.TitleColor);
  160. _this.ctx.setFontSize(uni.upx2px(60));
  161. _this.ctx.fillText(_this.Referrer, C_P, _strHeight + q[1] / 2);
  162. _this.ctx.setFillStyle(_this.OriginalColor);
  163. _this.ctx.setFontSize(uni.upx2px(48));
  164. _this.ctx.fillText(_this.ViewDetails, C_P, _strHeight + q[1] / 2 + 40);
  165. //添加推荐人与描述 end
  166. //延迟后渲染至canvas上
  167. setTimeout(function() {
  168. _this.ctx.draw(true,(ret)=>{
  169. _this.getNewImage();
  170. });
  171. }, 600);
  172. },
  173. async getImageInfo({ imgSrc }) {
  174. return new Promise((resolve, errs) => {
  175. uni.getImageInfo({
  176. src: imgSrc,
  177. success: function(image) {
  178. resolve(image);
  179. },
  180. fail(err) {
  181. errs(err);
  182. }
  183. });
  184. });
  185. },
  186. getNewImage(){
  187. uni.canvasToTempFilePath({
  188. canvasId: _this.CanvasID,
  189. quality: 1,
  190. complete: (res) => {
  191. console.log(res.tempFilePath);
  192. _this.$emit('success',res);
  193. }
  194. },this);
  195. }
  196. },
  197. mounted() {
  198. _this = this;
  199. }
  200. };
  201. </script>
  202. <style></style>