signName.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <template>
  2. <!-- #ifdef H5 -->
  3. <view>
  4. <view class="wrapper">
  5. <view class="handBtn">
  6. <view class="left">
  7. <u-button @click="retDraw">重写</u-button>
  8. <u-button @click="previewCanvasImg">预览</u-button>
  9. </view>
  10. <view class="right">
  11. <u-button @click="subCanvas" type="primary">完成</u-button>
  12. </view>
  13. </view>
  14. <view class="handCenter">
  15. <canvas class="handWriting" id="handWriting" :disable-scroll="true" @touchstart="uploadScaleStart"
  16. @touchmove="uploadScaleMove" canvas-id="handWriting"></canvas>
  17. </view>
  18. <view class="handRight">
  19. <view class="handTitle">请签名</view>
  20. </view>
  21. </view>
  22. </view>
  23. <!-- #endif -->
  24. <!-- #ifndef H5 -->
  25. <web-view :src="webViewHref(`/packageWorkorder/pages/signName`, pam, crossPagePam)" @message="crossPage.$listener"></web-view>
  26. <!-- #endif -->
  27. </template>
  28. <script>
  29. // #ifdef H5
  30. import { uploadImgFull } from '@/common/utils/util.js';
  31. export default {
  32. data() {
  33. return {
  34. canvasName: 'handWriting',
  35. ctx: '',
  36. startX: null,
  37. startY: null,
  38. canvasWidth: 0,
  39. canvasHeight: 0,
  40. selectColor: 'black',
  41. lineColor: '#1A1A1A', // 颜色
  42. lineSize: 5, // 笔记倍数
  43. isWrite: false,
  44. };
  45. },
  46. onLoad() {
  47. this.ctx = uni.createCanvasContext("handWriting");
  48. this.$nextTick(() => {
  49. uni.createSelectorQuery().select('.handCenter').boundingClientRect(rect => {
  50. this.canvasWidth = rect.width;
  51. this.canvasHeight = rect.height;
  52. /* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
  53. this.setCanvasBg('#fff');
  54. })
  55. .exec();
  56. });
  57. },
  58. methods: {
  59. // 笔迹开始
  60. uploadScaleStart(e) {
  61. this.startX = e.changedTouches[0].x
  62. this.startY = e.changedTouches[0].y
  63. //设置画笔参数
  64. //画笔颜色
  65. this.ctx.setStrokeStyle(this.lineColor)
  66. //设置线条粗细
  67. this.ctx.setLineWidth(this.lineSize)
  68. //设置线条的结束端点样式
  69. this.ctx.setLineCap("round") //'butt'、'round'、'square'
  70. //开始画笔
  71. this.ctx.beginPath()
  72. },
  73. // 笔迹移动
  74. uploadScaleMove(e) {
  75. //取点
  76. let temX = e.changedTouches[0].x
  77. let temY = e.changedTouches[0].y
  78. //画线条
  79. this.ctx.moveTo(this.startX, this.startY)
  80. this.ctx.lineTo(temX, temY)
  81. this.ctx.stroke()
  82. this.startX = temX
  83. this.startY = temY
  84. this.ctx.draw(true)
  85. this.isWrite = true;
  86. },
  87. // 重写
  88. retDraw() {
  89. this.ctx.clearRect(0, 0, 700, 730);
  90. this.ctx.draw();
  91. //设置canvas背景
  92. this.setCanvasBg('#fff');
  93. this.isWrite = false;
  94. },
  95. // 完成
  96. subCanvas() {
  97. if(!this.isWrite) return this.$toast('请签名');
  98. uni.canvasToTempFilePath({
  99. canvasId: 'handWriting',
  100. fileType: 'png',
  101. quality: 1, //图片质量
  102. destWidth: document.getElementById('handWriting').offsetWidth / 2,
  103. destHeight: document.getElementById('handWriting').offsetHeight / 2,
  104. success: async (res) => {
  105. this.rotateBase64(res.tempFilePath).then(async (img) => {
  106. if(img){
  107. let data = await uploadImgFull(img);
  108. // console.log(res.tempFilePath, 'canvas生成图片地址');
  109. this.crossPage.$emit('finishSign', data.url);
  110. this.$navToPage({
  111. delta: 1
  112. }, 'navigateBack')
  113. }
  114. });
  115. }
  116. });
  117. },
  118. // 将base64图片旋转90度以后上传
  119. rotateBase64(imgBase64) {
  120. return new Promise((resolve) => {
  121. const imgView = new Image();
  122. imgView.src = imgBase64;
  123. const canvas = document.createElement('canvas');
  124. const context = canvas.getContext('2d');
  125. const cutCoor = {
  126. sx: 0,
  127. sy: 0,
  128. ex: 0,
  129. ey: 0,
  130. };
  131. // 裁剪坐标
  132. imgView.onload = () => {
  133. const imgW = imgView.width;
  134. const imgH = imgView.height;
  135. const size = imgH;
  136. // 常量大小 = imgH;
  137. canvas.width = size * 2;
  138. canvas.height = size * 2;
  139. cutCoor.sx = size;
  140. cutCoor.sy = size - imgW;
  141. cutCoor.ex = size + imgH;
  142. cutCoor.ey = size + imgW;
  143. context.translate(size, size);
  144. context.rotate((Math.PI / 2) * 3);
  145. context.drawImage(imgView, 0, 0);
  146. const imgData = context.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey);
  147. canvas.width = imgH;
  148. canvas.height = imgW;
  149. context.putImageData(imgData, 0, 0);
  150. resolve(canvas.toDataURL('image/png'));
  151. };
  152. });
  153. },
  154. // 预览
  155. previewCanvasImg() {
  156. uni.canvasToTempFilePath({
  157. canvasId: 'handWriting',
  158. fileType: 'jpg',
  159. quality: 1, //图片质量
  160. success(res) {
  161. uni.previewImage({
  162. urls: [res.tempFilePath] //预览图片 数组
  163. });
  164. }
  165. });
  166. },
  167. //设置canvas背景色 不设置 导出的canvas的背景为透明
  168. //@params:字符串 color
  169. setCanvasBg(color) {
  170. /* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
  171. //rect() 参数说明 矩形路径左上角的横坐标,左上角的纵坐标, 矩形路径的宽度, 矩形路径的高度
  172. //这里是 canvasHeight - 4 是因为下边盖住边框了,所以手动减了写
  173. this.ctx.rect(0, 0, this.canvasWidth, this.canvasHeight - 4);
  174. // ctx.setFillStyle('red')
  175. this.ctx.setFillStyle(color);
  176. this.ctx.fill(); //设置填充
  177. this.ctx.draw(); //开画
  178. }
  179. }
  180. };
  181. // #endif
  182. // #ifndef H5
  183. export default {
  184. data() {
  185. return {
  186. pam: {},
  187. }
  188. },
  189. onLoad(pam) {
  190. this.pam = pam;
  191. }
  192. }
  193. // #endif
  194. </script>
  195. <style scoped lang="scss">
  196. page {
  197. background: #fbfbfb;
  198. height: auto;
  199. overflow: hidden;
  200. }
  201. .wrapper {
  202. width: 100%;
  203. height: 95vh;
  204. margin: 30rpx 0;
  205. overflow: hidden;
  206. display: flex;
  207. align-content: center;
  208. flex-direction: row;
  209. justify-content: center;
  210. font-size: 28rpx;
  211. }
  212. .handWriting {
  213. background: #fff;
  214. width: 100%;
  215. height: 95vh;
  216. }
  217. .handRight {
  218. display: inline-flex;
  219. align-items: center;
  220. }
  221. .handCenter {
  222. border: 4rpx dashed #e9e9e9;
  223. flex: 5;
  224. overflow: hidden;
  225. box-sizing: border-box;
  226. }
  227. .handTitle {
  228. transform: rotate(90deg);
  229. flex: 1;
  230. color: #666;
  231. }
  232. .handBtn button {
  233. font-size: 28rpx;
  234. }
  235. .handBtn {
  236. height: 95vh;
  237. display: flex;
  238. flex-direction: column;
  239. justify-content: space-between;
  240. flex: 1;
  241. .left {
  242. display: flex;
  243. flex-direction: column;
  244. }
  245. ::v-deep .u-button {
  246. flex-shrink: 0;
  247. transform: rotate(90deg);
  248. margin-bottom: 30rpx;
  249. margin-top: 30rpx;
  250. }
  251. }
  252. </style>