1. /**
    2. * 业务场景:
    3. * 微信小程序利用canvas生成海报分享图片
    4. * 唯一一个不同点在于,要根据返回list算canvas的高度(也就是高度是不确定的,图片可以无限长)
    5. * */
    6. // 页面结构
    7. <block>
    8. <view class="dire-content" wx:if="{{postersShow}}" catchtouchmove="donMove">
    9. <scroll-view scroll-y class="dire-scroll">
    10. <canvas class="inviteCanvas" canvas-id="inviteCanvas" style="width:{{canvasWidth}}rpx;height:{{canvasHeight}}rpx;"> </canvas>
    11. <image class="canvasimg" src="{{canvasImg}}" style="width:630rpx;height:{{canvasHeight}}rpx"></image>
    12. </scroll-view>
    13. </view>
    14. <view class="create-poster-wbtn" bindtap="saveInviteCard" wx:if="{{postersShow}}">保存到手机</view>
    15. </block>
    16. const app = getApp();
    17. var that;
    18. var articleApps = require('../../banyan/logics/articleApps');
    19. var promise = require("../../vendor/lib/promise.min.js");
    20. Page({
    21. data: {
    22. resultList: [],
    23. img: "",
    24. showModal: false, // 遮罩层
    25. showWeekly: false, // 分享
    26. postersShow: false, // 生成海报
    27. canWidth: Number,
    28. canHeight: Number
    29. },
    30. /**
    31. * 生命周期函数--监听页面加载
    32. */
    33. onLoad: function (options) {
    34. that = this;
    35. let wkid = options.wkid;
    36. // let wkid = 8;
    37. // let title = "生命周期函数--监听页面加载生命周期函数--监听页面加载"
    38. that.setData({
    39. wkid: wkid,
    40. title: options.title
    41. // title: title
    42. })
    43. that.getWeeklyList(wkid);
    44. // 扫码场景处理
    45. var scene = options.scene ? decodeURIComponent(options.scene) : false;
    46. console.log(options);
    47. if (scene) {
    48. let param = scene.split(',');
    49. let wkidKey = param[0];
    50. // let wkidValue = param[1];
    51. if (param.length > 1 && wkidValue !== null) {
    52. that.getWeeklyList(wkidKey);
    53. } else {
    54. wx.switchTab({
    55. url: '/pages/index/index',
    56. });
    57. }
    58. }
    59. },
    60. /**
    61. * 生命周期函数--监听页面显示
    62. */
    63. onShow: function () {
    64. that.setData({
    65. resultList: [],
    66. img: "",
    67. showModal: false,
    68. showWeekly: false,
    69. postersShow: false,
    70. })
    71. if (!app.globalData.userInfo) {
    72. app.getCurrentUser(res => {
    73. that.getWeeklyList(that.data.wkid)
    74. }, 2);
    75. } else {
    76. that.getWeeklyList(that.data.wkid)
    77. }
    78. },
    79. // 加载页面数据
    80. getWeeklyList(id) {
    81. let reqData = {
    82. wkid: id
    83. }
    84. articleApps.weeklyList({
    85. data: reqData
    86. }, that, data => {
    87. that.setData({
    88. resultList: data.list,
    89. img: data.qrcode
    90. })
    91. that.dowloadImgFiles(that.data.img);
    92. });
    93. },
    94. // 显示分享弹框
    95. share() {
    96. that.setData({
    97. showModal: true,
    98. showWeekly: true
    99. })
    100. },
    101. // 显示canvas海报
    102. posters() {
    103. that.setData({
    104. showModal: true,
    105. showWeekly: false,
    106. postersShow: true,
    107. })
    108. that.getCanvasSize();
    109. that.drawInviteCard();
    110. },
    111. // 关闭分享弹框
    112. unShow() {
    113. that.setData({
    114. showModal: false,
    115. showWeekly: false,
    116. postersShow: false
    117. })
    118. },
    119. // 下载图片
    120. downloadImage: function (url) {
    121. var ulpromise = new promise(function (resolve, reject) {
    122. wx.downloadFile({
    123. url: url,
    124. success: function (res) {
    125. resolve(res);
    126. },
    127. fail: function (e) {
    128. reject(e);
    129. console.log('download image failed');
    130. }
    131. });
    132. });
    133. return ulpromise;
    134. },
    135. // 下载图片到缓存
    136. dowloadImgFiles(img) {
    137. try {
    138. var imgArr = [];
    139. that.downloadImage(img).then(function (res) {
    140. imgArr.push(res.tempFilePath);
    141. that.data.imgArr = imgArr;
    142. return that.downloadImage(img);
    143. }.bind(this)).then(function (res) {
    144. that.getCanvasSize();
    145. that.drawInviteCard();
    146. });
    147. } catch (err) {
    148. console.log(err)
    149. that.setData({
    150. loaded: true,
    151. });
    152. app.ulToast('加载失败', 0);
    153. }
    154. },
    155. // 获取画布宽高
    156. getCanvasSize() {
    157. wx.getSystemInfo({
    158. success(res) {
    159. that.setData({
    160. canWidth: res.windowWidth,
    161. canHeight: res.windowHeight
    162. })
    163. }
    164. });
    165. },
    166. // 绘制邀请卡画布
    167. drawInviteCard(callback) {
    168. let imgArr = that.data.imgArr;
    169. let con = that.data.resultList;
    170. // 文本list添加序号
    171. for (let j = 0; j < con.length; j++) {
    172. con[j].index = j;
    173. }
    174. let ctx = wx.createCanvasContext('inviteCanvas');
    175. // 设置单个主体内容高度
    176. let _height = 190;
    177. // 绘制白色背景
    178. ctx.setFillStyle('#fff');
    179. ctx.fillRect(0, 0, that.changeRpx(630), (that.changeRpx(_height) * con.length + that.changeRpx(600)));
    180. // ctx.clip(); //剪切矩形后 开始画画
    181. ctx.fill();
    182. that.setData({
    183. canvasWidth: that.changeRpx(630) * 2,
    184. // canvasHeight: Math.round((that.changeRpx(_height) * con.length + that.changeRpx(680)) * 2)
    185. canvasHeight: (95 * con.length + 300) * 2
    186. })
    187. // 文本标题
    188. // let title = "本周报告更新目录";
    189. let title = that.data.title;
    190. ctx.beginPath();
    191. ctx.setFillStyle('#000');
    192. ctx.font = "bold 16px Arial";
    193. // ctx.fillText(title, that.changeRpx(60), that.changeRpx(104));
    194. that.drawText(ctx, title, that.changeRpx(60), that.changeRpx(104), that.changeRpx(530), that.changeRpx(32), 1);
    195. // 以下为研究中心本期更新内容
    196. let title_two = "以下为研究中心本期更新内容";
    197. ctx.beginPath();
    198. ctx.setFontSize(that.changeRpx(28));
    199. ctx.setFillStyle('#747474');
    200. ctx.font = "nobold 14px Arial";
    201. ctx.fillText(title_two, that.changeRpx(60), that.changeRpx(150));
    202. // canvas主体内容
    203. for (let i = 0; i < con.length; i++) {
    204. // 标题
    205. let con_title = con[i].index + 1 + '.' + con[i].Title;
    206. ctx.beginPath();
    207. ctx.setFillStyle('#000');
    208. ctx.font = "bold 16px Arial";
    209. that.drawText(ctx, con_title, that.changeRpx(60), that.changeRpx(_height) * i + that.changeRpx(260), that.changeRpx(530), that.changeRpx(40), 2);
    210. // 内容
    211. let con_content = con[i].Summary;
    212. ctx.beginPath();
    213. ctx.setFillStyle('#747474');
    214. ctx.font = "nobold 14px Arial";
    215. // 判断10的用意是因为第二行是摘要,要缩略与标题保持一致
    216. if (i < 10) {
    217. that.drawText(ctx, con_content, that.changeRpx(90), that.changeRpx(_height) * i + that.changeRpx(340), that.changeRpx(470), that.changeRpx(32), 3);
    218. } else {
    219. that.drawText(ctx, con_content, that.changeRpx(110), that.changeRpx(_height) * i + that.changeRpx(340), that.changeRpx(470), that.changeRpx(32), 3);
    220. }
    221. // // 设置文本之间距离
    222. // let distance = that.changeRpx(160);
    223. // // 线框
    224. // ctx.moveTo(that.changeRpx(40), that.changeRpx(200) + i * distance);
    225. // ctx.lineTo(that.changeRpx(600), that.changeRpx(200) + i * distance);
    226. // ctx.lineTo(that.changeRpx(600), that.changeRpx(340) + i * distance);
    227. // ctx.lineTo(that.changeRpx(40), that.changeRpx(340) + i * distance);
    228. // ctx.lineTo(that.changeRpx(40), that.changeRpx(340) + i * distance);
    229. // ctx.closePath(); //闭合路径
    230. // ctx.lineWidth = 1;
    231. // ctx.strokeStyle = '#F6F6F6';
    232. // ctx.stroke();
    233. }
    234. // 小程序二维码
    235. ctx.beginPath();
    236. ctx.drawImage(imgArr[0], that.changeRpx(230), ((that.changeRpx(_height) * con.length) + that.changeRpx(260)), that.changeRpx(172), that.changeRpx(172));
    237. ctx.draw();
    238. setTimeout(() => {
    239. that.downloadCanvasImg(0, 0, that.changeRpx(630), (that.changeRpx(_height) * con.length + that.changeRpx(600)), (that.changeRpx(630) * 2), ((that.changeRpx(_height) * con.length + that.changeRpx(630)) * 2));
    240. }, 500);
    241. },
    242. /**
    243. *
    244. * @method downloadCanvasImg 把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
    245. * @param { Number } x 画布区域的左上角横坐标
    246. * @param { Number } y 画布区域的左上角纵坐标
    247. * @param { Number } width 画布区域的宽度
    248. * @param { Number } height 画布区域的高度
    249. * @param { Number } destWidth 图片的宽度
    250. * @param { Number } destHeight 图片的高度
    251. */
    252. downloadCanvasImg(x, y, width, height, destWidth, destHeight) {
    253. wx.canvasToTempFilePath({
    254. x: x,
    255. y: y,
    256. width: width,
    257. height: height,
    258. destWidth: destWidth,
    259. destHeight: destHeight,
    260. canvasId: 'inviteCanvas',
    261. fileType: 'jpg',
    262. quality: 2,
    263. success(res) {
    264. console.log(res)
    265. let filePath = res.tempFilePath;
    266. that.setData({
    267. canvasImg: filePath
    268. })
    269. },
    270. fail(err) {
    271. console.log(err);
    272. }
    273. });
    274. },
    275. /**
    276. *
    277. * @method centerText canvas文本居中
    278. * @param {*} ctx canvas对象
    279. * @param {*} text 文字
    280. * @param {*} fontSzie 字体
    281. * @param {*} color 颜色
    282. * @param {*} height 绘制高度
    283. */
    284. centerText(ctx, text, fontSzie, color, height) {
    285. ctx.font = fontSzie;
    286. ctx.fillStyle = color;
    287. ctx.textAlign = "center";
    288. ctx.textBaseline = "middle";
    289. ctx.fillText(text, ctx.width / 2, height);
    290. },
    291. /**
    292. *
    293. * @method drawText canvas文本超过隐藏
    294. * @param {*} ctx canvas对象
    295. * @param {*} text 文字
    296. * @param {*} x X轴
    297. * @param {*} y Y轴
    298. * @param {*} maxWidth 文本宽度
    299. * @param {*} lineHeight 行高
    300. * @param {*} maxLine 显示行数
    301. */
    302. drawText(ctx, text, x, y, maxWidth, lineHeight, maxLine) {
    303. let arrText = text.split('');
    304. let line = '';
    305. let num = 1;
    306. for (let n = 0; n < arrText.length; n++) {
    307. let testLine = line + arrText[n];
    308. let metrics = ctx.measureText(testLine);
    309. let testWidth = metrics.width;
    310. if (testWidth > maxWidth && n > 0) {
    311. if (maxLine != undefined && num >= maxLine) {
    312. ctx.fillText(line.substr(0, line.length - 1) + '...', x, y);
    313. return num;
    314. }
    315. num++;
    316. ctx.fillText(line, x, y);
    317. line = arrText[n];
    318. y += lineHeight;
    319. } else {
    320. line = testLine;
    321. }
    322. }
    323. ctx.fillText(line, x, y);
    324. return num;
    325. },
    326. // canvas圆角
    327. // drawRoundRect()
    328. drawRoundRect(ctx, x, y, width, height, radius) {
    329. ctx.beginPath();
    330. ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
    331. ctx.lineTo(width - radius + x, y);
    332. ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);
    333. ctx.lineTo(width + x, height + y - radius);
    334. ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2);
    335. ctx.lineTo(radius + x, height + y);
    336. ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI);
    337. ctx.closePath();
    338. },
    339. // 转换rpx单位为px
    340. changeRpx(rpx) {
    341. return rpx * that.data.canWidth / 750;
    342. },
    343. // 保存图片
    344. saveInviteCard(e) {
    345. app.saveCanvasToAlbum(e, that, res => {
    346. app.ulToast('保存成功', 1);
    347. that.setData({
    348. showModal: false,
    349. showWeekly: false,
    350. postersShow: false
    351. });
    352. });
    353. },
    354. })
    355. //