sign.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // pages/sign/index.js
  2. var canvas = null;
  3. const app = getApp()
  4. Page({
  5. /**
  6. * 页面的初始数据
  7. */
  8. data: {
  9. id:'',
  10. ctx: null,
  11. points: [], // 存储所有笔画
  12. currentStroke: [], // 当前笔画
  13. isDrawing: false,
  14. },
  15. /**
  16. * 生命周期函数--监听页面加载
  17. */
  18. onLoad(options) {
  19. this.setData({
  20. id:options.id
  21. })
  22. this.initCanvas();
  23. },
  24. /**
  25. * 初始化画布
  26. * 设置画布大小、像素比例和画笔样式
  27. */
  28. async initCanvas() {
  29. // 使用ID获取canvas组件实例
  30. const query = wx.createSelectorQuery();
  31. query.select('#canvas')
  32. .fields({ node: true, size: true })
  33. .exec((res) => {
  34. canvas = res[0].node;
  35. const ctx = canvas.getContext('2d');
  36. // Canvas 画布的实际绘制宽高
  37. const width = res[0].width
  38. const height = res[0].height
  39. // 设置画布大小,使用新的API获取设备像素比
  40. const dpr = wx.getWindowInfo().pixelRatio;
  41. canvas.width = width * dpr;
  42. canvas.height = height * dpr;
  43. ctx.scale(dpr, dpr);
  44. // 设置画笔样式
  45. ctx.strokeStyle = '#000000';
  46. ctx.lineWidth = 3;
  47. ctx.lineCap = 'round';
  48. ctx.lineJoin = 'round';
  49. //绘制背景
  50. ctx.fillStyle = '#fff'
  51. ctx.clearRect(0, 0, canvas.width, canvas.height)
  52. ctx.fillRect(0, 0, canvas.width, canvas.height)
  53. this.setData({ ctx });
  54. });
  55. },
  56. /**
  57. * 处理触摸开始事件
  58. * 开始一个新的笔画,记录起始点
  59. * @param {Object} e - 触摸事件对象
  60. */
  61. handleTouchStart(e) {
  62. const { x, y } = e.touches[0];
  63. this.setData({
  64. isDrawing: true,
  65. currentStroke: [[x, y]]
  66. });
  67. this.data.ctx.beginPath();
  68. this.data.ctx.moveTo(x, y);
  69. },
  70. /**
  71. * 处理触摸移动事件
  72. * 继续绘制当前笔画的路径
  73. * @param {Object} e - 触摸事件对象
  74. */
  75. handleTouchMove(e) {
  76. if (!this.data.isDrawing) return;
  77. const { x, y } = e.touches[0];
  78. this.data.currentStroke.push([x, y]);
  79. this.data.ctx.lineTo(x, y);
  80. this.data.ctx.stroke();
  81. },
  82. /**
  83. * 处理触摸结束事件
  84. * 完成当前笔画,将其添加到笔画历史中
  85. */
  86. handleTouchEnd() {
  87. if (!this.data.isDrawing) return;
  88. this.setData({
  89. isDrawing: false,
  90. points: [...this.data.points, this.data.currentStroke],
  91. currentStroke: []
  92. });
  93. },
  94. /**
  95. * 清除画布内容
  96. * 清空所有笔画记录和画布显示
  97. */
  98. handleClear() {
  99. const { ctx } = this.data;
  100. ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  101. this.setData({ points: [] });
  102. },
  103. /**
  104. * 撤销上一步操作
  105. * 移除最后一笔,并重绘剩余的笔画
  106. */
  107. handleUndo() {
  108. if (this.data.points.length === 0) return;
  109. const { ctx } = this.data;
  110. ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  111. // 移除最后一笔
  112. const newPoints = this.data.points.slice(0, -1);
  113. this.setData({ points: newPoints });
  114. // 重绘所有笔画
  115. newPoints.forEach(stroke => {
  116. ctx.beginPath();
  117. ctx.moveTo(stroke[0][0], stroke[0][1]);
  118. stroke.forEach(([x, y]) => {
  119. ctx.lineTo(x, y);
  120. });
  121. ctx.stroke();
  122. });
  123. },
  124. /**
  125. * 提交签名
  126. * 将画布内容转换为图片并处理提交逻辑
  127. * @returns {Promise<void>}
  128. */
  129. async handleSubmit() {
  130. let that = this
  131. if (this.data.points.length === 0) {
  132. wx.showToast({
  133. title: '请先签名',
  134. icon: 'none'
  135. });
  136. return;
  137. }
  138. try {
  139. // 将画布内容转换为图片
  140. const tempFilePath = await new Promise((resolve, reject) => {
  141. wx.canvasToTempFilePath({
  142. canvas: canvas,
  143. success: res => resolve(res.tempFilePath),
  144. fail: reject
  145. });
  146. });
  147. // 这里可以处理签名图片,比如上传到服务器
  148. console.log('签名图片路径:', tempFilePath);
  149. // 将图片转为 Base64
  150. that.imageToBase64(tempFilePath, function (error, base64String) {
  151. if (error) {
  152. console.error('Base64 转换失败', error);
  153. return;
  154. }
  155. that.setData({
  156. signature: base64String
  157. })
  158. let formData = {
  159. id:that.data.id,
  160. driverSign:base64String
  161. }
  162. // 上传 Base64 编码的图片,订单签名
  163. app.request.POST({
  164. url: app.API.updateDriverSign,
  165. params: formData,
  166. page: that,
  167. isLoadingTxt: '提交中...',
  168. isSubmitting: true,
  169. successFun: true
  170. }).then(res => {
  171. wx.showToast({
  172. title: '确认成功',
  173. icon: 'success',
  174. duration: 2000,
  175. mask:true,
  176. complete: function () {
  177. setTimeout(() => {
  178. wx.navigateBack()
  179. }, 1500) //延迟时间
  180. }
  181. })
  182. })
  183. //that.selfConfirm(base64String);
  184. });
  185. // wx.showToast({
  186. // title: '提交成功',
  187. // icon: 'success'
  188. // });
  189. // // 返回上一页
  190. // setTimeout(() => {
  191. // wx.navigateBack();
  192. // }, 1500);
  193. } catch (error) {
  194. console.error('提交签名失败:', error);
  195. wx.showToast({
  196. title: '提交失败',
  197. icon: 'error'
  198. });
  199. }
  200. },
  201. //图片转baose64
  202. imageToBase64(tempFilePath, callback) {
  203. wx.getFileSystemManager().readFile({
  204. filePath: tempFilePath,
  205. encoding: 'base64',
  206. success: function (res) {
  207. // 拼接与 PC 端一致的格式
  208. var base64Str = "data:image/png;base64," + res.data;
  209. callback(null, base64Str);
  210. },
  211. fail: function (error) {
  212. callback(error);
  213. }
  214. });
  215. },
  216. /**
  217. * 生命周期函数--监听页面初次渲染完成
  218. */
  219. onReady() {
  220. },
  221. /**
  222. * 生命周期函数--监听页面显示
  223. */
  224. onShow() {
  225. },
  226. /**
  227. * 生命周期函数--监听页面隐藏
  228. */
  229. onHide() {
  230. },
  231. /**
  232. * 生命周期函数--监听页面卸载
  233. */
  234. onUnload() {
  235. },
  236. /**
  237. * 页面相关事件处理函数--监听用户下拉动作
  238. */
  239. onPullDownRefresh() {
  240. },
  241. /**
  242. * 页面上拉触底事件的处理函数
  243. */
  244. onReachBottom() {
  245. },
  246. /**
  247. * 用户点击右上角分享
  248. */
  249. onShareAppMessage() {
  250. }
  251. })