使用 Canvas 平滑随机线

发布于 2024-10-31 07:56:03 字数 1229 浏览 1 评论 0原文

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.canvas.width  = window.innerWidth;
context.canvas.height  = window.innerHeight;
var x1 = Math.random()*context.canvas.width;
var y1 = Math.random()*context.canvas.height;
var xdir = 0; var ydir = 0;
context.beginPath();

setInterval(function(){
    for (var i = 0; i < 10; i++) {
        randx = Math.random(); randy = Math.random();

        if (randx > 0.95) {
            if (xdir < 0) xdir = (xdir+((Math.random()*1.5) - 1))/2;
            else if (xdir > 0) xdir = (xdir+((Math.random()*1.5) - 0.5))/2;
            else xdir = (Math.random()*1.5) - 0.75;
        }

        if (randy > 0.95) {
            if (ydir < 0) ydir = (ydir+((Math.random()*1.5) - 1))/2;
            else if (ydir > 0) ydir = (ydir+((Math.random()*1.5) - 0.5))/2;
            else ydir = (Math.random()*1.5) - 0.75;
        }

        context.lineTo(x1+xdir, y1+ydir);
        context.stroke();

        x1 = x1+xdir;
        y1 = y1+ydir;
    }
},50);

这是我的随机行脚本,但我的行真的很难看: https://i.sstatic.net/YZT2o .png

有没有更好的方法使用canvas实现平滑的线条?

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.canvas.width  = window.innerWidth;
context.canvas.height  = window.innerHeight;
var x1 = Math.random()*context.canvas.width;
var y1 = Math.random()*context.canvas.height;
var xdir = 0; var ydir = 0;
context.beginPath();

setInterval(function(){
    for (var i = 0; i < 10; i++) {
        randx = Math.random(); randy = Math.random();

        if (randx > 0.95) {
            if (xdir < 0) xdir = (xdir+((Math.random()*1.5) - 1))/2;
            else if (xdir > 0) xdir = (xdir+((Math.random()*1.5) - 0.5))/2;
            else xdir = (Math.random()*1.5) - 0.75;
        }

        if (randy > 0.95) {
            if (ydir < 0) ydir = (ydir+((Math.random()*1.5) - 1))/2;
            else if (ydir > 0) ydir = (ydir+((Math.random()*1.5) - 0.5))/2;
            else ydir = (Math.random()*1.5) - 0.75;
        }

        context.lineTo(x1+xdir, y1+ydir);
        context.stroke();

        x1 = x1+xdir;
        y1 = y1+ydir;
    }
},50);

This is my random line script, but my lines are really ugly: https://i.sstatic.net/YZT2o.png

Is there any better way for achieving a smooth line using canvas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

二手情话 2024-11-07 07:56:03

HTML5 Canvas 上的线条在所有浏览器/操作系统上都可以很好地抗锯齿(据我所知)。但是,在每循环 10 笔画的更新回调中,您既不是 清除画布清除您的路径,因此您每秒在其自身之上绘制相同的路径 200 次。这会导致所有抗锯齿功能被破坏,因为即使是最微弱的不透明像素也会逐渐累积,直到变成实线。

使代码看起来更漂亮的最简单的修复方法是添加以下行:

context.clearRect(0,0,context.canvas.width,context.canvas.height);

for 循环内,例如在 context.lines();

这一行更改使其看起来不错,但对性能不利,每次视觉更新都会清除并重绘画布 10 次。

这是一个更好的选择:

context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x1+xdir, y1+ydir);
context.stroke();

x1 += xdir; y1 += ydir;

这样您就永远不会清除画布,而是每帧只绘制更改的线。

另一种替代方案(如果您需要始终可用的完整路径)是在一个高速 setInterval 循环中累积对上下文路径的更改,并在另一个较慢的循环中偶尔清除画布并重新抚摸整个路径。这与我在 Langton's (Very Fast) Ant 模拟中所做的类似。

Lines on HTML5 Canvas are nicely antialiased on all browsers/OS (AFAIK). However, in your update callback with its 10-strokes-per-loop you are neither clearing your canvas nor clearing your path and so you are drawing the same path on top of itself 200 times per second. This is causing all the anti-aliasing to be destroyed as even the faintest opacity pixels build up until they are solid lines.

The simplest fix to make your code look pretty is to add this line:

context.clearRect(0,0,context.canvas.width,context.canvas.height);

inside your for loop, for example right before context.stroke();.

This one-line change makes it look good, but is bad for performance, clearing and redrawing the canvas 10 times for each visual update.

Here's a better alternative:

context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x1+xdir, y1+ydir);
context.stroke();

x1 += xdir; y1 += ydir;

This way you never clear the canvas, and instead draw only the changed line each frame.

One other alternative (if you need the full path always available) is to accumulate your changes to the context path in one high-speed setInterval loop, and in another, slower loop occasionally clear the canvas and re-stroke the entire path. This is similar to what I've done for my Langton's (Very Fast) Ant simulation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文