javascript - 具有固定线宽的响应式 Canvas

标签 javascript css html canvas

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

我用 CSS 让它响应

    #myCanvas{
        width: 80%;
    }

,所以笔画被缩放了。

我找到的唯一解决方案是使用 Canvas 的宽度属性与其实际宽度之间的比例来获取 lineWidth 的值。 为了应用它,我在调整大小时清除并绘制 Canvas 。

    <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>

这是我的第一个 Canvas ,我认为有一种更简单的方法可以使 lineWidth 固定(不是每次调整大小时都清除和绘制),但我找不到它。

有个类似问题的问题

html5 canvas prevent linewidth scaling 但是使用方法 scale(),所以我不能使用该解决方案。

最佳答案

无法获得真实世界的 Canvas 细节尺寸(例如毫米或英寸),因此您必须以像素为单位。

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

您需要根据您期望的最低分辨率来定义线宽,这当然是合理的,并且随着 Canvas 分辨率相对于所选理想分辨率的变化调整该宽度。

如果您在 x 和 y 方向上按不同的量缩放图表,则必须使用 ctx.scalectx.setTransform 方法。正如您所说,您不想这样做,我会假设您的缩放比例始终为正方形。

因此我们可以选择可接受的最低分辨率。假设 Canvas 的宽度或高度为 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;

您可能希望将该尺寸限制为最小的 Canvas 尺寸。您可以使用 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;

您还可以将对 Angular 线视为调整因素,它将结合 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 像素时,您可能希望限制线条的下限以阻止奇怪的伪像。

使用对 Angular 线设置下限

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;

如果 Canvas 对 Angular 线分辨率低于 512,这将创建一个不会低于 1 像素的响应线宽。

您使用的方法取决于您。试试看,看看您最喜欢什么。我选择“512”的 NATIVE_RES 也是任意的,可以是任何你想要的。您只需试验这些值和方法,看看您最喜欢哪一个。

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

希望这对您有所帮助。

关于javascript - 具有固定线宽的响应式 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35576760/

相关文章:

php - jquery 自动完成选项不起作用

c# - 如何让 CrystalReportViewer 在屏幕上居中?

html - 努力摆脱模板上的黑框

html - 编织多个html文件rstudio

javascript - 如何使用 querySelectorAll javascript 访问具有相同 id 的第二个 div?

javascript - 带夹子的两个区域之间的 Canvas 部分

javascript - GSAP 动画 : scale vs height and width

javascript - 用/transition设置元素的字体大小时,如何从中心调整大小

php - Newsfeed Div 在第 2 页关闭

css - 如何向 HTML5 表格添加滚动条?