帆布绳索溢出?

时间:2015-10-18 17:19:27

标签: javascript canvas

如何防止一些帆布线圈溢出?

示例案例:

以下javascript:

 var canvas = document.getElementById("canvas");
 var context = canvas.getContext("2d");
 canvas.width = 500;
 canvas.height = 500;
 context.strokeStyle = "#000";
 context.beginPath();
 // line from (100, 100) to (100,999999999999.9)
 context.moveTo(100.0, 100.0);
 context.lineTo(100.0, 999999999999.9); 
 // line from (200, 200) to (200,9999999999999.9)
 context.moveTo(200.0, 100.0);
 context.lineTo(200.0, 9999999999999.9);
 context.stroke();

给出了这个画布输出

Output

在这些示例中,两条线的末端Y-coord都是正的,但第二条线似乎被解释为-Inf。似乎在内部将值转换为某些unsigned int,使得某些位值被视为符号,但我没有找到关于它的明确文档。

更新

我想要的是正确绘制线条,以防止画布中带有coords的画线。 我知道有一种方法可以做一些线性代数(计算线和边界之间的交点),但我想知道是否有一些更简单的方法。

2 个答案:

答案 0 :(得分:2)

tl;dr Jsfiddle

moveTolineTo参数的数据类型为unrestricted double。你可以看到它的32位浮点数,大概是签名的。这意味着通过规范,应该没有溢出,错误取决于浏览器的实现。

我的测试证实了这一点,因为Firefox,Google Chrome或Opera都没有提供任何内容,表明未定义的可疑行为。如果坐标无效,我预计会出错。如果我使用较小的坐标(300),它们都提供了这个结果(裁剪,框架):

image description

然后我执行了一些测试,最后一个可以渲染的数字是:

Math.pow(2,31)-Math.pow(2,6)-1 = 2147483583

因此,如果你真的试图解决问题而不是出于好奇心,我建议采用以下两种解决方案之一:

  1. 制作辅助功能以限制坐标。

      var max = 2147483583;
      var min = -2147483583;
      function safeCoordinate(number) {
        if(number>max)
          return max;
        if(number<min)
          return min;
        return number;
      }
    

    然后打电话:

    context.lineTo(safeCoordinate(x), safeCoordinate(y)); 
    
  2. 覆盖实际的画布方法以解决问题

    如果您感觉很难,您可以继续使用画布上下文方法。但是很多人会建议你这样做,因为改变内置的东西经常会导致难以追查的神秘错误。有了这个警告:

    (function(max, min, context_proto) {
              // Override move to
              var old_moveTo =context_proto.moveTo;
              context_proto.moveTo = function(x, y) {
                  return old_moveTo.call(this, safeCoordinate(x), safeCoordinate(y));   
              }
              var old_lineTo =context_proto.lineTo;
              context_proto.lineTo = function(x, y) {
                  return old_lineTo.call(this, safeCoordinate(x), safeCoordinate(y));   
              }
              // Override more methods if needed!
                ...
              // Our helper function
              function safeCoordinate(number) {
                if(number>max)
                  return max;
                if(number<min)
                  return min;
                return number;
              }  
    })(2147483583,-2147483583, CanvasRenderingContext2D.prototype);
    

答案 1 :(得分:0)

假设我们有canvas.height = 500canvas.width = 500,我们希望防止坐标在0 to 500范围内。我们可以使用这些属性在使用function()调用上下文时设置范围。

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
context.strokeStyle = "#000";
letsDraw(100, 200, 800, 300); //Returns Alert Error


function letsDraw(moveToX, moveToY, lineToX, lineToY){
     if((moveToX<canvas.width && moveToX>0) && (moveToY<canvas.height && moveToY>0)){
       context.beginPath();
       context.moveTo(moveToX, moveToY);
       if((lineToX<canvas.width && lineToX>0) && (lineToY<canvas.height && lineToY>0)){
         context.lineTo(lineToX, lineToY);
         context.stroke();
       } else {
         alert("Range outside Canvas");
         return false;
       }
     } else {
       alert("Range outside Canvas");
       return false;
     }
}