【问题标题】:How to resize html canvas element?如何调整html画布元素的大小?
【发布时间】:2010-09-24 18:26:13
【问题描述】:

我在 html 中静态定义了一个具有宽度和高度的画布元素。如果我尝试使用 JavaScript 动态调整它的大小(设置新的宽度和高度 - 在画布的属性上或通过样式属性)我在 Firefox 中收到以下错误:

未捕获的异常:[异常...“对 WrappedNative 原型对象的非法操作”nsresult:“0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)”位置:“JS 框架 :: file:///home/russh/Desktop/test.html :: onclick :: line 1" 数据:无]

是否可以调整这个元素的大小,或者我必须销毁它并动态创建一个新元素?

【问题讨论】:

  • 实际上,错误消息看起来好像您尝试直接更改HTMLCanvasElement.prototypewidthheight 属性。我不知道这是怎么意外做到的。

标签: javascript html canvas dhtml


【解决方案1】:
<div id="canvasdiv" style="margin: 5px; height: 100%; width: 100%;">
    <canvas id="mycanvas" style="border: 1px solid red;"></canvas>
</div>
<script>
$(function(){
    InitContext();
});
function InitContext()
{
var $canvasDiv = $('#canvasdiv');

var canvas = document.getElementById("mycanvas");
canvas.height = $canvasDiv.innerHeight();
canvas.width = $canvasDiv.innerWidth();
}
</script>

【讨论】:

    【解决方案2】:

    使用原型可能很麻烦,从错误的_PROTO 部分来看,您的错误似乎是由HTMLCanvasElement.prototype.width 引起的,可能是为了一次调整所有画布的大小。

    作为建议,如果您尝试一次调整多个画布的大小,您可以尝试:

    <canvas></canvas>
    <canvas></canvas>
    <canvas></canvas>
    <script type="text/javascript">
        ...
    </script>
    

    在 JavaScript 中,不要调用原型,试试这个:

    $$ = function(){
        return document.querySelectorAll.apply(document,arguments);
    }
    for(var i in $$('canvas')){
        canvas = $$('canvas')[i];
        canvas.width = canvas.width+100;
        canvas.height = canvas.height+100;
    }
    

    这将通过将 100 像素添加到它们的大小来调整所有画布的大小,如 this example 中所示


    希望这有帮助。

    【讨论】:

      【解决方案3】:

      请注意,如果您的画布是静态声明的,您应该使用 widthheight 属性,而不是样式,例如。这将起作用:

      <canvas id="c" height="100" width="100" style="border:1px"></canvas>
      <script>
          document.getElementById('c').width = 200;
      </script>
      

      但这将工作:

      <canvas id="c" style="width: 100px; height: 100px; border:1px"></canvas>
      <script>
          document.getElementById('c').width = 200;
      </script>
      

      【讨论】:

        【解决方案4】:

        这是我试图给出更完整答案的努力(基于@john 的答案)。

        我遇到的最初问题是更改画布节点的宽度和高度(使用样式),导致内容只是“缩放”或“缩小”。这不是预期的效果。

        假设您想在 100 x 100 像素的画布上绘制两个任意大小的矩形。

        <canvas width="100" height="100"></canvas>
        

        为确保矩形不会超过画布的大小并因此不可见,您需要确保画布足够大。

        var $canvas = $('canvas'),
            oldCanvas,
            context = $canvas[0].getContext('2d');
        
        function drawRects(x, y, width, height)
        {
          if (($canvas.width() < x+width) || $canvas.height() < y+height)
          {
            oldCanvas = $canvas[0].toDataURL("image/png")
            $canvas[0].width = x+width;
            $canvas[0].height = y+height;
        
            var img = new Image();
            img.src = oldCanvas;
            img.onload = function (){
              context.drawImage(img, 0, 0);
            };
          }
          context.strokeRect(x, y, width, height);
        }
        
        
        drawRects(5,5, 10, 10);
        drawRects(15,15, 20, 20);
        drawRects(35,35, 40, 40);
        drawRects(75, 75, 80, 80);
        

        最后,这是 jsfiddle:http://jsfiddle.net/Rka6D/4/

        【讨论】:

          【解决方案5】:

          你没有发布你的代码,我怀疑你做错了什么。可以通过使用数字分配宽度和高度属性来更改大小:

          canvasNode.width  = 200; // in pixels
          canvasNode.height = 100; // in pixels
          

          至少它对我有用。确保不要分配字符串(例如,“2cm”、“3in”或“2.5px”),并且不要混淆样式。

          实际上,这是一个公开的知识——您可以在the HTML canvas spec 中阅读所有相关信息——它非常小而且信息量非常大。这是整个 DOM 接口:

          interface HTMLCanvasElement : HTMLElement {
                     attribute unsigned long width;
                     attribute unsigned long height;
          
            DOMString toDataURL();
            DOMString toDataURL(in DOMString type, [Variadic] in any args);
          
            DOMObject getContext(in DOMString contextId);
          };
          

          如您所见,它定义了两个属性widthheight,它们都是unsigned long

          【讨论】:

          • 注意:当您更改画布大小时,它似乎会清除画布(至少在 chrome 中)。
          • 是的。我同意。有没有办法在调整画布大小的同时调整画布内部图像的大小(缩放)?
          • @Alexis 改变它的风格会改变它的缩放比例。所以 canvas.style.width = "700px";会改变它的缩放比例,但 canvas.width = 700;不会。
          • @JosephLennox 知道这非常有用。提到这一点,你为我节省了大量的精力。
          • 是的,谢谢,@JosephLennox。在 jquery 中, $('#canvas').width(500) 将重新缩放,而 $('#canvas')[0].width = 500 不会重新缩放。我正在做前者,如果没有你的评论,我会永远解决它。
          【解决方案6】:

          我刚刚遇到了和你一样的问题,但是发现了 toDataURL 方法,它被证明很有用。

          它的要点是将你当前的画布变成一个 dataURL,改变你的画布大小,然后从你保存的 dataURL 中将你原来的内容重新绘制到画布中。

          这是我的代码:

          var oldCanvas = canvas.toDataURL("image/png");
          var img = new Image();
          img.src = oldCanvas;
          img.onload = function (){
              canvas.height += 100;
              ctx.drawImage(img, 0, 0);
          }
          

          【讨论】:

          • ctx.getImageData() 和 ctx.putImageData() 重量更轻,专为这项任务而设计。
          • @fuzzyTew 我很确定使用getImageData()putImageData() 会很有效,但会逐像素复制,因此不会缩放旧图像数据,而使用drawImage() 将允许用于缩放。
          • 为什么使用toDataUrl?这会导致不必要的数据转换 (raw=>png)。您可以改用两次drawImage
          【解决方案7】:

          这刚刚对我有用:

          <canvas id="c" height="100" width="100" style="border:1px solid red"></canvas>
          <script>
          var c = document.getElementById('c');
          alert(c.height + ' ' + c.width);
          c.height = 200;
          c.width = 200;
          alert(c.height + ' ' + c.width);
          </script>
          

          【讨论】:

            猜你喜欢
            • 2012-01-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多