【问题标题】:JS: Why do I have to click my canvas-resizing-button twice? [duplicate]JS:为什么我必须点击我的画布调整大小按钮两次? [复制]
【发布时间】:2019-04-27 00:22:15
【问题描述】:

我有一个大小为 392x392 的 HTML5 画布,我可以在其中绘制一些东西。 我正在尝试将该画布的内容调整为另一个大小为 28x28 像素的画布。

以下方法工作正常,除了我必须单击“调整图像大小”按钮两次 - 为什么会这样,我该如何解决?

function resize() {
  //get the base64 string of the Image
  var dataURL = canvas.toDataURL();
  //draw the base64 string into a 28x28 canvas (for resizing)
  var img = new Image();
  img.src = dataURL;
  resizedCtx.drawImage(img, 0, 0, 28, 28);
}
<canvas id="canvas" width="392" height="392" style="border:1px solid;"></canvas>
<br>
<br>
<input type="button" value="resize image" id="btn" size="30" onclick="resize()">
<br>
<br>
<canvas id="resizedCanvas" width="28" height="28" style="border:1px solid;"></canvas>

<script>
  canvas = document.getElementById('canvas');
  ctx = canvas.getContext("2d");

  resizedCanvas = document.getElementById('resizedCanvas');
  resizedCtx = resizedCanvas.getContext('2d');
    
  ctx.fillStyle = "red";
  ctx.fillRect(20, 20, 280, 280);
</script>

code in jsfiddle.net

提前致谢!

【问题讨论】:

  • 重要提示: 甚至不要通过 img 来调整画布大小。只需将画布直接绘制在调整大小的画布上即可。

标签: javascript html canvas image-resizing double-click


【解决方案1】:

在您尝试drawImage 时,您的Image 对象尚未完成其内容的加载。您必须等到图像触发load 事件。在该事件触发之前,图像不会呈现为任何内容,因为它尚未完成从其src URL 加载数据。

您的代码在第二次点击后工作,因为浏览器在第一次点击后缓存了与特定 src 关联的图像数据,因此它可以在第二次点击时立即呈现。

只需将您的resizedCtx.drawImage(...) 调用放在一个回调函数中,该回调函数将在load 事件为img 触发后按时间顺序运行。

function resize() {
  //get the base64 string of the Image
  var dataURL = canvas.toDataURL();
  //draw the base64 string into a 28x28 canvas (for resizing)
  var img = new Image();
  img.src = dataURL;
  img.addEventListener("load", function() {
      resizedCtx.drawImage(img, 0, 0, 28, 28);
  });
}

function resize() {
//get the base64 string of the Image
var dataURL = canvas.toDataURL();
//draw the base64 string into a 28x28 canvas (for resizing)
var img = new Image();
  img.src = dataURL;
  img.addEventListener("load", function() {
    resizedCtx.drawImage(img, 0, 0, 28, 28);
  });
}
<canvas id="canvas" width="392" height="392" style="border:1px solid;"></canvas>
<br><br>
<input type="button" value="resize image" id="btn" size="30" onclick="resize()">
<br><br>
<canvas id="resizedCanvas" width="28" height="28" style="border:1px solid;"></canvas>
<script>
  canvas = document.getElementById('canvas');
  ctx = canvas.getContext("2d");
  resizedCanvas = document.getElementById('resizedCanvas');
  resizedCtx = resizedCanvas.getContext('2d');
  ctx.fillStyle = "red";
  ctx.fillRect(20, 20, 280, 280);

</script>

【讨论】:

  • 很好的答案! +1 我希望您不介意,但我添加了一个片段以显示您的更改按预期工作。我将它设置为默认隐藏,这样它就不会占用太多空间并使您的帖子看起来很乱。
  • 非常感谢!这很好用!
【解决方案2】:

你可以用这个替换你的JS代码

function resize() {
    var myCanvas = document.getElementById('resizedCanvas');
    var ctx = myCanvas.getContext('2d');
    var img = document.getElementById('canvas');
    ctx.drawImage(img,0,0);
}

Canvas 将接受另一个画布内容。您现在所能做的就是操纵变量图像来改变它的位置,然后就可以了。

【讨论】:

    【解决方案3】:

    你可以在 other 中使用 img.onload 来加载图片,然后执行该功能 function resize() { //get the base64 string of the Image var dataURL = canvas.toDataURL(); //draw the base64 string into a 28x28 canvas (for resizing) var img = new Image(); img.src = dataURL; img.onload = function () { resizedCtx.drawImage(img, 0, 0, 28, 28); } }

    只需将输入标签替换为此处的标签即可解决问题。

    function resize() {
      //get the base64 string of the Image
      var dataURL = canvas.toDataURL();
      //draw the base64 string into a 28x28 canvas (for resizing)
      var img = new Image();
      img.src = dataURL;
      img.onload = function () { 
    		resizedCtx.drawImage(img, 0, 0, 28, 28);
        }
    }
    <canvas id="canvas" width="392" height="392" style="border:1px solid;"></canvas>
    <br>
    <br>
    <input type="button" value="resize image" id="btn" size="30" onclick="resize()">
    <br>
    <br>
    <canvas id="resizedCanvas" width="28" height="28" style="border:1px solid;"></canvas>
    
    <script>
    	canvas = document.getElementById('canvas');
      ctx = canvas.getContext("2d");
    
      resizedCanvas = document.getElementById('resizedCanvas');
      resizedCtx = resizedCanvas.getContext('2d');
        
      ctx.fillStyle = "red";
      ctx.fillRect(20, 20, 280, 280);
    </script>

    【讨论】:

      【解决方案4】:

      function resize() {
        //get the base64 string of the Image
        var dataURL = canvas.toDataURL();
        //draw the base64 string into a 28x28 canvas (for resizing)
        var img = new Image();
        img.onload = function() {
          resizedCtx.drawImage(img, 0, 0, 28, 28);
        };
        img.src = dataURL;
      }
      <canvas id="canvas" width="392" height="392" style="border:1px solid;"></canvas>
      <br>
      <br>
      <input type="button" value="resize image" id="btn" size="30" onclick="resize()">
      <br>
      <br>
      <canvas id="resizedCanvas" width="28" height="28" style="border:1px solid;"></canvas>
      
      <script>
        canvas = document.getElementById('canvas');
        ctx = canvas.getContext("2d");
        resizedCanvas = document.getElementById('resizedCanvas');
        resizedCtx = resizedCanvas.getContext('2d');
        ctx.fillStyle = "red";
        ctx.fillRect(20, 20, 280, 280);
      </script>

      只需将 resizedCanvas 和 resizedCtx 行放在 resize 函数中即可。

      【讨论】:

      • 感谢您的回答,但这并没有改变任何事情......
      • 嗨!答案已更新。
      • 抱歉,我还是要点击两次。
      • 不知道发生了什么。它发生在单击让我检查。对不起
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 2014-05-06
      • 2021-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多