iOS平台上的HTML5canvas缩放问题

我一直在开发一个phonegap项目,试图构buildAndroid和iOS。 主要思路是访问手机库中保存的图片,将该图片保存到HTML img元素,然后将该img元素绘制到canvas上。 从那里,用户可以缩放和旋转图像。

我在Android上没有任何问题。 我已经使用仿真器和设备进行了testing,并且testing了大量的设备(不同的像素比例,密度等),结果的canvas转换总是给出预期的结果。

另一方面,iOS版本并没有那么成功。 缩放/旋转canvas看起来很好,直到我缩放canvas比原来的尺寸稍大(比原来大约4-5个像素)。 将canvas向上缩放后,canvas上绘制的图像会发生变化。 现在不用看现在看到的整个图像,我通常会在整个canvas上画出一小部分图像(通常是左上angular)。

我的canvas在HTML:

<canvas id="sourceImgCanvas" width="200" height="200" style="z-index:1; position:absolute; left:5%; top:100px;"></canvas> 

我从手机库收到的图像几乎总是太大,不适合手机屏幕。 我缩小图像并logging我缩小图像的比率(如果没有缩放发生,绘制比例为1,如果图像缩小到适合屏幕,则比例大于1)。 PhoneGap处理抓取手机库中的图片,我只是使用从照片返回的imageURI并将其设置为一个img元素Phonegap Camera API :

 // Called when a photo is successfully retrieved function onPhotoURISuccess(imageURI) { sourceImage = document.getElementById('sourceImg'); sourceImage.src = imageURI; //signal that user can manipulate photo with touch inputs b_editPhotoAllowed = true; } 

要缩放canvas,我在canvas的右下angular有一个箭头。 拖动时,它会logging距离canvas左上angular多远,并根据距离设置canvas高度/宽度。

 //Calls when user is dragging the arrow resize button. Updates the source image size function ResizeSourceImage() { var horizontalDistanceFromTopLeft = parseFloat(ovalCanvas.style.left) + ovalCanvas.width - endX; var verticalDistanceFromTopLeft = parseFloat(ovalCanvas.style.top) + ovalCanvas.height - endY; //update canvas size with new length sourceImgCanvas.width = originalSrcImgWidth - horizontalDistanceFromTopLeft; sourceImgCanvas.height = originalSrcImgHeight - verticalDistanceFromTopLeft; //re-draw based on new size sourceImgContext.drawImage(sourceImg, 0, 0, pictureWidth * drawRatio * drawRatioMod, pictureHeight * drawRatio * drawRatioMod, 0, 0, sourceImgCanvas.width, sourceImgCanvas.height); } 

上面的绘制比率是我在重新调整图像尺寸时存储的比率(代码在这里没有显示;它相当长,但很简单)

drawRatioMod是我在实验时设定的一个值,也是我的问题的主要焦点。 在Android上,我设置了drawRatioMod = 1以便绘图不受影响。 在iPhone4 / iPad(我可以testing的设备)上,我设置了drawRatioMod = 0.5 。 这解决了我在iOS上使用html5canvas时遇到的一些初始问题:由于iPhone4的分辨率实际上是屏幕尺寸的两倍,因此我将源图像的长度/宽度减less了一半。

每当用户移动resize的箭头工具时,都会调用以上ResizeSourceImage()函数,从而更新canvas大小。 只有在缩小的情况下,图像才能正确调整到新的canvas大小。 如果我将canvas缩放超过5-6个像素,则canvas不再绘制整个源图像; 相反,canvas只在整个canvas上绘制图像的左上angular。

我一直在解决这个问题几天,没有运气。 我最初认为它与设备像素比(可通过JavaScript window.devicePixelRatio访问)有关,但是我已经testing了几种不同比率的Android设备,并且从来没有得到这个结果。

我觉得我非常接近解决问题,因为在iOS上扩展时图像只显示不正确。 任何指针/提示,非常感谢! 我已经尝试了几个与window.devicePixelRatio相关的修复,但是我的iPad的iPhone4模拟器总是返回1的像素比率(这似乎是不正确的),而且我没有这样的修复运气。

干杯! (我试图张贴关于canvas的缩放和绘制的基本代码,如果你想看更多的代码,我可以发表更多的内容;希望能有一个不像中国长城的post:))

经过几天的testing,我终于find了罪魁祸首:使用myContext.drawImage()来切片图像只是iOS的一大痛苦(也许是由于视网膜显示,但我不是100%肯定) 。

我所做的是双缓冲和使用myContext.drawImage()的组合, 只能缩放,而不是切片。

FelineSoft在与canvas有关的几件事上有一个很棒的post。 双缓冲在这里解释: http : //www.felinesoft.com/blog/index.php/2010/09/accelerated-game-programming-with-html5-and-canvas/

所以,而不是像这样切片的原始图像:

 sourceImgContext.drawImage(sourceImg, 0, 0, pictureWidth * drawRatio * drawRatioMod, pictureHeight * drawRatio * drawRatioMod, 0, 0, sourceImgCanvas.width, sourceImgCanvas.height); 

我将图像绘制到缓冲区,然后将其绘制到用户在屏幕上看到的canvas上。 回想一下,缓冲区可能不是必须的,以解决我所遇到的这个缩放问题,但习惯于习惯于这样的习惯:

 //buffer to draw the image to before drawing on-screen var bufferCanvas = document.createElement('canvas'); var bufferContext = bufferCanvas.getContext('2d'); bufferContext.drawImage(sourceImg, 0, 0, bufferCanvas.width, bufferCanvas.height); //later, I draw the image stored in buffer to a canvas user will see on-screen //if this call is coming right after the command to draw image to buffer, would be best //to add a check to make sure buffer has finished drawing image. sourceImgContext.drawImage(bufferCanvas, 0, 0, sourceImgCanvas.width, sourceImgCanvas.height); 

正如你所看到的,我不再使用canvas.drawImage()来切片源图像,我只是缩放它以适应canvas。

似乎我是以错误的方式去做的,但希望其他遇到类似问题的人会发现这种方法很有帮助。

Interesting Posts