moment_share.tsx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import { useDispatch, useSelector } from "react-redux";
  2. import { useEffect, useState } from "react";
  3. import { View, Canvas } from "@tarojs/components";
  4. import Taro, { useDidShow } from "@tarojs/taro";
  5. export default function MomentShare() {
  6. const user = useSelector((state: any) => state.user);
  7. const info = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync()
  8. const dpr = info.pixelRatio; // 获取设备的像素比
  9. useEffect(() => {
  10. if (user.isLogin) {
  11. // beginDraw()
  12. downCover()
  13. }
  14. }, [user])
  15. useDidShow(() => {
  16. if (user.isLogin) {
  17. // beginDraw()
  18. downCover()
  19. }
  20. })
  21. async function downCover() {
  22. const urls = ['https://background-pictures.oss-cn-beijing.aliyuncs.com/share_cover/invite.png', user.avatar]
  23. try {
  24. const imagePaths = await Promise.all(urls.map(downloadImage));
  25. beginDraw(imagePaths);
  26. } catch (error) {
  27. console.error('下载图片错误:', error);
  28. }
  29. }
  30. function downloadImage(url) {
  31. return new Promise((resolve, reject) => {
  32. Taro.downloadFile({
  33. url,
  34. success: (res) => {
  35. if (res.statusCode === 200) {
  36. resolve(res.tempFilePath);
  37. } else {
  38. reject(new Error('图片下载失败'));
  39. }
  40. },
  41. fail: (err) => {
  42. reject(err);
  43. }
  44. });
  45. });
  46. }
  47. function beginDraw(imagePaths) {
  48. const query = Taro.createSelectorQuery();
  49. query.select(`#moment_share`).fields({ node: true, size: true });
  50. query.exec((res) => {
  51. const _canvas = res[0].node;
  52. _canvas.width = res[0].width * dpr;
  53. _canvas.height = res[0].height * dpr;
  54. const ctx = _canvas.getContext('2d');
  55. global.canvas2 = _canvas
  56. drawDetail(ctx, imagePaths, _canvas)
  57. });
  58. }
  59. function drawDetail(ctx, imagePaths, canvas) {
  60. const img = canvas.createImage(); // 创建图像对象
  61. img.src = imagePaths[0]
  62. img.onload = () => {
  63. ctx.drawImage(img, 0, 0, 420 * dpr, 336 * dpr);
  64. ctx.stroke();
  65. const img1 = canvas.createImage(); // 创建图像对象
  66. img1.src = imagePaths[1]
  67. img1.onload = () => {
  68. // ctx.fillStyle = '#ff0000'
  69. // ctx.fillRect(0, 0, 420 * dpr, 336 * dpr);
  70. const x = 64 * dpr; // 矩形左上角 x 坐标
  71. const y = 212 * dpr; // 矩形左上角 y 坐标
  72. const width = 292 * dpr; // 矩形宽度
  73. const height = 72 * dpr; // 矩形高度
  74. const radius = 18 * dpr; // 圆角半径
  75. // 绘制带圆角的矩形
  76. ctx.beginPath();
  77. ctx.moveTo(x + radius, y); // 移动到左上角的圆角位置
  78. ctx.arcTo(x + width, y, x + width, y + height, radius); // 右上角
  79. ctx.arcTo(x + width, y + height, x, y + height, radius); // 右下角
  80. ctx.arcTo(x, y + height, x, y, radius); // 左下角
  81. ctx.arcTo(x, y, x + width, y, radius); // 左上角
  82. ctx.closePath();
  83. ctx.fillStyle = '#ff0000'; // 设置填充颜色为红色
  84. ctx.fill(); // 填充矩形
  85. ctx.font = `bold ${26 * dpr}px sans-serif`
  86. ctx.fillStyle = '#ffffff'
  87. ctx.textAlign = 'center'
  88. ctx.fillText('立即跟卡', x + width / 2.0, y + height / 2.0+10*dpr);
  89. ctx.font = `bold ${24 * dpr}px sans-serif`
  90. ctx.fillStyle = '#E0B152'
  91. ctx.textAlign = 'center'
  92. var name = user.nickname.length > 8 ? user.nickname.substring(0, 8) + '...' : user.nickname
  93. ctx.fillText(name, 210 * dpr, 182 * dpr);
  94. ctx.beginPath()
  95. ctx.arc(210 * dpr, 82 * dpr, 70 * dpr, 0, Math.PI * 2)
  96. ctx.clip()
  97. ctx.drawImage(img1, 140 * dpr, 12 * dpr, 140 * dpr, 140 * dpr);
  98. ctx.restore()
  99. ctx.stroke();
  100. Taro.canvasToTempFilePath({
  101. canvas: canvas,
  102. success: (res) => {
  103. console.log('图片保存成功:', res.tempFilePath);
  104. global.moment_share_url = res.tempFilePath
  105. },
  106. fail: (err) => {
  107. console.error('转为图片失败:', err);
  108. }
  109. });
  110. }
  111. };
  112. }
  113. function drawDetail2(ctx, imagePaths, canvas) {
  114. const promises = imagePaths.map((path, index) => {
  115. return new Promise((resolve) => {
  116. const img = canvas.createImage(); // 创建图像对象
  117. img.src = path;
  118. if (index == 0) {
  119. img.onload = () => {
  120. ctx.drawImage(img, 0, 0, 420 * dpr, 336 * dpr);
  121. ctx.stroke();
  122. resolve(true);
  123. };
  124. }
  125. else {
  126. img.onload = () => {
  127. ctx.font = `bold ${24 * dpr}px sans-serif`
  128. ctx.fillStyle = '#E0B152'
  129. ctx.textAlign = 'center'
  130. var name = user.nickname.length > 8 ? user.nickname.substring(0, 8) + '...' : user.nickname
  131. ctx.fillText(name, 210 * dpr, 182 * dpr);
  132. ctx.beginPath()
  133. ctx.arc(210 * dpr, 82 * dpr, 70 * dpr, 0, Math.PI * 2)
  134. ctx.clip()
  135. ctx.drawImage(img, 140 * dpr, 12 * dpr, 140 * dpr, 140 * dpr);
  136. ctx.restore()
  137. ctx.stroke();
  138. resolve(true);
  139. };
  140. }
  141. });
  142. });
  143. Promise.all(promises).then(() => {
  144. // ctx.draw();
  145. Taro.canvasToTempFilePath({
  146. canvas: canvas,
  147. success: (res) => {
  148. console.log('图片保存成功:', res.tempFilePath);
  149. global.moment_share_url = res.tempFilePath
  150. },
  151. fail: (err) => {
  152. console.error('转为图片失败:', err);
  153. }
  154. });
  155. //
  156. // const ctx = Taro.createCanvasContext(this.canvasId);
  157. // ctx.draw();
  158. });
  159. // ctx.drawImage(imagePaths[0], 0, 0, 420, 336) // 设置图片位置和大小
  160. // ctx.draw()
  161. }
  162. return <View style={{ position: 'absolute', left: 0, top: -500, width: 420, height: 336, zIndex: 10000 }}>
  163. <Canvas canvasId='moment_share' id='moment_share' className="canvas" type="2d" style={{ width: 420, height: 336, zIndex: 0 }} />
  164. </View>
  165. }