signMode.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <template>
  2. <<<<<<< HEAD
  3. <view class="main-content" v-if="isShow">
  4. <!-- 签字canvas -->
  5. <block v-if="showCanvas">
  6. <canvas
  7. class="mycanvas"
  8. id="mycanvas"
  9. canvas-id="mycanvas"
  10. @touchstart="touchstart"
  11. @touchmove="touchmove"
  12. @touchend="touchend"
  13. disable-scroll="true"
  14. ></canvas>
  15. <!-- 旋转canvas -->
  16. </block>
  17. <block class="" v-else>
  18. <image :src="imgurl" mode="" class="sign-img"></image>
  19. </block>
  20. <canvas
  21. class="rotatCanvas"
  22. id="rotatCanvas"
  23. :style="{ 'z-index': -1, width: `${screenWidth}px`, height: `${(screenWidth * screenWidth) / screenHeight}px` }"
  24. canvas-id="rotatCanvas"
  25. ></canvas>
  26. <view class="button-line">
  27. <view class="save-button" @tap.stop="finish">保存</view>
  28. <view class="clear-button" @tap.stop="clear">清除</view>
  29. <view class="cancel-button" @tap.stop="hide">关闭</view>
  30. </view>
  31. <view class="mask" v-if="showModal" @tap.stop>
  32. <view class="kw-modal flex align-items-center justify-content-center">
  33. <view class="kw-modal-content">
  34. <view class="flex justify-content-end font-size-34 lightgray">
  35. <text class="iconfont icon-guanbi" @tap="close"></text>
  36. </view>
  37. <view class="flex justify-content-center font-size-38 font-600 kw-modal-title">
  38. {{title}}
  39. </view>
  40. <view class="kw-modal-btnbox flex justify-content-between">
  41. <view @tap="cancel" class="kw-modal-btn">{{cancelText}}</view>
  42. <view @tap="confirm" class="kw-modal-btn">{{confirmText}}</view>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. <view class="mask" v-if="showToast">
  48. <view class="sign-toast flex align-items-center justify-content-center">
  49. <view class="toast-box">请先签名</view>
  50. </view>
  51. </view>
  52. </view>
  53. </template>
  54. <script>
  55. export default {
  56. data() {
  57. return {
  58. ctx: '', //绘图图像
  59. points: [], //路径点集合
  60. screenWidth: '',
  61. screenHeight: '',
  62. isRotatShow:false,
  63. showModal:false,
  64. showToast:false,
  65. startX:'',
  66. startY:'',
  67. moveX:'',
  68. moveY:'',
  69. imgurl:'',
  70. showCanvas:true,
  71. title:'提示框',
  72. cancelText:'取消',
  73. confirmText:'确认',
  74. };
  75. },
  76. props:{
  77. isShow:{
  78. type:Boolean,
  79. default:true
  80. }
  81. },
  82. mounted() {
  83. this.createCanvas();
  84. uni.getSystemInfo({
  85. success: e => {
  86. this.screenWidth = e.screenWidth;
  87. this.screenHeight = e.screenHeight - 110;
  88. console.log(e,'e')
  89. }
  90. });
  91. },
  92. methods: {
  93. show() {
  94. this.clear();
  95. this.isShow = true;
  96. },
  97. hide() {
  98. this.$emit('close',false)
  99. this.showCanvas = true
  100. },
  101. close(){
  102. this.showCanvas = true
  103. this.showModal = false
  104. },
  105. //取消保存
  106. cancel(){
  107. this.close()
  108. //清除画布
  109. this.clear()
  110. },
  111. confirm(){
  112. this.rotat(this.imgurl);
  113. },
  114. save(){
  115. this.showCanvas = false
  116. console.log(this.moveX,'moveX')
  117. console.log(this.moveY,'moveY')
  118. if(!this.moveX&&!this.moveY){
  119. this.showToast = true
  120. setTimeout(()=>{
  121. this.showToast = false
  122. this.showCanvas = true
  123. },1500)
  124. return false
  125. }
  126. this.showModal = true
  127. this.title = '确认签字?一旦确认,不能修改'
  128. },
  129. //创建并显示画布
  130. createCanvas() {
  131. this.showCanvas = true;
  132. this.ctx = uni.createCanvasContext('mycanvas', this); //创建绘图对象
  133. //设置画笔样式
  134. this.ctx.lineWidth = 2;
  135. this.ctx.lineCap = 'round';
  136. this.ctx.lineJoin = 'round';
  137. },
  138. //触摸开始,获取到起点
  139. touchstart(e) {
  140. let startX = e.changedTouches[0].x;
  141. let startY = e.changedTouches[0].y;
  142. let startPoint = {
  143. X: startX,
  144. Y: startY
  145. };
  146. this.points.push(startPoint);
  147. //每次触摸开始,开启新的路径
  148. this.ctx.beginPath();
  149. },
  150. //触摸移动,获取到路径点
  151. touchmove(e) {
  152. this.moveX = e.changedTouches[0].x;
  153. this.moveX = e.changedTouches[0].y;
  154. let moveX = e.changedTouches[0].x;
  155. let moveY = e.changedTouches[0].y;
  156. let movePoint = {
  157. X: moveX,
  158. Y: moveY
  159. };
  160. this.points.push(movePoint); //存点
  161. let len = this.points.length;
  162. if (len >= 2) {
  163. this.draw(); //绘制路径
  164. }
  165. },
  166. // 触摸结束,将未绘制的点清空防止对后续路径产生干扰
  167. touchend() {
  168. this.points = [];
  169. },
  170. draw() {
  171. let point1 = this.points[0];
  172. let point2 = this.points[1];
  173. this.points.shift();
  174. this.ctx.moveTo(point1.X, point1.Y);
  175. this.ctx.lineTo(point2.X, point2.Y);
  176. this.ctx.stroke();
  177. this.ctx.draw(true);
  178. },
  179. //清空画布
  180. clear() {
  181. this.ctx.clearRect(0, 0, this.screenWidth, this.screenHeight);
  182. this.ctx.draw(true);
  183. this.moveX = '';
  184. this.moveY = '';
  185. this.showCanvas = true
  186. },
  187. //完成绘画并保存到本地
  188. finish() {
  189. uni.canvasToTempFilePath(
  190. {
  191. canvasId: 'mycanvas',
  192. success: res => {
  193. this.imgurl = res.tempFilePath
  194. this.save()
  195. },
  196. complete: com => {}
  197. },
  198. this
  199. );
  200. },
  201. // 将图片选装
  202. rotat(e) {
  203. // this.isRotatShow = true
  204. // this.showCanvas = true
  205. let rotatCtx = uni.createCanvasContext('rotatCanvas', this); //创建绘图对象
  206. // 重新定位中心点
  207. rotatCtx.translate(0, (this.screenWidth * this.screenWidth) / this.screenHeight);
  208. // rotatCtx.translate(0, 0);
  209. // 将画布逆时针旋转90度
  210. rotatCtx.rotate((270 * Math.PI) / 180);
  211. // 将签字图片绘制进入Canvas
  212. rotatCtx.drawImage(e, 0, 0, (this.screenWidth * this.screenWidth) / this.screenHeight, this.screenWidth);
  213. // 保存后旋转后的结果
  214. rotatCtx.draw(true);
  215. setTimeout(() => {
  216. // 生成图片并回调
  217. uni.canvasToTempFilePath(
  218. {
  219. canvasId: 'rotatCanvas',
  220. success: val => {
  221. console.log('tempFilePath', val.tempFilePath)
  222. this.showCanvas = false
  223. this.$emit('savesign', {tempFilePath: val.tempFilePath ,flag: true} );
  224. setTimeout(() => {
  225. this.hide();
  226. }, 500);
  227. },
  228. complete: com => {
  229. // console.log(com);
  230. }
  231. },
  232. this
  233. );
  234. }, 500);
  235. }
  236. }
  237. };
  238. </script>
  239. <style lang="scss" scoped>
  240. .main-content {
  241. width: 100vw;
  242. height: 100vh;
  243. background-color: #ffffff;
  244. z-index: 9999;
  245. overflow: hidden;
  246. max-height:100vh;
  247. }
  248. .mycanvas {
  249. width: 100vw;
  250. height: calc(100vh - 120px);
  251. background-color: #efefef;
  252. position: fixed;
  253. left: 0rpx;
  254. top: 0rpx;
  255. z-index: 2;
  256. }
  257. .sign-img{
  258. width: 100vw;
  259. height: calc(100vh - 110px);
  260. }
  261. .rotatCanvas{
  262. background-color: red;
  263. }
  264. .button-line {
  265. transform: rotate(90deg);
  266. position: fixed;
  267. bottom: -130rpx;
  268. left: 260rpx;
  269. align-items: center;
  270. justify-content: space-between;
  271. z-index: 999;
  272. }
  273. .button-style {
  274. color: #ffffff;
  275. width: 100px;
  276. height: 120rpx;
  277. text-align: center;
  278. line-height: 120rpx;
  279. border-radius: 10rpx;
  280. margin-bottom: 40rpx;
  281. font-size: 34rpx
  282. }
  283. .save-button {
  284. @extend .button-style;
  285. background-color: #02b340;
  286. height: 140rpx;
  287. line-height: 140rpx;
  288. }
  289. .clear-button {
  290. @extend .button-style;
  291. background-color: #ffa500;
  292. height: 140rpx;
  293. line-height: 140rpx;
  294. }
  295. .cancel-button {
  296. @extend .button-style;
  297. background-color: #e10b2b;
  298. }
  299. .mask{
  300. width: 100vw;
  301. height: 100vh;
  302. background: rgba(0,0,0,0.8) ;
  303. position: absolute;
  304. top: 0;
  305. left: 0;
  306. z-index: 999;
  307. }
  308. .kw-modal,.sign-toast{
  309. width: 50vw;
  310. height: calc(100vh - 210px);
  311. transform: rotate(90deg);
  312. position: absolute;
  313. top: 0;
  314. left: 0;
  315. text-align: center;
  316. z-index: 999;
  317. }
  318. .kw-modal-content{
  319. width: 690rpx;
  320. // height: 400rpx;
  321. background: #efefef;
  322. border-radius: 30rpx;
  323. padding: 38rpx 30rpx 70rpx;
  324. .kw-modal-title{
  325. margin-top: 22rpx;
  326. }
  327. .kw-modal-tips{
  328. margin-top: 20rpx;
  329. }
  330. .kw-modal-inp{
  331. margin-top: 50rpx;
  332. .kw-inp{
  333. border: 1rpx solid #D9D9D9;
  334. border-radius: 4rpx;
  335. height: 70rpx;
  336. line-height: 70rpx;
  337. padding: 0 30rpx;
  338. }
  339. .inp-title{
  340. margin-right: 20rpx;
  341. }
  342. }
  343. .kw-modal-btnbox{
  344. margin-top: 100rpx;
  345. display: flex;
  346. justify-content: space-around;
  347. .kw-modal-btn{
  348. width: 300rpx;
  349. height: 84rpx;
  350. background: #D9D9D9;
  351. border-radius: 60rpx;
  352. line-height: 84rpx;
  353. text-align: center;
  354. font-size: 30rpx;
  355. &:last-child{
  356. color: #FFFFFF;
  357. background: #59A3FF;
  358. }
  359. }
  360. }
  361. }
  362. .toast-box{
  363. padding: 15rpx 30rpx;
  364. // background-color: rgba(0, 0, 0, .7);
  365. // color: #fff;
  366. background-color: #ffffff;
  367. color: #ffa500;
  368. border-radius: 8rpx;
  369. font-size: 30rpx;
  370. }
  371. =======
  372. <view class="signature-box">
  373. <!-- 签名 -->
  374. <view class="signature" v-show="showCanvas">
  375. <canvas class="mycanvas" canvas-id="mycanvas" @touchstart="touchstart" @touchmove="touchmove"
  376. @touchend="touchend"></canvas>
  377. <!-- <view style="padding: 5px;
  378. color: red;" class="text-sm colorred">注意:请用横屏签名</view> -->
  379. <view class="footer">
  380. <button @click="finish" type="primary">保存
  381. </button>
  382. <button @click="clear" type="default">清除
  383. </button>
  384. <button @click="close" type="warn">关闭
  385. </button>
  386. </view>
  387. </view>
  388. <!-- 签完名后生成的图片 -->
  389. <!-- <view v-show="SignatureImg" class="SignatureImg">
  390. <image :src="SignatureImg" mode=""></image>
  391. </view> -->
  392. <!-- 清除签完名后生成的图片 -->
  393. <!-- <button v-show="SignatureImg" @click="obliterate" type="error" :plain="true" :ripple="true"
  394. ripple-bg-color="#909399" size="medium">清除签名</button> -->
  395. </view>
  396. </template>
  397. <script>
  398. import {
  399. sign
  400. } from '@/api/workman.js'
  401. import {
  402. pathToBase64
  403. } from '@/utils/jssdk_image_tools.js'
  404. var x = 20;
  405. var y = 20;
  406. export default {
  407. data() {
  408. return {
  409. //绘图图像
  410. ctx: '',
  411. //路径点集合
  412. points: [],
  413. //签名图片
  414. SignatureImg: '',
  415. hasSign: false
  416. };
  417. },
  418. props: {
  419. salaryId: {
  420. type: [Number, String],
  421. default: 0
  422. },
  423. showCanvas: {
  424. type: Boolean,
  425. default: false
  426. },
  427. },
  428. created() {
  429. console.log(this.salaryId, 'options333')
  430. },
  431. methods: {
  432. //清除签名的图片
  433. open() {
  434. this.$refs.popup.open()
  435. },
  436. /**
  437. * 点击取消按钮触发
  438. * @param {Object} done
  439. */
  440. close() {
  441. // TODO 做一些其他的事情,before-close 为true的情况下,手动执行 close 才会关闭对话框
  442. // ...
  443. this.$refs.popup.close()
  444. },
  445. obliterate() {
  446. if (this.SignatureImg) {
  447. this.SignatureImg = '';
  448. }
  449. this.close();
  450. },
  451. //关闭并清空画布
  452. close() {
  453. uni.navigateBack({
  454. delta: 1
  455. })
  456. this.clear();
  457. },
  458. //创建并显示画布
  459. createCanvas() {
  460. this.ctx = uni.createCanvasContext('mycanvas', this); //创建绘图对象
  461. this.ctx.setFillStyle('#000000')
  462. this.ctx.fillStyle = '#000000'
  463. //设置画笔样式
  464. this.ctx.lineWidth = 4;
  465. this.ctx.lineCap = 'round';
  466. this.ctx.lineJoin = 'round';
  467. console.log(this.ctx)
  468. },
  469. //触摸开始,获取到起点
  470. touchstart(e) {
  471. let startX = e.changedTouches[0].x;
  472. let startY = e.changedTouches[0].y;
  473. let startPoint = {
  474. X: startX,
  475. Y: startY
  476. };
  477. this.points.push(startPoint);
  478. //每次触摸开始,开启新的路径
  479. this.ctx.beginPath();
  480. },
  481. //触摸移动,获取到路径点
  482. touchmove(e) {
  483. let moveX = e.changedTouches[0].x;
  484. let moveY = e.changedTouches[0].y;
  485. let movePoint = {
  486. X: moveX,
  487. Y: moveY
  488. };
  489. this.points.push(movePoint); //存点
  490. let len = this.points.length;
  491. if (len >= 2) {
  492. this.draw(); //绘制路径
  493. }
  494. },
  495. // 触摸结束,将未绘制的点清空防止对后续路径产生干扰
  496. touchend() {
  497. this.points = [];
  498. },
  499. //绘制笔迹
  500. draw() {
  501. let point1 = this.points[0];
  502. let point2 = this.points[1];
  503. this.points.shift();
  504. this.ctx.moveTo(point1.X, point1.Y);
  505. this.ctx.lineTo(point2.X, point2.Y);
  506. this.ctx.stroke();
  507. this.ctx.draw(true);
  508. this.hasSign = true
  509. },
  510. //清空画布
  511. clear() {
  512. this.hasSign = false
  513. let that = this;
  514. uni.getSystemInfo({
  515. success: function(res) {
  516. let canvasw = res.windowWidth;
  517. let canvash = res.windowHeight;
  518. that.ctx.clearRect(0, 0, canvasw, canvash);
  519. that.ctx.draw(true);
  520. }
  521. });
  522. },
  523. //完成绘画并保存到本地
  524. finish() {
  525. if (!this.hasSign) {
  526. uni.showToast({
  527. title: '签名为空不能保存',
  528. icon: 'none',
  529. duration: 2000
  530. })
  531. return
  532. }
  533. let that = this;
  534. uni.canvasToTempFilePath({
  535. canvasId: 'mycanvas',
  536. success: function(res) {
  537. if (!res || !res.tempFilePath) {
  538. console.log(res.tempFilePath);
  539. that.SignatureImg = res.tempFilePath;
  540. that.$emit('closeCanvas', that.SignatureImg);
  541. that.close();
  542. } else {
  543. //用来解决安卓真机获取到的是canvas图片的临时路径,转成base64格式
  544. pathToBase64(res.tempFilePath).then(re => {
  545. uni.setStorageSync('signaTureImg', re)
  546. console.log(re, 'signaTureImg')
  547. uni.showLoading({
  548. title: '签名中'
  549. })
  550. sign({
  551. signId: that.salaryId,
  552. pictureData: re
  553. }).then(res => {
  554. uni.hideLoading()
  555. that.$modal.confirm('签名成功','',false).then(() => {
  556. uni.navigateBack()
  557. })
  558. }).catch(err => {
  559. uni.hideLoading()
  560. })
  561. // that.SignatureImg = re;
  562. // that.$emit('closeCanvas', that.SignatureImg);
  563. //
  564. })
  565. }
  566. }
  567. });
  568. }
  569. },
  570. mounted() {
  571. this.createCanvas();
  572. }
  573. };
  574. </script>
  575. <style lang="less" scoped>
  576. .signature-box {
  577. display: flex;
  578. flex-direction: column;
  579. align-items: center;
  580. background: #fff;
  581. // height: calc(100vh-44rpx);
  582. //签名模块
  583. .signature {
  584. position: fixed;
  585. top: 10px;
  586. left: 2%;
  587. z-index: 999;
  588. width: 96%;
  589. //canvas
  590. .mycanvas {
  591. width: 100%;
  592. // height: calc(100vh - 200upx);
  593. height: calc(100vh - 60vh);
  594. background-color: #fff;
  595. border-radius: 10px 10px 0 0;
  596. }
  597. //底部按钮
  598. .footer {
  599. height: 130upx;
  600. display: flex;
  601. justify-content: space-around;
  602. align-items: center;
  603. background-color: #fff;
  604. border-radius: 0 0 10px 10px;
  605. border-top: 1px solid #a7a7a733;
  606. }
  607. ::v-deep .footer uni-button {
  608. font-size: 16px;
  609. padding: 8rpx 50rpx;
  610. }
  611. }
  612. //生成的图片
  613. .SignatureImg {
  614. image {
  615. width: 750rpx;
  616. height: 750rpx;
  617. }
  618. }
  619. }
  620. >>>>>>> d5d543f6014ac2bbe7c450bec75cf372ae8284be
  621. </style>