index.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. // nova-werun/pages/home/share/index.js
  2. const qiniuUploader = require("../../../../utils/qiniuUploader");
  3. const Parse = getApp().Parse;
  4. const company = getApp().globalData.company;
  5. const user = Parse.User.current()
  6. let getSportData = require('../../../service/getSportData')
  7. const dateF = require("../../../../utils/date")
  8. Page({
  9. /**
  10. * 页面的初始数据
  11. */
  12. data: {
  13. sharList: [],
  14. images: [
  15. // 'https://file-cloud.fmode.cn/qpFbRRSZrO/20250113/1p97lf053250915.png',
  16. 'https://file-cloud.fmode.cn/qpFbRRSZrO/20250113/bt19fm050427168.png'
  17. ],
  18. randomImage: '',
  19. saveimage: '',
  20. uptokenURL: '',
  21. domain: '',
  22. uploadURL: '',
  23. userList: [],
  24. },
  25. /**
  26. * 生命周期函数--监听页面加载
  27. */
  28. onLoad: function (options) {
  29. this.refersh()
  30. },
  31. async refersh() {
  32. let {
  33. screenWidth
  34. } = wx.getWindowInfo()
  35. let rate_px_rpx = (screenWidth / 750)
  36. await this.showRandomImage()
  37. await this.setData({
  38. user_json: user.toJSON(),
  39. rate_px_rpx
  40. })
  41. await this.getData()
  42. this.setCanvas()
  43. },
  44. /**随机展示图片 */
  45. showRandomImage() {
  46. const randomIndex = Math.floor(Math.random() * this.data.images.length);
  47. this.setData({
  48. randomImage: this.data.images[randomIndex]
  49. });
  50. },
  51. /**获取数据 */
  52. async getData() {
  53. let rank = '200名之后'
  54. let step = await getSportData.getwalk('steps', '', '') || 0
  55. let distance = await getSportData.getwalk('distance', '', '') || 0
  56. if (distance) {
  57. let rd = await getSportData.getUserRank(user?.id, '', 'today')
  58. rank = rd[0]?.rank || 0
  59. }
  60. console.log(rank, step, distance)
  61. this.setData({
  62. rank,
  63. step,
  64. distance
  65. })
  66. },
  67. /**绘制canvas */
  68. setCanvas() {
  69. let {
  70. rank,
  71. step,
  72. distance,
  73. user_json,
  74. randomImage
  75. } = this.data
  76. let that = this
  77. wx.createSelectorQuery()
  78. .select('#myCanvas') // 在 WXML 中填入的 id
  79. .fields({
  80. node: true,
  81. size: true
  82. })
  83. .exec((res) => {
  84. const canvas = res[0].node
  85. const ctx = canvas.getContext('2d')
  86. const width = res[0].width
  87. const height = res[0].height
  88. // 初始化画布大小
  89. const dpr = wx.getWindowInfo().pixelRatio
  90. canvas.width = width * dpr
  91. canvas.height = height * dpr
  92. ctx.scale(dpr, dpr)
  93. ctx.clearRect(0, 0, width, height)
  94. //========背景=====
  95. let bg = canvas.createImage()
  96. bg.onload = () => {
  97. ctx.drawImage(bg, 0, 0, width, height)
  98. const gradient = ctx.createLinearGradient(0, 0, 0, height);
  99. gradient.addColorStop(0, 'rgba(255, 255, 255, 0)');
  100. gradient.addColorStop(1, 'rgb(255, 255, 255)');
  101. ctx.fillStyle = gradient;
  102. ctx.fillRect(0, 0, width, height);
  103. //=========头像=========
  104. let avatar = canvas.createImage();
  105. avatar.onload = () => {
  106. const radius = 20; // 圆的半径
  107. const x = 40;
  108. const y = height - 185;
  109. ctx.save();
  110. ctx.beginPath();
  111. ctx.arc(x, y, radius, 0, Math.PI * 2, false);
  112. ctx.closePath();
  113. ctx.clip();
  114. ctx.drawImage(avatar, x - radius, y - radius, radius * 2, radius * 2);
  115. ctx.restore();
  116. };
  117. avatar.src = user_json.avatar;
  118. ctx.fillStyle = '#4F9AF7';
  119. ctx.font = '15px bold Arial';
  120. ctx.fillText(user_json.nickname, 70, height - 185);
  121. ctx.font = '10px Arial';
  122. ctx.fillText(dateF.formatTime("YYYY.mm.dd HH:MM", user_json.createdAt), 70, height - 170);
  123. ctx.font = 'bold 20px Arial';
  124. ctx.fillText('梦想家', 20, height - 140);
  125. ctx.font = '10px Arial';
  126. ctx.fillText('用汗水实现想象,用脚步丈量梦想', 20, height - 125);
  127. ctx.font = '15px Arial';
  128. ctx.fillText('今日排名', 20, height - 100);
  129. ctx.fillText('今日步数', width / 2 - 20, height - 100);
  130. ctx.fillText('公里数', width - 60, height - 100);
  131. ctx.font = 'bold 15px Arial';
  132. ctx.fillText(rank, 20, height - 80);
  133. ctx.fillText(step, width / 2 - 20, height - 80);
  134. ctx.fillText(distance, width - 60, height - 80);
  135. ctx.font = '10px Arial';
  136. ctx.fillText('长按二维码加入跑团', width - 170, height - 45);
  137. ctx.fillText('和我一起运动', width - 140, height - 30);
  138. let qr = canvas.createImage();
  139. qr.onload = () => {
  140. ctx.drawImage(qr, width - 70, height - 70, 70, 70)
  141. };
  142. qr.src = 'https://file-cloud.fmode.cn/qpFbRRSZrO/20250220/ig1167052435205.jpg?imageView2/1/w/200/h/200'
  143. }
  144. bg.src = 'https://file-cloud.fmode.cn/qpFbRRSZrO/20250113/bt19fm050427168.png'
  145. that.setData({
  146. canvas
  147. })
  148. })
  149. },
  150. /**保存图片 */
  151. saveCanvas() {
  152. let {
  153. canvas
  154. } = this.data
  155. let that = this
  156. wx.canvasToTempFilePath({
  157. canvas: canvas,
  158. success(res) {
  159. that.setData({saveimage: res.tempFilePath})
  160. wx.saveImageToPhotosAlbum({
  161. filePath: res.tempFilePath,
  162. success: (res) => {
  163. console.log('success',res)
  164. },
  165. fail: (err) => {
  166. // console.log('err',err)
  167. }
  168. })
  169. },
  170. fail: (err) => {
  171. console.log(err)
  172. }
  173. })
  174. },
  175. /**
  176. * 生命周期函数--监听页面初次渲染完成
  177. */
  178. onReady: function () {
  179. },
  180. /**
  181. * 生命周期函数--监听页面显示
  182. */
  183. onShow: function () {
  184. },
  185. /**
  186. * 生命周期函数--监听页面隐藏
  187. */
  188. onHide: function () {
  189. },
  190. /**
  191. * 生命周期函数--监听页面卸载
  192. */
  193. onUnload: function () {
  194. },
  195. /**
  196. * 页面相关事件处理函数--监听用户下拉动作
  197. */
  198. onPullDownRefresh: function () {
  199. },
  200. /**
  201. * 页面上拉触底事件的处理函数
  202. */
  203. onReachBottom: function () {
  204. },
  205. /**
  206. * 用户点击右上角分享
  207. */
  208. onShareAppMessage: function () {
  209. },
  210. //绘制canvas
  211. rpxToPx(rpx) {
  212. const systemInfo = wx.getSystemInfoSync();
  213. return rpx * (systemInfo.windowWidth / 750);
  214. },
  215. getImageInfo(url) {
  216. console.log(url);
  217. return new Promise((result) => {
  218. wx.getImageInfo({
  219. src: url, //服务器返回的图片地址
  220. success: function (res) {
  221. // res.path是网络图片的本地地址
  222. let Path = res.path;
  223. result(Path)
  224. },
  225. fail(err) {
  226. console.log(err);
  227. result()
  228. }
  229. });
  230. })
  231. },
  232. //获取用户信息
  233. async getuser() {
  234. const currentUser = Parse.User.current();
  235. let user = new Parse.Query('_User');
  236. user.equalTo('company', company);
  237. user.notEqualTo('isDeleted', true);
  238. user.equalTo('objectId', currentUser.id);
  239. let P = await user.find();
  240. let userList = P.map(item => item.toJSON());
  241. this.setData({
  242. userList,
  243. })
  244. console.log('userList', this.data.userList);
  245. },
  246. //rpx
  247. async saveImage() {
  248. // console.log('运行了');
  249. const canvas = wx.createCanvasContext('myCanvas');
  250. const width = this.rpxToPx(670);
  251. const height = this.rpxToPx(1100);
  252. // console.log(width, height);
  253. canvas.width = this.rpxToPx(670);
  254. canvas.height = this.rpxToPx(1100);
  255. const backgroundImage2 = await this.getImageInfo(this.data.randomImage);
  256. // 绘制背景图片
  257. canvas.drawImage(backgroundImage2, 0, 0, width, height);
  258. // 加载背景图片
  259. const backgroundImage1 = await this.getImageInfo('https://file-cloud.fmode.cn/qpFbRRSZrO/20250113/1r3o3q045323287.png');
  260. // 绘制背景图片
  261. canvas.drawImage(backgroundImage1, 0, 0, width, height);
  262. // 绘制背景
  263. // canvas.setFillStyle('#CAE1FD'); // 背景色
  264. // canvas.fillRect(0, 0, width, height);
  265. canvas.setFillStyle('#0178EE');
  266. // let mainimage = await this.getImageInfo(this.data.randomImage)
  267. let avatar = Parse.User.current()?.get('avatar')
  268. console.log('avatar', avatar);
  269. let userAvatar = await this.getImageInfo(avatar)
  270. console.log('userAvatar', userAvatar);
  271. //主图片
  272. // canvas.drawImage(mainimage, 0, 0, width, this.rpxToPx(500)); // 调整图片高度
  273. //头像
  274. if (userAvatar) {
  275. // 绘制带圆角的头像
  276. const avatarX = this.rpxToPx(40);
  277. const avatarY = this.rpxToPx(540);
  278. const avatarSize = this.rpxToPx(83);
  279. const radius = avatarSize / 2; // 半径为头像大小的一半
  280. // 绘制圆角矩形
  281. canvas.save(); // 保存当前状态
  282. canvas.beginPath(); // 开始路径
  283. canvas.moveTo(avatarX + radius, avatarY); // 左上角
  284. canvas.lineTo(avatarX + avatarSize - radius, avatarY); // 上边
  285. canvas.arc(avatarX + avatarSize - radius, avatarY + radius, radius, 1.5 * Math.PI, 0, false); // 右上角
  286. canvas.lineTo(avatarX + avatarSize, avatarY + avatarSize - radius); // 右边
  287. canvas.arc(avatarX + avatarSize - radius, avatarY + avatarSize - radius, radius, 0, 0.5 * Math.PI, false); // 右下角
  288. canvas.lineTo(avatarX + radius, avatarY + avatarSize); // 下边
  289. canvas.arc(avatarX + radius, avatarY + avatarSize - radius, radius, 0.5 * Math.PI, Math.PI, false); // 左下角
  290. canvas.lineTo(avatarX, avatarY + radius); // 左边
  291. canvas.arc(avatarX + radius, avatarY + radius, radius, Math.PI, 1.5 * Math.PI, false); // 左上角
  292. canvas.closePath(); // 关闭路径
  293. canvas.clip(); // 剪切
  294. // 绘制头像
  295. canvas.drawImage(userAvatar, avatarX, avatarY, avatarSize, avatarSize); // 头像位置和大小
  296. canvas.restore(); // 恢复状态
  297. }
  298. // 绘制昵称和时间
  299. const nickname = this.data.userList[0].nickname;
  300. const currentTime = this.data.sharList.currentTime;
  301. const rank = this.data.sharList.rank;
  302. const steps = this.data.sharList.totalSteps || 0;
  303. const distance = this.data.sharList.totaldistance || 0;
  304. canvas.setFontSize(this.rpxToPx(30));
  305. canvas.fillText(nickname, this.rpxToPx(140), this.rpxToPx(580)); // 昵称位置
  306. // console.log('昵称加载成功');
  307. canvas.setFontSize(this.rpxToPx(28));
  308. canvas.fillText(currentTime, this.rpxToPx(140), this.rpxToPx(610)); // 时间位置
  309. // console.log('时间加载成功');
  310. // 绘制其他文本
  311. canvas.setFontSize(this.rpxToPx(55));
  312. canvas.fillText('梦想家', this.rpxToPx(40), this.rpxToPx(720));
  313. // console.log('梦想家加载成功');
  314. canvas.setFontSize(this.rpxToPx(30));
  315. canvas.fillText('用汗水实现想象,用脚步丈量梦想', this.rpxToPx(40), this.rpxToPx(780));
  316. // console.log('汗水加载成功');
  317. // 绘制排名、步数和公里数
  318. canvas.setFontSize(this.rpxToPx(22));
  319. // canvas.fillText('今日排名: ' + rank, 20, 400);
  320. canvas.fillText('今日排名', this.rpxToPx(40), this.rpxToPx(840));
  321. // console.log('排名加载成功');
  322. // canvas.fillText('今日步数: ' + steps, 20, 420);
  323. canvas.fillText('今日步数', this.rpxToPx(180), this.rpxToPx(840));
  324. // console.log('步数加载成功');
  325. // canvas.fillText('公里数: ' + distance + 'km', 20, 430);
  326. canvas.fillText('公里数', this.rpxToPx(320), this.rpxToPx(840));
  327. // console.log('公里数加载成功');
  328. canvas.setFontSize(this.rpxToPx(34));
  329. canvas.fillText(rank, this.rpxToPx(70), this.rpxToPx(900));
  330. canvas.fillText(steps, this.rpxToPx(180), this.rpxToPx(900));
  331. canvas.fillText(distance + 'km', this.rpxToPx(320), this.rpxToPx(900));
  332. // 加载二维码图片
  333. const qrCodeImage = await this.getImageInfo('https://file-cloud.fmode.cn/qpFbRRSZrO/20250113/t2vst6051431547.png');
  334. // 绘制二维码
  335. canvas.drawImage(qrCodeImage, width - this.rpxToPx(140), height - this.rpxToPx(160), this.rpxToPx(120), this.rpxToPx(120));
  336. canvas.setFillStyle('#0178EE');
  337. canvas.setFontSize(this.rpxToPx(28));
  338. canvas.fillText('长按二维码加入儒乐湖健身跑', width - this.rpxToPx(510), height - this.rpxToPx(120));
  339. canvas.fillText('和我一起运动', width - this.rpxToPx(405), height - this.rpxToPx(80));
  340. // 完成绘制
  341. canvas.draw(false, () => {
  342. console.log('123');
  343. wx.canvasToTempFilePath({
  344. canvasId: 'myCanvas',
  345. success: (res) => {
  346. console.log('绘制完成', res);
  347. this.setData({
  348. saveimage: res.tempFilePath
  349. });
  350. this.getUptoken()
  351. console.log(this.data.saveimage);
  352. },
  353. fail: (err) => {
  354. console.error('canvasToTempFilePath 失败', err);
  355. }
  356. });
  357. });
  358. },
  359. uploadImageToServer() {
  360. const that = this;
  361. const tempFilePath = this.data.saveimage; // 获取本地临时文件路径
  362. qiniuUploader.upload(
  363. tempFilePath, // 本地文件路径
  364. (res) => {
  365. const imageURL = res.imageURL; // 上传成功后的网络地址
  366. console.log('上传成功,网络地址:', imageURL);
  367. that.setData({
  368. saveimage: imageURL // 更新 saveimage 为网络地址
  369. });
  370. },
  371. (error) => {
  372. console.error('上传失败:', error);
  373. }, {
  374. region: "SCN", // 七牛云区域
  375. uploadURL: that.data.uploadURL, // 上传地址
  376. domain: that.data.domain, // 域名
  377. uptoken: that.data.uptokenURL, // 上传凭证
  378. }
  379. );
  380. console.log('saveimage', this.data.saveimage);
  381. },
  382. async getUptoken() {
  383. let res = await Parse.Cloud.run('qiniu_uptoken', {
  384. company: company
  385. })
  386. this.setData({
  387. uptokenURL: res.uptoken,
  388. domain: res.domain,
  389. uploadURL: res.zoneUrl
  390. })
  391. this.uploadImageToServer()
  392. console.log(this.data.uptokenURL, this.data.domain, this.data.uploadURL);
  393. },
  394. //点击保存图片
  395. async savepic() {
  396. await this.saveImage()
  397. const imagePath = this.data.saveimage; // 获取保存的图片路径
  398. if (imagePath) {
  399. // 调用保存图片到相册的方法
  400. wx.saveImageToPhotosAlbum({
  401. filePath: imagePath,
  402. success: () => {
  403. wx.showToast({
  404. title: '图片已保存到相册',
  405. icon: 'success'
  406. });
  407. },
  408. fail: (err) => {
  409. console.error('保存失败', err);
  410. wx.showToast({
  411. title: '保存失败',
  412. icon: 'none'
  413. });
  414. }
  415. });
  416. } else {
  417. wx.showToast({
  418. title: '没有可保存的图片',
  419. icon: 'none'
  420. });
  421. }
  422. },
  423. //保存图片到相册
  424. savepic2: function () {
  425. let that = this;
  426. wx.canvasToTempFilePath({
  427. x: 0,
  428. y: 0,
  429. width: 670,
  430. height: 1100,
  431. destWidth: 670,
  432. destHeight: 1100,
  433. canvasId: 'myCanvas',
  434. success: function (result) {
  435. wx.getSetting({
  436. success(res) {
  437. if (!res.authSetting['scope.writePhotosAlbum']) {
  438. wx.authorize({
  439. scope: 'scope.writePhotosAlbum',
  440. success() {
  441. //这里是用户同意授权后的回调
  442. // that.saveImgToLocal();
  443. wx.saveImageToPhotosAlbum({
  444. filePath: result.tempFilePath,
  445. success(res) {
  446. wx.showToast({
  447. title: '图片已保存到相册',
  448. icon: 'success'
  449. });
  450. }
  451. })
  452. },
  453. fail() { //这里是用户拒绝授权后的回调
  454. wx.showToast({
  455. title: '打开相册授权,才能保存图片哦~',
  456. icon: 'none',
  457. duration: 2000
  458. })
  459. that.setData({
  460. openSettingBtnHidden: false
  461. })
  462. }
  463. })
  464. } else {
  465. //调取小程序当中获取图片
  466. console.log(result.tempFilePath);
  467. wx.saveImageToPhotosAlbum({
  468. filePath: result.tempFilePath,
  469. success(res) {
  470. wx.showToast({
  471. title: '图片已保存到相册',
  472. icon: 'success'
  473. });
  474. }
  475. })
  476. }
  477. }
  478. })
  479. },
  480. fail: function (res) {
  481. console.log(res)
  482. }
  483. })
  484. },
  485. shar() {
  486. wx.downloadFile({
  487. url: this.data.saveimage, //图片服务器地址
  488. success: (res) => {
  489. wx.showShareImageMenu({
  490. path: res.tempFilePath, //转为本地地址showShareImageMenu进行分享
  491. success: (res) => {
  492. uni.hideLoading();
  493. this.modalShare = null;
  494. },
  495. fail: (err) => {
  496. uni.hideLoading();
  497. this.modalShare = null;
  498. },
  499. });
  500. },
  501. });
  502. },
  503. sharecircle() {
  504. console.log('this.data.saveimage', this.data.saveimage);
  505. wx.navigateTo({
  506. url: '../../circle/send-circle/index?image=' + this.data.saveimage // 目标页面的路径
  507. });
  508. }
  509. })