canvas书写图片并修改尺寸

记录一下两年前的一个关于canvas设置手写签名的需求

需求如下:

由于手写区域较大,部分用户手写的区域较小,在盖章的过程中,可能会使得签名笔迹看起来特别小,我们需要将用户真实手写的笔迹进行区域裁剪,得到红框中的部分,使得该图片在盖章展示的时候能看清用户的笔迹

分析设计:

  • 1.由于需要对canvas中已经手写的笔迹进行处理,且手写区域是固定的,一次需要再有一个canvas(adjustCanvas)来处理
  • 2.需要将用户的手写笔迹记录下来,并形成一个矩形区域,在二次绘制的时候,就能确定adjustCanvas的宽高
  • 3.将手写签名的尺寸固定为400*160

要点

1.在touch事件中记录手写区域,包含最小和最大的x、y坐标,因此格式为mEffectivePoint = {
    minX: -1,
    minY: -1,
    maxX: -1,
    maxY: -1,
  }

2.将手写区域的canvas作为原始图片,在重绘前将其赋值到image对象

var image = new Image()
image.src = document.getElementById('myCanvas').toDataURL('image/png')

3.重绘时,需要将canvas的绘图方法需要将原本的图和最终图片的起点和宽高计算出来,该函数定义为:

drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;

关键代码:

  • 设置一个不展示的canvas节点,用来重绘手写签名图片
<div id="work_area" class="canvasContain">

  <canvas id="idStampAdjustCanvas" class="canvasContentAdjust"></canvas>

  <canvas id="myCanvas" class="canvasContent"></canvas>
</div>
  • 在手写的过程中,记录手写区域
var mEffectivePoint = {
    minX: -1,
    minY: -1,
    maxX: -1,
    maxY: -1,
  }

///


/**
   * 重新计算手写签名的有效区域
   * @param x
   * @param y
   */
  function checkEffectivePoint (x, y) {
    if (x >= 0 && x <= mCanvasWidth) {
      if (x - mPanWidth < mEffectivePoint.minX || mEffectivePoint.minX === -1) {
        mEffectivePoint.minX = x - mPanWidth
        if (mEffectivePoint.minX < 0) {
          mEffectivePoint.minX = 0
        }
      }
      if (x + mPanWidth > mEffectivePoint.maxX || mEffectivePoint.maxX === -1) {
        mEffectivePoint.maxX = x + mPanWidth
        if (mEffectivePoint.maxX > mCanvasWidth) {
          mEffectivePoint.maxX = mCanvasWidth
        }
      }
    }
    if (y >= 0 && y <= mCanvasHeight) {
      if (y - mPanWidth < mEffectivePoint.minY || mEffectivePoint.minY === -1) {
        mEffectivePoint.minY = y - mPanWidth
        if (mEffectivePoint.minY < 0) {
          mEffectivePoint.minY = 0
        }
      }
      if (y + mPanWidth > mEffectivePoint.maxY || mEffectivePoint.maxY === -1) {
        mEffectivePoint.maxY = y + mPanWidth
        if (mEffectivePoint.maxY > mCanvasHeight) {
          mEffectivePoint.maxY = mCanvasHeight
        }
      }
    }
  }

  function touchStart (event) {
    event.preventDefault()
    HAS_IMAGE = true
    for (var i = 0; i < event.touches.length; i++) {
      checkEffectivePoint(event.touches[i].pageX - mCanvasOffsetLeft, event.touches[i].pageY - mCanvasOffsetTop)
      paths.push({
        id: event.touches[i].identifier,
        points: [{
          x: event.touches[i].pageX - mCanvasOffsetLeft,
          y: event.touches[i].pageY - mCanvasOffsetTop,
          timestamp: new Date().getTime(),
          drawn: false,
        }],
        complete: false,
      })
    }
  }

  function touchEnd (event) {
    event.preventDefault()
    for (var i = 0; i < event.changedTouches.length; i++) {
      for (var j = 0; j < paths.length; j++) {
        if (paths[j].id == event.changedTouches[i].identifier) {
          paths[j].id = null
          paths[j].complete = true
        }
      }
    }
  }

  function touchMove (event) {
    event.preventDefault()

    for (var i = 0; i < event.touches.length; i++) {
      for (var j = 0; j < paths.length; j++) {
        if (paths[j].id == event.touches[i].identifier) {
          checkEffectivePoint(event.touches[i].pageX - mCanvasOffsetLeft, event.touches[i].pageY - mCanvasOffsetTop)
          paths[j].points.push({
            x: event.touches[i].pageX - mCanvasOffsetLeft,
            y: event.touches[i].pageY - mCanvasOffsetTop,
            drawn: false,
            timestamp: new Date().getTime(),
          })
        }
      }
    }
  }
  • 补充需求—将手写签名的区域固定为400*160

  // 我们将图章设置为400*160的尺寸保存到服务端
  var stampMaxX = 400
  var stampMaxY = 160

