我正在用画布绘制折线图。图表是响应式的,但线条必须有固定的宽度。
我用css
做了回应 #myCanvas{
width: 80%;
}
,因此笔划缩放。
我找到的唯一解决方案是使用画布的width属性与其实际宽度之间的比例来获取lineWidth的值。 要应用它,我清除并在调整大小时绘制画布。
<canvas id="myCanvas" width="510" height="210"></canvas>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw(){
var canvasattrwidth = $('#myCanvas').attr('width');
var canvasrealwidth = $('#myCanvas').width();
// n sets the line width
var n = 4;
var widthStroke = n * (canvasattrwidth / canvasrealwidth) ;
ctx.lineWidth = widthStroke;
ctx.beginPath();
ctx.moveTo( 0 , 10 );
ctx.lineTo( 200 , 100 );
ctx.stroke();
}
$(window).on('resize', function(){
ctx.clearRect(0, 0, c.width, c.height);
draw();
});
draw();
</script>
这是我的第一个画布,我认为有一种更简单的方法可以修复lineWidth(不是每次调整时都清除和绘制),但我找不到它。
有类似问题的问题
html5 canvas prevent linewidth scaling 但是使用方法scale(),所以我无法使用该解决方案。
答案 0 :(得分:3)
无法获得画布细节的真实世界尺寸,例如毫米或英寸,因此您必须以像素为单位进行操作。
随着画布分辨率降低,行的像素宽度也需要减小。线宽的限制属性是像素。渲染比像素窄的线只会通过降低不透明度来近似较窄线的外观(这是自动完成的)
您需要根据您期望的最低分辨率定义线宽,当然还要根据画布分辨率相对于所选理想分辨率的变化调整宽度。
如果您在x和y方向上按不同的比例缩放图表,则必须使用ctx.scale
或ctx.setTransform
方法。正如你所说,你不想这样做,我会假设你的缩放总是方方面面。
因此我们可以选择最低的可接受分辨率。假设画布的宽度或高度为512像素,并为该分辨率选择lineWidth
像素。
因此我们可以创建两个常量
const NATIVE_RES = 512; // the minimum resolution we reasonably expect
const LINE_WIDTH = 1; // pixel width of the line at that resolution
// Note I Capitalize constants, This is non standard in Javascript
然后计算实际线宽只是实际的canvas.width
除以NATIVE_RES
,然后将该结果乘以LINE_WIDTH
。
var actualLineWidth = LINE_WIDTH * (canvas.width / NATIVE_RES);
ctx.lineWidth = actualLineWidth;
您可能希望将该大小限制为最小的画布尺寸。您可以使用Math.min
执行此操作,也可以使用Math.max
对于最小尺寸。
var actualLineWidth = LINE_WIDTH * (Math.min(canvas.width, canvas.height) / NATIVE_RES);
ctx.lineWidth = actualLineWidth;
最大尺寸
var actualLineWidth = LINE_WIDTH * (Math.max(canvas.width, canvas.height) / NATIVE_RES);
ctx.lineWidth = actualLineWidth;
您还可以将对角线视为包含x和y尺寸最佳值的调整因子。
// get the diagonal resolution
var diagonalRes = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height)
var actualLineWidth = LINE_WIDTH * (diagonalRes / NATIVE_RES);
ctx.lineWidth = actualLineWidth;
最后,当线条小于1像素时,您可能希望限制线条的较低范围以阻止奇怪的伪影。
使用对角线设置下限
var diagonalRes = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height)
var actualLineWidth = Math.max(1, LINE_WIDTH * (diagonalRes / NATIVE_RES));
ctx.lineWidth = actualLineWidth;
如果画布对角线分辨率低于512,这将创建一个不会低于1像素的响应线宽。
您使用的方法取决于您。尝试一下,看看你最喜欢的。 NATIVE_RES
我选择的“512”也是任意的,可以是你想要的。您只需要尝试使用值和方法来查看您最喜欢的值。
如果您的缩放方面正在改变,那么有一种完全不同的技术可以解决这个问题,我将留下另一个问题。
希望这有所帮助。