在剪裁的画布中移动所有图像

时间:2013-11-30 04:00:40

标签: javascript html5 canvas clip

好的,所以我刚看了一下Canvas元素,但是我遇到了障碍。

我找到了一个演示,使用箭头键将三个图像移到另一个上面。

然而,我剪掉其中一个,即使上面的剪辑图像也没有移动,但是底层图像现在没有移动。

HTML:

<canvas id="parallax-canvas">
    Sorry, your browser does not support HTML5 Canvas.
</canvas>

CSS:

.parallax-canvas {
    width: 400px;
    height: 300px;
}

JavaScript的:

$(document).ready(function() {
    var w = $("#parallax-canvas").width();
    var h = $("#parallax-canvas").height();

    var sky = new Image();
    sky.src = "assets/img/sky.jpg";
    var skydx = 2;
    var skyx = 0;

    var mountains = new Image();
    mountains.src ="assets/img/mountains.png";
    var mountainsdx = 10;
    var mountainsx = 0;

    var jeep = new Image();
    jeep.src ="assets/img/jeep.png";
    var jeepx = 100; 
    var jeepy = 210; 
    var jeepsx = 0; 
    var jeepsxWidth = 155;

    var cntx =  $("#parallax-canvas")[0].getContext("2d");
    setInterval(draw, 10, cntx);

    $(window).keydown(function(evt) {
        switch (evt.keyCode) {
            case 37: // Left arrow
                if ((skyx + skydx) > skydx)
                  skyx -= skydx;
                else
                  skyx = w;

                if ((mountainsx + mountainsdx) > mountainsdx)
                  mountainsx -= mountainsdx;
                else
                  mountainsx = 398;

                if (jeepsx > 0) 
                    jeepsx -= jeepsxWidth;
                else 
                    jeepsx = (jeepsxWidth*2);

            break;

            case 39: // Right arrow
                if ((skyx + skydx) < (w - skydx))
                  skyx += skydx;
                else
                  skyx = 0;

                if ((mountainsx + mountainsdx) < (w - mountainsdx))
                  mountainsx += mountainsdx;
                else
                  mountainsx = 0;

                if (jeepsx < (jeepsxWidth*2))
                   jeepsx += jeepsxWidth;
                else
                   jeepsx = 0;

                break;
        }
    });

    function draw(_cntx) {
        drawRectangle(_cntx, 0, 0, w, h);
        _cntx.drawImage(sky, skyx, 0, 300, 300, 0, 0, w, 300);
        _cntx.beginPath();
        _cntx.moveTo(0,300);
        _cntx.lineTo(150,150);
        _cntx.lineTo(300, 300);
        _cntx.closePath();
        _cntx.clip();
        _cntx.drawImage(mountains, mountainsx, 0, 300, 300, 0, 0, w, 300);
        _cntx.drawImage(jeep, jeepsx, 0, jeepsxWidth, 60, jeepx, jeepy, 155, 60);
    }

    function drawRectangle(_cntx, x, y, w, h) {
        _cntx.beginPath();
        _cntx.rect(x,y,w,h);
        _cntx.closePath();
        _cntx.fill();
        _cntx.stroke();
    }
});

我添加剪辑的部分是此部分:

function draw(_cntx) {
    drawRectangle(_cntx, 0, 0, w, h);
    _cntx.drawImage(sky, skyx, 0, 300, 300, 0, 0, w, 300);
    _cntx.beginPath();
    _cntx.moveTo(0,300);
    _cntx.lineTo(150,150);
    _cntx.lineTo(300, 300);
    _cntx.closePath();
    _cntx.clip();
    _cntx.drawImage(mountains, mountainsx, 0, 300, 300, 0, 0, w, 300);
    _cntx.drawImage(jeep, jeepsx, 0, jeepsxWidth, 60, jeepx, jeepy, 155, 60);
}

如果从剪辑方法中删除并包含beginPath方法,它将允许三个图像全部移动。

发生了什么:当按下左右箭头键时,天空图像不会移动,山峰和吉普车被剪裁但在剪裁区域内移动。

