【问题标题】:Canvas: Animate bezier curve drawing画布:动画贝塞尔曲线绘制
【发布时间】:2012-08-03 14:49:05
【问题描述】:

我试图画一条从左到右穿过画布的线。我仍处于早期阶段来实现这一点,我使用以下函数来做一步一步的动画

timer = window.setInterval(draw_line, 30);

我的绘图功能是这样的

function draw_line()
    {
        context.fillStyle = "#000";
        context.fillRect(0, 0, canv.width, canv.height);

            context.beginPath();
        context.lineWidth = 2;
        context.strokeStyle = '#fff';

            //Where p1, p2, cp1, cp2 are point objects that has x & y values already defined    
        context.moveTo(p1.x, p1.y);
        context.bezierCurveTo(cp1.x,cp1.y,cp2.x,cp2.y,p2.x,p2.y);
        context.stroke();
        context.closePath();

            // now i have to move p1, p2 ,cp1,cp2
            // now here is my problem
    }

我知道我需要移动p1.x+= a random number;,对于 cp1 和 cp2 也是如此,但是 p2 端点应该遵循相同的轨迹!我怎样才能做到这一点?

谢谢

【问题讨论】:

    标签: javascript jquery html canvas


    【解决方案1】:

    修改后的答案

    有了你的澄清,我想我现在可以适当地回答这个问题了。

    为了让终点沿着起点穿过画布的路径,您必须存储历史值。在此示例中,http://jsfiddle.net/mobidevelop/bGgHQ/,我使用鼠标移动来填充最后 16 个位置的缓冲区,然后使用它通过遍历 RingBuffer 来形成通过点的贝塞尔曲线。

    function RingBuffer(length) {
        this.length = length;
        this.pointer = 0;
        this.buffer = [];
    }
    RingBuffer.prototype.get = function(index) {
        if (index < 0) {
            index += this.length;        
        }
        return this.buffer[index];
    }
    RingBuffer.prototype.push = function(value) {
        this.buffer[this.pointer] = value;
        this.pointer = (this.length + this.pointer +1) % this.length;    
    }
    
    var c = document.getElementById("myCanvas");
    var context =c.getContext("2d");
    
    timer = window.setInterval(draw_line, 30);
    function Point(x,y) {
        this.x = x;
        this.y = y;
    }
    Point.prototype.translateX = function(x) {
        return this.x += x;
    };
    Point.prototype.translateY = function(y) {
        return this.y += y;
    };
    
    function draw_line()
    {
        context.fillStyle = "#000";
        context.fillRect(0, 0, c.width, c.height);
    
        var pointer = history.pointer;
        context.beginPath();
        context.lineWidth = 2;
        context.strokeStyle = '#F00';     
        for (iteration = 0, count = 15; iteration < count; iteration += 3) {
            var p1 = history.get(--pointer);
            var p2 = history.get(--pointer);
            var p3 = history.get(--pointer);
            var p4 = history.get(--pointer);        
    
            if (p1 && p2 && p3 && p4) {
    
                context.moveTo(p1.x, p1.y);
                context.bezierCurveTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
    
            }
            pointer++;
        }
        context.stroke();
        context.closePath();    
    
    }
    
    var history = new RingBuffer(16);
    var lastGrab = new Date();
    c.addEventListener('mousemove', function() {
        now = new Date();
        if (now - lastGrab > 15) {
            history.push(new Point(event.clientX - c.offsetLeft, event.clientY - c.offsetTop)); 
            lastGrab = now;
        }    
    });​
    

    上一个答案留在下面,出于历史目的。

    我不确定我是否完全理解您想要实现的目标,但我认为您需要做的就是将您的所有观点转换为相同的值。这将导致穿过画布的线保持相同的形状。像这样:

    JSFiddle

    var c = document.getElementById("myCanvas");
    var context =c.getContext("2d");
    
    timer = window.setInterval(draw_line, 30);
    function Point(x,y) {
        this.x = x;
        this.y = y;
    }
    Point.prototype.translateX = function(x) {
        return this.x += x;
    };
    Point.prototype.translateY = function(y) {
        return this.y += y;
    };
    
    var p1 = new Point(0,0);
    var p2 = new Point(100,100);
    var cp1 = new Point(15,45);
    var cp2 = new Point(85,45);
    
    function draw_line()
    {
        context.fillStyle = "#000";
        context.fillRect(0, 0, c.width, c.height);
    
        context.beginPath();
        context.lineWidth = 2;
        context.strokeStyle = '#fff';
    
            //Where p1, p2, cp1, cp2 are point objects that has x & y values already defined    
        context.moveTo(p1.x, p1.y);
        context.bezierCurveTo(cp1.x,cp1.y,cp2.x,cp2.y,p2.x,p2.y);
        context.stroke();
        context.closePath();
    
        p1.translateX(1);
        p2.translateX(1);
        cp1.translateX(1);
        cp2.translateX(1);
    
        if (p1.x > 300) {
            p1.translateX(-400);
            p2.translateX(-400);
            cp1.translateX(-400);
            cp2.translateX(-400);        
        }
    }
    

    除非我误解了目标......

    【讨论】:

    • 感谢您的回答,但我试图实现的是一个有尾巴的点。第一个点 p1 沿随机方向移动,第二个点 p2 跟随 p1 尾部
    • 有趣,我永远不会从你对问题的描述中得到这个......不幸的是,我仍然很困惑。你有你想要实现的视觉示例吗?
    • @ra_htial 您是否正在寻找更多类似的东西? jsfiddle.net/mobidevelop/bGgHQ(在画布上移动鼠标)
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多