支付寶小程式 橫屏電子版簽字 ,canvas實現

那年發表於2022-04-14

背景描述:業務需要在支付寶小程式橫屏簽字,但是目前支付寶不支援橫屏,所以只能用樣式引導使用者
實現效果:
image.png

思路:
使用transform和translate 去旋轉頁面,這樣就能滿足樣式的需求,看著是沒啥問題,但是當在canvas上繪畫的時候,就會看到,我寫的是一橫,展示的確是一豎
原因:頁面是旋轉了,但是座標系統沒有改變

image.png

解決方案:調整座標系統
可藉由rotate逆向旋轉90°,然後由translate平移座標系。

context.rotate((degree * Math.PI) / 180);
switch (degree) {
  // 頁面順時針旋轉90°後,畫布左上角的原點位置落到了螢幕的右上角(此時寬高互換),圍繞原點逆時針旋轉90°後,畫布與原位置垂直,居於螢幕右側,需要向左平移畫布當前高度相同的距離。
  case -90:
    context.translate(-height, 0);
    break;
  // 頁面逆時針旋轉90°後,畫布左上角的原點位置落到了螢幕的左下角(此時寬高互換),圍繞原點順時針旋轉90°後,畫布與原位置垂直,居於螢幕下側,需要向上平移畫布當前寬度相同的距離。
  case 90:
    context.translate(0, -width);
    break;
  // 頁面順逆時針旋轉180°回到了同一個位置(即頁面倒立),畫布左上角的原點位置落到了螢幕的右下角(此時寬高不變),圍繞原點反方向旋轉180°後,畫布與原位置平行,居於螢幕右側的下側,需要向左平移畫布寬度相同的距離,向右平移畫布高度的距離。
  case -180:
  case 180:
    context.translate(-width, -height);
}

下面是我的程式碼:

<canvas ref="cxt" id="xfCanvas" class="xfcanvas" :style="{ height: canvasw -52+'px' , width: '100%'}"
      @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" :disable-scroll="true">
    </canvas>
    <view class="btn">
      <view @click="resetImg">重籤</view>
      <view @click="goSignDate">下一步籤日期</view>
    </view>
    mounted() {
      let that = this;
      uni.getSystemInfo({
        success: function(res) {
          that.canvasw = res.windowWidth;
          that.canvash = res.windowHeight;
          console.log(that.canvasw, that.canvash, '畫布尺寸');
          that.$nextTick(() => {
            that.ctx = uni.createCanvasContext('xfCanvas');
//========重點在這裡  改變座標系統,52的高度是我操作按鈕的高度=============
            that.ctx.rotate((-90 * Math.PI) / 180); 
            that.ctx.translate(-that.canvash + that.canvasw + 52, 0)
            that.ctx.setStrokeStyle('#000'); // 顏色
            that.ctx.setLineWidth(8); // 粗細
            that.ctx.setLineCap('round'); // 線頭形狀
            that.ctx.setLineJoin('round'); // 交叉處形狀
          });
        },
      });
    },

methods:{
     touchStart(e) {
        console.log('+++++++++++剛開始觸控');
        this.startX = e.changedTouches[0].x;
        this.startY = e.changedTouches[0].y;
        this.ctx.beginPath();
        this.ctx.moveTo(this.startX, this.startY); // 找到起點
      },
      touchMove(e) {
        console.log('+++++++++++觸控進行中');
        this.isSign = true
        let moveX = e.changedTouches[0].x;
        let moveY = e.changedTouches[0].y;
        this.ctx.lineTo(moveX, moveY); // 找到終點
        this.ctx.stroke(); // 描繪路徑
        this.ctx.draw(true, function(ret) {});
      },
      touchEnd() {
        this.isSign = true
        console.log('+++++結束啦', this.ctx);
      },}

最後實現效果

image.png
折騰了好一會,參考了大佬的文件,受益匪淺,原文連結:https://segmentfault.com/a/11...

相關文章