我编写了大部分模块来处理 HTML 5 画布元素上的多点触控捏合、平移和缩放。我将在下面分享。我已经用 JavaScript 开发了一段时间了,而这个仍然让我感到困惑。如果有人有任何见解,一旦确认在我的 iPad 上工作,我会将最终版本发布到堆栈上供大家分享。
这是我正在做的事情:
touchmove
事件触发变量的变化。我使用这些变量来改变我的图像在画布上的绘制方式。我有八个变量,每个变量对应于可以放入drawImage()
函数的选项。这八个变量通过递增/递减它们的值并将它们保持在一定范围内的函数进行更新。这些变量是闭包变量,因此它们在我的模块中是全局的。为了防止过度处理,我drawImage()
每 40 毫秒调用一次此函数,同时用户使用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);
}
}