/**
   *
   * 根据原始图片的宽高,在限定尺寸的canvas中配置好绘图起始点坐标和宽高,让图片能够不变形地完全绘制在限定尺寸的canvas中
   * @param width 真实手写的宽
   * @param height  真实手写区域的高度
   * canvas的尺寸(maxX=400,maxY=160)
   * 1-原始图片width<maxX
   *   1-1 height<maxY
   *   1-2 height>=maxY
   * 2-原始图片width>=maxX
   *   2-1 width/maxX > height/maxY (宽度的比例大于高度的比例)
   *   2-2 width/maxX <= height/maxY
   *
   * @return {
   
   {width: number, startY: number, startX: number, height: number}}
   */
  function getDrawArea (width, height) {
    var drawStartPoint = {
      startX: 0,  //重绘起点的x坐标
      startY: 0,  //重绘起点的y坐标
      width: stampMaxX, //重绘图片的宽
      height: stampMaxY,  //重绘图片的高
    }
    if (width < stampMaxX) {
      if (height < stampMaxY) {

        drawStartPoint = {
          startX: (stampMaxX - width) / 2,
          startY: (stampMaxY - height) / 2,
          width: width,
          height: height,
        }
      } else {
        var scale = stampMaxY / height
        drawStartPoint = {
          startX: (stampMaxX - width * scale) / 2,
          startY: 0,
          width: width * scale,
          height: stampMaxY,
        }
      }
    } else {
      var scaleWidth = stampMaxX / width
      var scaleHeight = stampMaxY / height
      var scale = scaleWidth
      if (width / height > stampMaxX / stampMaxY) {
        // 说明图片相对比例,缩放后,width更小,所以以height为基准边
        scale = scaleWidth
        drawStartPoint = {
          startX: 0,
          startY: (stampMaxY - height * scale) / 2,
          width: stampMaxX,
          height: height * (stampMaxX / width),
        }
      } else {
        scale = scaleHeight
        drawStartPoint = {
          startX: (stampMaxX - width * scale) / 2,
          startY: 0,
          width: width * (stampMaxY / height),
          height: stampMaxY,
        }
      }
    }
    return drawStartPoint
  }



// ....其他逻辑代码

