html 5画布绘图错误

时间:2013-06-07 10:35:37

标签: javascript html html5 html5-canvas

我正在尝试根据html 5画布中绘制的矢量构建我的第一个几乎复杂的地图。

除缩放外,效果很好。我注意到以下几点:

  • 在Firefox中,一切运行良好(除了鼠标滚轮,但仅用于测试)
  • 在Chrome中使用鼠标滚轮缩小到比例因子< 1看起来每次绘制时图像都会重复
  • 在Android和iOS中,使用缩放手势,存在最大的问题:每次重新绘制图像时都会出现重复的图像。

我起初认为这是我的错,也许画布没有被清除。但经过一些测试,“幽灵”消失了,新鬼出现了。

如果有人可以提供帮助,那就太酷了。

代码 - HTML:

<div>
    <div style="position:absolute;top:30px;z-index:102;">
        <canvas id="canvas" width="1386" height="747" style="position:absolute;"></canvas>
    </div>
    <div style="position:absolute; top:30px;" id="debugText">Debug</div>
    <div style="position:absolute;top:30px; visibility: hidden;">
        <canvas id="debugCanvas" width="1386" height="747"></canvas>
    </div>
    <div style="position:absolute; left: 200px;z-index:99;" id="debugContols">
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        <a href="#" onClick="javascript:zoomIn(0, 0, 0.5);">Zoom 0.5</a>
        <a href="#" onClick="javascript:zoomIn(0, 0, 2);">Zoom 2</a>
        <a href="#" onClick="javascript:zoomIn(0, 0, 3);">Zoom 3</a>
    </div>
</div>

代码 - Javascript:

var canvas = document.getElementById("canvas");
var debugCanvas = document.getElementById("debugCanvas");
var ctx = canvas.getContext("2d");
var ctxDebug = debugCanvas.getContext("2d");
var context = ctx;
var scale = 1;
var originx = 0;
var originy = 0;

function draw() {
    // plne/Straen
[find drawing in fiddle, since its too long]
}

this.onmousewheel = function(event) {
    var mousex = event.clientX - canvas.offsetLeft;
    var mousey = event.clientY - canvas.offsetTop;
    var wheel = event.wheelDelta/120;//n or -n

    //according to Chris comment
    var zoom = Math.pow(1 + Math.abs(wheel)/2 , wheel > 0 ? 1 : -1);

    zoomIn(mousex, mousey, zoom);
    return;
}

var isZooming = false;
var distances = new Array();

function touchStart(e) {
    preventDefaultScroll(e);
    if(e.touches.length > 1 && isZooming == false) {
        var touch1 = event.touches[0];
        var touch2 = event.touches[1];

        x1 = touch1.pageX;
        y1 = touch1.pageY;
        x2 = touch2.pageX;
        y2 = touch2.pageY;

        var diffX = x2 - x1;
        var diffY = y2 - y1;

        var centerX = x1 + diffX/2;
        var centerY = y1 + diffY/2;

        //$("#debugText").text(centerX + " " + centerY);
        debugCanvas.width = debugCanvas.width;
        ctxDebug.beginPath();
        ctxDebug.arc(centerX, centerY, 20, 0, 2 * Math.PI, false);
        ctxDebug.fillStyle = 'green';
        ctxDebug.fill();
        ctxDebug.lineWidth = 5;
        ctxDebug.strokeStyle = '#003300';
        ctxDebug.stroke();

        zoomCenterX = centerX;
        zoomCenterY = centerY;

        var touch1 = event.touches[0];
        var touch2 = event.touches[1];

        x1 = touch1.pageX;
        y1 = touch1.pageY;
        x2 = touch2.pageX;
        y2 = touch2.pageY;

        var distanz = dist(x1,y1,x2,y2);
        lastDistance = distanz;

        distanceInterval = setInterval(checkDistance,50);
        isZooming = true;
    }
}

    var distanceInterval;
    var zoomCenterX;
    var zoomCenterY;
    var lastDistance = 0;
    function checkDistance()
    {
    $("#debugText").text("checkDist");
        if(distances.length == 0) return;





        var distanceGesamt = 0;

        for(var i = 0; i < distances.length; i++)
        {
            distanceGesamt += distances[i];
        }


        var distanceDurchschnitt = distanceGesamt / distances.length;


        var curDist = distanceDurchschnitt - lastDistance;

        var zoomFac = 1 + (curDist / 100);

        $("#debugText").text(distanceDurchschnitt + " " + zoomFac);

        distances = new Array();


        zoomIn(zoomCenterX, zoomCenterY, zoomFac)
        lastDistance = distanceDurchschnitt;
    }

    function touchEnd(e)
    {
        if(e.touches.length < 2)
        {
            isZooming = false;
            clearInterval(distanceInterval);

        }
    }

    function dist(x1,y1,x2,y2)
     {
        return Math.sqrt((x1 -= x2) * x1 + (y1 -= y2) * y1);
     }

    function touchMove(e)
    {
        if(isZooming)
        {
            var touch1 = event.touches[0];
            var touch2 = event.touches[1];

            x1 = touch1.pageX;
            y1 = touch1.pageY;
            x2 = touch2.pageX;
            y2 = touch2.pageY;

            var distanz = dist(x1,y1,x2,y2);
            distances.push(distanz);
        }
    }

    function preventDefaultScroll(event) {
        event.preventDefault();
        window.scroll(0,0);
        return false;
    } 



    canvas.addEventListener('gestureend', function(e) {
        if (e.scale < 1.0) {
            // User moved fingers closer together
        } else if (e.scale > 1.0) {
            // User moved fingers further apart
        }
    }, false);

    function zoomIn(mousex, mousey, zoom)
    {

        canvas.style.display = 'none';
        context.translate(
            originx,
            originy
        );
        context.scale(zoom,zoom);
        context.translate(
            -( mousex / scale + originx - mousex / ( scale * zoom ) ),
            -( mousey / scale + originy - mousey / ( scale * zoom ) )
        );

        originx = ( mousex / scale + originx - mousex / ( scale * zoom ) );
        originy = ( mousey / scale + originy - mousey / ( scale * zoom ) );
        scale *= zoom;





         requestAnimFrame(function() {
            context.clearRect(0,0,canvas.width,canvas.height);
              draw();
        });


        canvas.style.display = 'block';
        //context.clearRect(0,0,canvas.width,canvas.height);
    }

    $(document).ready(function() {
        draw();
        addEventListener('touchstart', touchStart, true);
        addEventListener('touchmove', touchMove, true);
        addEventListener('touchend', touchEnd, true);
        addEventListener('touchcancel', touchEnd, true);


    });
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       ||
              window.webkitRequestAnimationFrame ||
              window.mozRequestAnimationFrame    ||
              function( callback ){
                window.setTimeout(callback, 1000 / 60);
              };
    })();

Here's the fiddle

2 个答案:

答案 0 :(得分:5)

好的,我在您的代码中发现的第一个问题是,当您进行上下文转换时,您使用的是context而不是ctx,所以我修复了这个问题。

接下来,我将clearRect移动到函数的顶部,然后在上下文已经转换后绘制。

最后,还有一些地图仍在底部重复,因此我更改clearRect以清除画布canvas.height*2的实际高度的两倍。

JSFiddle

答案 1 :(得分:3)

两个想法:

首先:哇,好好利用路径来布置地图 - 非常广泛!

第二:由于您使用滚轮/触摸而不是鼠标点击来驱动缩放,因此需要删除requestAnimFrame动画。

动画旨在逐渐缩放到用户鼠标滑动的位置。