如何使用HTML画布

时间:2018-02-04 21:15:58

标签: javascript html canvas

我是html画布的新手。我试图旋转两个轮子看起来旋转形成像汽车的底座(例如)但是,下面的代码围绕第一个轮子旋转第二个轮子(当它在中心旋转时)。 / p>

function wheel(rot,angle) {

    c.save();
    c.beginPath();
    this.rot = rot;
    for(var i =0; i<2*Math.PI; i = i + 0.01) {
        var x = 50 * Math.cos(6 * i) * Math.cos(i);
        var y = 50 * Math.cos(6 * i) * Math.sin(i);

        c.lineTo(x, y);
    }
    if(this.rot===1) {
        c.fill();
    }else{
        c.stroke();
    }
}

var slider1 = document.getElementById('slider1');
var slider2 = document.getElementById('slider2');
slider2.value =1;
slider1.value = 1;


function draw() {

    c.clearRect(-450, -450, canvas.width, canvas.height);

    c.save();
    c.rotate(slider2.value);

    wheel(1);

    c.restore();
    c.save();
    c.translate(200, 200);

    wheel(2);

    c.restore();
    c.restore();

    window.requestAnimationFrame(draw);
}


c.save();

c.translate(400, 200);

draw();

我认为我的错误在于放置c.save()和c.restore()但是 我不确定。

1 个答案:

答案 0 :(得分:0)

您的代码中的主要问题是c.save()函数中的wheel调用不平衡。您对saverestore的其他用法很好,但通常这些调用需要进行平衡(还要考虑嵌套函数调用,例如wheel函数)。这类似于数学方程中的平衡括号或代码块中的平衡括号。

如果删除除saverestore来电之外的所有代码,则很容易看出出现了什么问题。保持心理计数器,从零开始并为每个save呼叫添加1,并为每个restore呼叫减去1。最后,你应该回到零。

function wheel(rot,angle) {
    c.save();
}

function draw() {
    // counter = 0
    c.save();
    // counter = 1

    wheel(1); // contains save() call
    // counter = 2

    c.restore();
    // counter = 1
    c.save();
    // counter = 2

    wheel(2); // contains save() call
    // counter = 3

    c.restore();
    // counter = 2;
    c.restore();
    // counter = 1;
}

我们在draw()函数的末尾,我们的计数器等于1.某些东西是不平衡的,并且快速分析显示wheel()函数是罪魁祸首,其无法匹配的save()调用。

wheel函数不会改变画布状态,因此它实际上不需要使用保存和恢复。如果从wheel函数中删除save()调用,事情几乎是平衡的。最后一个更改是在draw()结束时删除冗余restore()调用。

以下是您可以运行的包含这些更改的片段,以及其他一些可以启用两个轮子的独立旋转的片段。

var canvas = document.querySelector('canvas');
var c = canvas.getContext('2d');

var slider1 = document.getElementById('slider1');
var slider2 = document.getElementById('slider2');

function wheel(rot,angle) {
    c.beginPath();
    this.rot = rot;
    for(var i =0; i<2*Math.PI; i = i + 0.01) {
        var x = 50 * Math.cos(6 * i) * Math.cos(i);
        var y = 50 * Math.cos(6 * i) * Math.sin(i);

        c.lineTo(x, y);
    }
    if(this.rot===1) {
        c.fill();
    }else{
        c.stroke();
    }
}


function draw() {

    c.clearRect(-100, -100, canvas.width, canvas.height);

    c.save();
    c.rotate(slider1.value);

    wheel(1);

    c.restore();
    c.save();
    c.translate(200, 0);
    c.rotate(slider2.value);

    wheel(2);

    c.restore();

    window.requestAnimationFrame(draw);
}


c.save();

c.translate(100, 100);

draw();
<input id="slider1" type="range" min="0" max="6.28" step="0.01" />
<input id="slider2" type="range" min="0" max="6.28" step="0.01" />
<canvas width="400" height="300"></canvas>