/**
   * 根据手写区域裁剪图片
   */
  function getImageByEffectiveArea (imageSource, callback) {
    var effectivePoint = {
      minX: mEffectivePoint.minX,
      maxX: mEffectivePoint.maxX === mEffectivePoint.minX ? mEffectivePoint.minX + 10 : mEffectivePoint.maxX,
      minY: mEffectivePoint.minY,
      maxY: mEffectivePoint.maxY === mEffectivePoint.minX ? mEffectivePoint.maxY + 10 : mEffectivePoint.maxY,
    }
    canvas2 = document.getElementById('idStampAdjustCanvas')
    context2 = canvas2.getContext('2d')
    //先清除
    context2.clearRect(0, 0, canvas2.width, canvas2.height)
    var width = effectivePoint.maxX - effectivePoint.minX
    var height = effectivePoint.maxY - effectivePoint.minY
    canvas2.width = stampMaxX
    canvas2.height = stampMaxY
    loadImage(imageSource.src, function () {
      context2 = canvas2.getContext('2d')
      var drawStartPoint = getDrawArea(width, height)
      context2.drawImage(imageSource,
        effectivePoint.minX, effectivePoint.minY, width, height,
        drawStartPoint.startX, drawStartPoint.startY,
        drawStartPoint.width, drawStartPoint.height)
      callback(canvas2.toDataURL('image/png'))
    })
  }
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>签名笔迹设置</title>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
  <meta name="apple-mobile-web-app-capable" content="yes"/>

  <style type="text/css">
    * {
      padding: 0;
      margin: 0;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }

    html {
      height: 100%;
      width: 100%;
    }

    body {
      height: 100%;
      width: 100%;
      box-sizing: border-box;
      -moz-box-sizing: border-box; /* Firefox */
      -webkit-box-sizing: border-box; /* Safari */
      display: flex;
      display: -webkit-flex;
      display: inline-flex;
      display: -moz-flex;
      display: -ms-flexbox;
      flex-direction: row;
      -webkit-flex-direction: row;
    }

    .canvasContain {
      display: flex;
      flex: 1;
      position: relative;
    }

    .canvasContent {
      display: block;
      width: 100%;
      z-index: 99;
      /*background-color: #FFF;*/
      background: #FFF url(./image/bg_canvas.png) no-repeat fixed center;
    }

    .canvasContentAdjust {
      position: absolute;
      display: none;
      background-color: #F2F2F2;
      z-index: 1;
      width: 400px;
      height: 160px;

    }

    .rightContain {
      display: flex;
      display: -webkit-flex;
      justify-content: flex-end;
      -webkit-justify-content: flex-end;
      flex-direction: column;
      -webkit-flex-direction: column;
      align-items: center;
      width: 60px;
      background-color: #F2F2F2;
      padding-bottom: 20px;
    }

    .penContain {
      width: 60px;
      height: 45px;
      text-align: center;
      vertical-align: middle;
      display: flex;
      display: -webkit-flex;
      justify-content: center;
      -webkit-justify-content: center;
      flex-direction: column;
      -webkit-flex-direction: column;
      box-sizing: border-box;
      -moz-box-sizing: border-box; /* Firefox */
      -webkit-box-sizing: border-box; /* Safari */
    }

    .pen {
      margin: 0 auto;
      display: flex;
      border: solid 2px transparent;
      background-color: #000;
      border-radius: 50%;
    }

    .i1 {
      width: 10px;
      height: 10px;
    }

    .i2 {
      width: 14px;
      height: 14px;
    }

    .i3 {
      width: 18px;
      height: 18px;
    }

    .on {
      border: solid 2px #999;
    }

    .delete {
      color: #333;
      background: url(./image/del.png) no-repeat center center;
      background-size: 80% 100%;
      outline: none;
    }

    .save {
      color: #333;
      background: url(./image/signed.png) no-repeat center center;
      background-size: 80% 100%;
      outline: none;
    }

    .click-image {
      margin-top: 15px;
      width: 60px;
      height: 40px;
      /*transform: rotate(-90deg);*/
      border: 0 none;
      position: relative;
      z-index: auto;
    }


  </style>
</head>

<body>

<!-- 正文 -->
<div id="work_area" class="canvasContain">

  <canvas id="idStampAdjustCanvas" class="canvasContentAdjust"></canvas>

  <canvas id="myCanvas" class="canvasContent"></canvas>
  <!--    <img id='signImg' src='draw/image/canvas_bg1.png'/>-->
</div>


<div class="rightContain">
  <div class="penContain" onclick="setPenWidth(3)">
    <div class="pen i1" id="idPenSmall"></div>
  </div>
  <div class="penContain" onclick="setPenWidth(5)">
    <div class="pen i2 on" id="idPenNormal"></div>
  </div>
  <div class="penContain" onclick="setPenWidth(8)">
    <div class="pen i3" id="idPenMax"></div>
  </div>
  <div class="H5_footer pull-left btncon">
    <button class="click-image delete" onclick="clean()"></button>
    <button class="click-image save" onclick="save()"></button>
  </div>
</div>