我想发生什么:在剪裁的区域内移动的天空图像以及山脉和吉普车。

ALSO:

我想知道如何用箭头按下移动剪裁区域。我的意思是,目前有一个剪切区域,通过左右按压图像移动但剪切(切出)区域保持静止。我想知道(如果可能的话)如何使用箭头键移动剪切区域。

正在使用的演示:http://www.ibm.com/developerworks/web/library/wa-parallaxprocessing/

遗憾的是无法设置小提琴,因为图片不在网站上,因此无法提供URL但.zip在网站上,并通过复制和粘贴代码的底部部分,其方法位于JavaScript文件中我得到了什么。

感谢您的帮助!

编辑:感谢Ken帮助您缩短代码和效率。到目前为止,没有什么能回答我关于如何移动图像以及剪切位置的初步问题。

1 个答案:

答案 0 :(得分:1)

您需要为画布设置大小 - 不要将CSS用于set the size of a canvas

<canvas id="parallax-canvas" width=500 height=300>
    Sorry, your browser does not support HTML5 Canvas.
</canvas>

同样,您需要从画布中读取正确的大小:

$(document).ready(function() {
    var canvas = $("#parallax-canvas")[0];
    var w = canvas.width;
    var h = canvas.height;
    ...

每次按光标键时,都需要重绘所有内容。画布不知道画入了什么 - 它只是一堆像素,所以我们需要自己提供更新的逻辑。

更新似乎我错过了你正在从setInterval循环重绘,所以这并不适用,但我让这个例子保持不变,因为它可能是一个更好的方法,因为你只当事情真正发生变化时需要更新。例如,一个重新绘制所有内容的循环将很快耗尽电池。

例如:

$(window).keydown(function(evt) {
    switch (evt.keyCode) {
        case 37: // Left arrow
            if ((skyx + skydx) > skydx)
              skyx -= skydx;
            else
              skyx = w;

            if ((mountainsx + mountainsdx) > mountainsdx)
              mountainsx -= mountainsdx;
            else
              mountainsx = 398;

            if (jeepsx > 0) 
                jeepsx -= jeepsxWidth;
            else 
                jeepsx = (jeepsxWidth*2);

        draw(cntx );

        break;
        ...

你需要重复其他动作。

由于加载是异步的,因此加载图像的方式也会遇到问题。您需要通过点击onload处理程序来处理加载:

var sky = new Image();
sky.onload = functionToHandleLoad;
sky.src = "assets/img/sky.jpg";

在您加载许多图片时,您需要count the images或使用批量加载程序,例如我的YAIL loader

对于剪辑,使用保存/恢复非常重要,因为当前浏览器无法正确处理剪辑区域的手动重置:

function draw(_cntx) {
    drawRectangle(_cntx, 0, 0, w, h);
    _cntx.drawImage(sky, skyx, 0, 300, 300, 0, 0, w, 300);
    _cntx.beginPath();
    _cntx.moveTo(0,300);
    _cntx.lineTo(150,150);
    _cntx.lineTo(300, 300);
    _cntx.closePath();

    _cntx.save();     /// save current clip region

    _cntx.clip();
    _cntx.drawImage(mountains, mountainsx, 0, 300, 300, 0, 0, w, 300);
    _cntx.drawImage(jeep, jeepsx, 0, jeepsxWidth, 60, jeepx, jeepy, 155, 60);

    _cntx.restore();  /// reset clip
}

在回答那里没有小提琴时,所以我没有检查代码的其他部分,但这应该是一个好的开始,我认为。

此功能

function drawRectangle(_cntx, x, y, w, h) {
    _cntx.beginPath();
    _cntx.rect(x,y,w,h);
    _cntx.closePath();
    _cntx.fill();
    _cntx.stroke();
}

可以简化为:

function drawRectangle(_cntx, x, y, w, h) {
    _cntx.fillRect(x, y, w, h);
    _cntx.strokeRect(x, y, w, h);
}

无需在rect上关闭路径,fillRect / strokeRect不需要beginPath。