簡體   English   中英

多點觸控捏合、平移、放大 HTML 5 畫布

[英]Multitouch Pinch, Pan, Zoom in HTML 5 Canvas

我編寫了大部分模塊來處理 HTML 5 畫布元素上的多點觸控捏合、平移和縮放。 下面我來分享一下。 我已經用 JavaScript 開發一段時間了,這個問題繼續讓我感到困惑。 如果有人有任何見解,一旦確認可以在我的 iPad 上運行,我會將最終版本發布到堆棧上供大家分享。

這是我在做什么:

touchmove事件觸發變量的變化。 我使用這些變量來改變我的圖像在畫布上的繪制方式。 我有八個變量,每個變量對應於可以放入drawImage()函數的選項。 這八個變量通過增加/減少它們的值並將它們保持在一定范圍內的函數進行更新。 變量是閉包變量,因此它們在我的模塊中是全局的。 為了防止過度處理,我每 40 毫秒調用一次drawImage()函數,同時用戶使用setInterval()將手指壓在屏幕上。 這是問題所在:

touchmove事件似乎導致了競爭條件,其中我的變量被同一事件的許多不同實例更新。 我可以通過我的控制台輸出在一定程度上證實這一點,它跟蹤一個永遠不會低於 20 的變量。當我快速向一個方向滑動時,該變量下降到遠低於 20。然后當我松開手指,慢慢滑動時,它返回到 20。另一件讓我指向這個方向的事情,當我在逐步執行我的程序時查看這些變量時,它們與我的console.log()輸出的不同。

注意:該代碼第一次成功繪制了圖像,但之后的任何時候都無法成功繪制。 我的代碼的基本版本如下...完整版本位於GitHub 上的 Scripts 文件夾內。 它本質上是一個 Sencha Touch v1.1 應用程序

function PinchPanZoomFile(config)
{
    /*
     * Closure variable declaration here...
     * Canvas Declaration here...
    */
    
    function handleTouchStart(e) {
        whatDown.oneDown = (e.originalEvent.targetTouches.length == 1) ? true : false;
        whatDown.twoDown = (e.originalEvent.targetTouches.length >= 2) ? true : false;
        
        drawInterval = setInterval(draw, 100);
    }
    
    function handleTouchEnd(e) {
        whatDown.oneDown = (e.originalEvent.targetTouches.length == 1) ? true : false;
        whatDown.twoDown = (e.originalEvent.targetTouches.length >= 2) ? true : false;
        clearInterval(drawInterval);
    }
    
    function handleTouchMove(e) {
        if(whatDown.twoDown) {
            /*
             * Do Panning & Zooming
            */  
            changeWindowXBy(deltaDistance); //deltaDistance
            changeWindowYBy(deltaDistance); //deltaDistance
            changeCanvasXBy(deltaX); //Pan
            changeCanvasYBy(deltaY); //Pan
            changeWindowDimsBy(deltaDistance*-1,deltaDistance*-1); //(deltaDistance)*-1 -- get smaller when zooming in.
            changeCanvasWindowDimsBy(deltaDistance,deltaDistance); //deltaDistance -- get bigger when zooming in
            
        } else if(whatDown.oneDown) {
            /*
             * Do Panning
            */
            changeWindowXBy(0);
            changeWindowYBy(0);
            changeCanvasXBy(deltaX);
            changeCanvasYBy(deltaY);
            changeWindowDimsBy(0,0);
            changeCanvasWindowDimsBy(0,0);
        }
    }
    
    function draw() {
        //Draw Image Off Screen
        var offScreenCtx = offScreenCanvas[0].getContext('2d');
        offScreenCtx.save();
        offScreenCtx.clearRect(0, 0, canvasWidth, canvasHeight);
        offScreenCtx.restore();
        offScreenCtx.drawImage(base64Image, 
            parseInt(windowX), 
            parseInt(windowY), 
            parseInt(windowWidth), 
            parseInt(windowHeight), 
            parseInt(canvasX), 
            parseInt(canvasY), 
            parseInt(canvasWindowWidth), 
            parseInt(canvasWindowHeight)
        );
        
        //Draw Image On Screen
        var offScreenImageData = offScreenCtx.getImageData(0, 0, canvasWidth, canvasHeight);
        var onScreenCtx = canvas[0].getContext('2d');
        onScreenCtx.putImageData(offScreenImageData, 0, 0);
    }
}

我強烈推薦使用 Sencha Touch 2.0.1,因為它支持很多你需要的觸摸事件。 有關示例,請參閱http://dev.sencha.com/deploy/touch/examples/production/kitchensink/#demo/touchevents

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM