2011-07-06 4 views
3

저는 Android 및 iOS 용으로 빌드를 시도하면서 phonegap에서 프로젝트를 개발해 왔습니다. 주요 아이디어는 전화 라이브러리의 저장된 그림에 액세스하여 그림을 HTML img 요소에 저장 한 다음 해당 img 요소를 캔버스에 그립니다. 거기에서 사용자는 이미지를 확대 및 축소 할 수 있습니다.iOS 플랫폼에서 HTML5 캔버스 크기 조정 문제가 발생했습니다.

Android에서 문제가 없었습니다. 저는 에뮬레이터와 장치를 사용하여 테스트했으며 광범위한 장치 (다른 픽셀 비율, 밀도 등)를 테스트했으며 결과로 나타나는 캔버스 변환은 항상 예상 된 결과를 제공합니다.

한편 iOS 버전은 아직 성공적이지 못했습니다. 캔버스의 크기를 원래 크기보다 약간 크게 할 때까지 캔버스를 확대/축소하는 것이 좋습니다 (원본보다 약 4-5 픽셀 더 큽니다). 캔버스의 크기를 조정하면 캔버스에 그려지는 이미지가 변경됩니다. 이제 전체 이미지가 표시되는 대신 전체 캔버스에 그려지는 이미지의 일부 (일반적으로 왼쪽 위 모서리)를 얻습니다. HTML에서

내 캔버스 :

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

내가 전화 라이브러리에서받는 이미지는 거의 항상 전화기 화면에 비해 너무 큽니다. 이미지를 축소하고 이미지를 축소하는 비율을 기록합니다 (크기 조정이 발생하지 않으면 drawRatio는 1이고, 이미지가 화면에 맞게 축소 된 경우 1보다 큼). 폰갭 전화 라이브러리에서 사진을 잡아 핸들, 나는 단순히 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; 
} 

캔버스의 크기를 조절하려면, 나는 오른쪽 하단에 화살표가 캔버스의 코너. 드래그하면 캔버스의 왼쪽 위 모서리에서 얼마나 떨어져 있는지 기록하고 거리에 따라 캔버스 높이/너비를 설정합니다. (그것은 다소 긴하지만, 간단하다. 코드 여기에 도시되지 않음) I는 실험 동안 설정된 값

drawRatioMod되고

//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); 
} 

drawRatio 위에 내가 리사이즈 이미지에 저장하는 비가 내 질문의 주요 초점이다. Android에서는 그림이 영향을받지 않도록 drawRatioMod = 1을 설정합니다. iPhone4/iPad (테스트 할 수있는 기기)에서 drawRatioMod = 0.5을 설정합니다. 이것은 iOS의 html5 캔버스에서 겪었던 몇 가지 초기 문제를 해결했습니다. iPhone4의 해상도는 실제로 화면 크기의 두 배이기 때문에 원본 이미지의 길이/너비를 절반으로 줄였습니다.

위의 ResizeSourceImage() 함수는 사용자가 크기 조정 화살표 도구를 움직일 때마다 호출되어 캔버스 크기를 업데이트합니다. 크기가 작 으면 새 캔버스 크기로 이미지가 올바르게 조정됩니다. 캔버스를 약 5-6 픽셀 이상으로 확대하면 캔버스가 더 이상 전체 소스 이미지를 그립니다. 대신 캔버스는 전체 캔버스에 이미지의 왼쪽 위 모서리 만 그립니다.

나는이 문제를 며칠 동안 다루었으며 운이 없었습니다. 처음에는 장치 픽셀 비율 (자바 스크립트 window.devicePixelRatio을 통해 액세스 할 수 있음)과 관련이 있다고 생각했지만 다양한 Android 장치를 테스트 한 결과이 결과가 없었습니다.

iOS에서 크기를 조정할 때 이미지가 잘못 표시되기 때문에 매우 가깝다고 생각합니다. 모든 포인터/팁을 대단히 감사합니다! window.devicePixelRatio과 관련된 몇 가지 수정 사항을 시도했지만 내 iPad의 iPhone4 시뮬레이터는 항상 1의 pixelRatio (잘못된 것 같습니다)를 반환하며 그러한 수정 사항이없는 행운을 빕니다.

건배! (나는 캔버스의 스케일링과 드로잉을 다루는 베어 본 코드를 게시하려고 시도했다. 추가 코드를보고 싶으면 더 게시 할 수 있으며 중국의 거대한 벽과 닮지 않은 게시물을 가지기를 바랐다. :)

답변

3

며칠 동안 이것을 테스트 한 후, 마침내 범인을 발견했습니다. myContext.drawImage()을 사용하여 이미지를 슬라이싱하는 것은 iOS에서 큰 고통 일 수 있습니다 (아마도 망막 디스플레이 때문일 수 있지만, 저는 100이 아닙니다. % 확실).

내가 대신 한 것은 이중 버퍼링을 조합하여 myContext.drawImage()에서 까지만 크기가 아니라 조각입니다.

FelineSoft에는 여러 가지 캔버스 관련 게시물이 있습니다. 더블 버퍼링은 여기에 설명 : 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.drawImage()를 사용하지 당신이 볼 수 있듯이

//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); 

: 다시 찾고, 버퍼는 내가 가진이 스케일링 문제를 해결하기 위해 필요하지 않을 수 있지만, 익숙해 좋은 습관 캔버스에 맞게 크기를 조절하면됩니다.

내가 잘못된 방향으로 가고있는 것처럼 보였으 나, 비슷한 문제가있는 다른 사용자도이 방법을 사용하면 도움이 될 것입니다.