具有固定线宽的响应式画布

时间:2016-02-23 11:47:31

标签: javascript html css html5 canvas

我正在用画布绘制折线图。图表是响应式的,但线条必须有固定的宽度。

我用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(),所以我无法使用该解决方案。

1 个答案:

答案 0 :(得分:3)

无法获得画布细节的真实世界尺寸,例如毫米或英寸,因此您必须以像素为单位进行操作。

随着画布分辨率降低,行的像素宽度也需要减小。线宽的限制属性是像素。渲染比像素窄的线只会通过降低不透明度来近似较窄线的外观(这是自动完成的)

您需要根据您期望的最低分辨率定义线宽,当然还要根据画布分辨率相对于所选理想分辨率的变化调整宽度。

如果您在x和y方向上按不同的比例缩放图表,则必须使用ctx.scalectx.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”也是任意的,可以是你想要的。您只需要尝试使用值和方法来查看您最喜欢的值。

如果您的缩放方面正在改变,那么有一种完全不同的技术可以解决这个问题,我将留下另一个问题。

希望这有所帮助。