如何防止一些帆布线圈溢出?
示例案例:
以下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();
给出了这个画布输出
在这些示例中,两条线的末端Y-coord都是正的,但第二条线似乎被解释为-Inf
。似乎在内部将值转换为某些unsigned int
,使得某些位值被视为符号,但我没有找到关于它的明确文档。
我想要的是正确绘制线条,以防止画布中带有coords的画线。 我知道有一种方法可以做一些线性代数(计算线和边界之间的交点),但我想知道是否有一些更简单的方法。
答案 0 :(得分:2)
moveTo
和lineTo
参数的数据类型为unrestricted double
。你可以看到它的32位浮点数,大概是签名的。这意味着通过规范,应该没有溢出,错误取决于浏览器的实现。
我的测试证实了这一点,因为Firefox,Google Chrome或Opera都没有提供任何内容,表明未定义的可疑行为。如果坐标无效,我预计会出错。如果我使用较小的坐标(300),它们都提供了这个结果(裁剪,框架):
然后我执行了一些测试,最后一个可以渲染的数字是:
Math.pow(2,31)-Math.pow(2,6)-1 = 2147483583
因此,如果你真的试图解决问题而不是出于好奇心,我建议采用以下两种解决方案之一:
制作辅助功能以限制坐标。
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));
覆盖实际的画布方法以解决问题
如果您感觉很难,您可以继续使用画布上下文方法。但是很多人会建议你这样做,因为改变内置的东西经常会导致难以追查的神秘错误。有了这个警告:
(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 = 500
和canvas.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;
}
}