<script type="text/javascript">
  var CANVAS_WIDTH = 0
  var CANVAS_HEIGHT = 0

  // 我们将图章设置为400*160的尺寸保存到服务端
  var stampMaxX = 400
  var stampMaxY = 160

  var PAN_WIDTH_SMALL = 3
  var PAN_WIDTH_NORMAL = 5
  var PAN_WIDTH_BIG = 8

  var MAX_VELOCITY = 10
  var context = null
  var HAS_IMAGE = false
  var scale = 1

  var mCanvasWidth = 0
  var mCanvasHeight = 0
  var mCanvasOffsetLeft = 0
  var mCanvasOffsetTop = 0

  var base_url = null
  var token = null

  var mStartPoint = {
    x: 0,
    y: 0,
  }

  var mEndPoint = {
    x: 0,
    y: 0,
  }

  var mPanWidth = PAN_WIDTH_NORMAL
  var canvas2
  var context2

  var mEffectivePoint = {
    minX: -1,
    minY: -1,
    maxX: -1,
    maxY: -1,
  }

  var paths = []

  function clean () {
    context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
    HAS_IMAGE = false
    initEffectivePoint()
    return false
  }

  function setPenWidth (width) {
    mPanWidth = width
    removeSelectPenStyle()
    if (width > PAN_WIDTH_NORMAL) {
      document.getElementById('idPenMax').className = 'pen i3 on'
    } else if (width < PAN_WIDTH_NORMAL) {
      document.getElementById('idPenSmall').className = 'pen i1 on'
    } else {
      document.getElementById('idPenNormal').className = 'pen i2 on'
    }
    console.log(document.getElementById('idPenSmall').className)
    console.log(document.getElementById('idPenNormal').className)
    console.log(document.getElementById('idPenMax').className)
  }

  function removeSelectPenStyle () {
    document.getElementById('idPenSmall').className = 'pen i1'
    document.getElementById('idPenNormal').className = 'pen i2'
    document.getElementById('idPenMax').className = 'pen i3'
  }
  function init () {
    CANVAS_WIDTH = document.body.clientWidth - 60
    CANVAS_HEIGHT = document.body.clientHeight
    var canvas = document.getElementById('myCanvas')
    mCanvasWidth = CANVAS_WIDTH
    mCanvasHeight = CANVAS_HEIGHT
    canvas.height = CANVAS_HEIGHT
    canvas.width = CANVAS_WIDTH
    context = canvas.getContext('2d')
    var image = new Image()

    if (image.src != 'data:image/png;base64,null') {
      preImage(image.src, function () {
        context.drawImage(this, 0, 0, this.width * scale, this.height * scale)
        HAS_IMAGE = true
      })
    }

    context.lineWidth = mPanWidth
    context.fillStyle = '#000000'
    context.strokeStyle = '#000000'
    context.lineCap = 'round'
    context.lineJoin = 'miter'

    canvas.addEventListener('touchmove', touchMove, false)
    canvas.addEventListener('touchstart', touchStart, false)
    canvas.addEventListener('touchend', touchEnd, false)

    function preImage (url, callback) {
      var img = new Image() //创建一个Image对象,实现图片的预下载
      img.src = url

      if ((url.indexOf('null') <= 0) && (url.length > 50)) //判断图片非空
      {
        if (img.complete) {
          //如果图片已经存在于浏览器缓存,直接调用回调函数
          callback.call(img)
          return // 直接返回,不用再处理onload事件
        }

        img.onload = function () { //图片下载完毕时异步调用callback函数。
          callback.call(img)//将回调函数的this替换为Image对象
        }
      }
    }

    setInterval(draw, 20)
  }

  function drawLine (startPoint, endPoint) {
    context.lineWidth = mPanWidth
    context.beginPath()
    context.moveTo(startPoint.x, startPoint.y)
    context.lineTo(endPoint.x, endPoint.y)
    context.stroke()
    context.closePath()
    mStartPoint = endPoint
  }

  function touchStart (event) {
    event.preventDefault()
    HAS_IMAGE = true
    for (var i = 0; i < event.touches.length; i++) {
      checkEffectivePoint(event.touches[i].pageX - mCanvasOffsetLeft, event.touches[i].pageY - mCanvasOffsetTop)
      paths.push({
        id: event.touches[i].identifier,
        points: [{
          x: event.touches[i].pageX - mCanvasOffsetLeft,
          y: event.touches[i].pageY - mCanvasOffsetTop,
          timestamp: new Date().getTime(),
          drawn: false,
        }],
        complete: false,
      })
    }
  }

  function touchEnd (event) {
    event.preventDefault()
    for (var i = 0; i < event.changedTouches.length; i++) {
      for (var j = 0; j < paths.length; j++) {
        if (paths[j].id == event.changedTouches[i].identifier) {
          paths[j].id = null
          paths[j].complete = true
        }
      }
    }
  }

  function touchMove (event) {
    event.preventDefault()

    for (var i = 0; i < event.touches.length; i++) {
      for (var j = 0; j < paths.length; j++) {
        if (paths[j].id == event.touches[i].identifier) {
          checkEffectivePoint(event.touches[i].pageX - mCanvasOffsetLeft, event.touches[i].pageY - mCanvasOffsetTop)
          paths[j].points.push({
            x: event.touches[i].pageX - mCanvasOffsetLeft,
            y: event.touches[i].pageY - mCanvasOffsetTop,
            drawn: false,
            timestamp: new Date().getTime(),
          })
        }
      }
    }
  }

  function draw () {
    var DRAW_TIME_THRESHOLD = 10
    var start = new Date()

    context.lineWidth = mPanWidth
    for (var i = 0; i < paths.length
    && new Date() - start < DRAW_TIME_THRESHOLD; i++) {
      var firstPoint = true
      var points = paths[i].points

      if (points.length > 1 && points[points.length - 1].drawn == false) {

        context.beginPath()

        for (var j = 1; j < points.length; j++) {
          if (firstPoint && points[j].drawn == false) {
            firstPoint = false

            context.moveTo(points[j - 1].x, points[j - 1].y)
            points[j - 1].drawn = true

            context.lineTo(points[j].x, points[j].y)
          } else if (points[j].drawn == false) {
            context.lineTo(points[j].x, points[j].y)
          }
          points[j].drawn = true
        }

        context.stroke()
        context.closePath()
      } else if (paths[i].complete && points[0].drawn == false) {
        context.arc(points[0].x, points[0].y, context.lineWidth / 2, 0,
          Math.PI * 2, false)
        context.closePath()
        context.fill()

        points[0].drawn = true
      }
    }
  }

  /**
   * 重新计算手写签名的有效区域
   * @param x
   * @param y
   */
  function checkEffectivePoint (x, y) {
    if (x >= 0 && x <= mCanvasWidth) {
      if (x - mPanWidth < mEffectivePoint.minX || mEffectivePoint.minX === -1) {
        mEffectivePoint.minX = x - mPanWidth
        if (mEffectivePoint.minX < 0) {
          mEffectivePoint.minX = 0
        }
      }
      if (x + mPanWidth > mEffectivePoint.maxX || mEffectivePoint.maxX === -1) {
        mEffectivePoint.maxX = x + mPanWidth
        if (mEffectivePoint.maxX > mCanvasWidth) {
          mEffectivePoint.maxX = mCanvasWidth
        }
      }
    }
    if (y >= 0 && y <= mCanvasHeight) {
      if (y - mPanWidth < mEffectivePoint.minY || mEffectivePoint.minY === -1) {
        mEffectivePoint.minY = y - mPanWidth
        if (mEffectivePoint.minY < 0) {
          mEffectivePoint.minY = 0
        }
      }
      if (y + mPanWidth > mEffectivePoint.maxY || mEffectivePoint.maxY === -1) {
        mEffectivePoint.maxY = y + mPanWidth
        if (mEffectivePoint.maxY > mCanvasHeight) {
          mEffectivePoint.maxY = mCanvasHeight
        }
      }
    }
  }

  /**
   * 保存图片
   */
  function save () {
    var image = new Image()
    // var imgSrc = canvas.toDataURL("image/png");
    image.src = document.getElementById('myCanvas').toDataURL('image/png')
    if (HAS_IMAGE) {
      getImageByEffectiveArea(image, function (img) {
        if (window.ReactNativeWebView) {
          // react-native的webview修改为react-native-webview组件,需要使用一下方式进行通信
          window.ReactNativeWebView.postMessage(img)
          initEffectivePoint()
        } else if (window.postMessage) {
          window.postMessage(img)
          initEffectivePoint()
        } else {
          alert('浏览器暂不支持此操作')
        }
      })
    } else {
      /**
       * 点击保存签章判断,画布是否有内容
       * 如果画布为空,参数为null
       * */
      window.ReactNativeWebView.postMessage('null')
    }
  }
  /**
   * 根据手写区域裁剪图片
   */
  function getImageByEffectiveArea (imageSource, callback) {
    var effectivePoint = {
      minX: mEffectivePoint.minX,
      maxX: mEffectivePoint.maxX === mEffectivePoint.minX ? mEffectivePoint.minX + 10 : mEffectivePoint.maxX,
      minY: mEffectivePoint.minY,
      maxY: mEffectivePoint.maxY === mEffectivePoint.minX ? mEffectivePoint.maxY + 10 : mEffectivePoint.maxY,
    }
    canvas2 = document.getElementById('idStampAdjustCanvas')
    context2 = canvas2.getContext('2d')
    //先清除
    context2.clearRect(0, 0, canvas2.width, canvas2.height)
    var width = effectivePoint.maxX - effectivePoint.minX
    var height = effectivePoint.maxY - effectivePoint.minY
    canvas2.width = stampMaxX
    canvas2.height = stampMaxY
    loadImage(imageSource.src, function () {
      context2 = canvas2.getContext('2d')
      var drawStartPoint = getDrawArea(width, height)
      console.log(width, height, drawStartPoint)
      context2.drawImage(imageSource,
        effectivePoint.minX, effectivePoint.minY, width, height,
        drawStartPoint.startX, drawStartPoint.startY,
        drawStartPoint.width, drawStartPoint.height)
      callback(canvas2.toDataURL('image/png'))
    })
  }

  /**
   *
   * 根据原始图片的宽高,在限定尺寸的canvas中配置好绘图起始点坐标和宽高,让图片能够不变形地完全绘制在限定尺寸的canvas中
   * @param width 真实手写的宽
   * @param height  真实手写区域的高度
   * canvas的尺寸(maxX=400,maxY=160)
   * 1-原始图片width<maxX
   *   1-1 height<maxY
   *   1-2 height>=maxY
   * 2-原始图片width>=maxX
   *   2-1 width/maxX > height/maxY (宽度的比例大于高度的比例)
   *   2-2 width/maxX <= height/maxY
   *
   * @return {
   
   {width: number, startY: number, startX: number, height: number}}
   */
  function getDrawArea (width, height) {
    var drawStartPoint = {
      startX: 0,  //重绘起点的x坐标
      startY: 0,  //重绘起点的y坐标
      width: stampMaxX, //重绘图片的宽
      height: stampMaxY,  //重绘图片的高
    }
    if (width < stampMaxX) {
      if (height < stampMaxY) {

        drawStartPoint = {
          startX: (stampMaxX - width) / 2,
          startY: (stampMaxY - height) / 2,
          width: width,
          height: height,
        }
        console.log(111111)
      } else {
        var scale = stampMaxY / height
        drawStartPoint = {
          startX: (stampMaxX - width * scale) / 2,
          startY: 0,
          width: width * scale,
          height: stampMaxY,
        }
        console.log(222222, scale)
      }
    } else {
      var scaleWidth = stampMaxX / width
      var scaleHeight = stampMaxY / height
      var scale = scaleWidth
      if (width / height > stampMaxX / stampMaxY) {
        // 说明图片相对比例,缩放后,width更小,所以以height为基准边
        scale = scaleWidth
        drawStartPoint = {
          startX: 0,
          startY: (stampMaxY - height * scale) / 2,
          width: stampMaxX,
          height: height * (stampMaxX / width),
        }
      } else {
        scale = scaleHeight
        drawStartPoint = {
          startX: (stampMaxX - width * scale) / 2,
          startY: 0,
          width: width * (stampMaxY / height),
          height: stampMaxY,
        }
      }
    }
    return drawStartPoint
  }

  function loadImage (url, callback) {
    var img = new Image() // 创建一个Image对象,实现图片的预下载
    img.src = url

    if (img.complete) {
      // 如果图片已经存在于浏览器缓存,直接调用回调函数
      callback.call(img)
    }

    img.onload = function () { // 图片下载完毕时异步调用callback函数。
      callback.call(img)// 将回调函数的this替换为Image对象
    }
  }

  function initEffectivePoint () {
    mEffectivePoint = {
      minX: -1,
      minY: -1,
      maxX: -1,
      maxY: -1,
    }
  }

  setTimeout(function () {
    // 延时进行init,需要等页面渲染完成后再初始化canvas
    init()
  }, 600)
</script>
</body>

</html>

猜你喜欢

转载自blog.csdn.net/u010899138/article/details/108204712
今日推荐