2012-03-01 1 views
1

우리는 캔버스 요소를 가지고 놀았지만 모바일 사파리는 느리게 움직이는 반면 데스크톱에서는 부드럽게 작동합니다.모바일 사파리 (HTML5 캔버스)에서 웹 앱을 그리기/스케치 할 때 UI가 부끄럽다

테스트 응용 프로그램은 매우 원시적입니다. 그것은 단지 사용자가 바탕 화면에서 마우스를 사용하거나 스마트 폰에서 손가락을 사용하여 선을 그릴 수있게 해줍니다.

모바일 Safari에서 선 그리기는 종종 매우 번쩍입니다. 한 줄의 첫 번째 비트는 실시간으로 렌더링되지만 나머지는 화면에서 손가락이 들릴 때까지 렌더링되지 않습니다.

왜 그런가?

아래 코드. (당신이 사용하는) img_update에 대한 주석 선 (볼 http://dev.opera.com/articles/view/html5-canvas-painting/과는 휴대 전화에 유동적으로 작동합니다

HTML :

<!DOCTYPE html> 
<html> 
    <head>  
      <link rel='stylesheet' href='http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css' /> 
      <script src='http://code.jquery.com/jquery-1.6.4.min.js'></script> 
      <script src='http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js'></script>    
      <style type='text/css'> 
       #canvas { border:1px solid red } 
      </style>   
    </head> 

    <body>  
      <div id='draw_page' data-role='page'> 
       <canvas id="canvas" width="500" height="350"></canvas> 
      </div> 

      <script type="text/javascript"> 
       $('#draw_page').live('pageinit', function() { 
       prep_canvas(); 
       }); 
      </script> 
    </body> 
</html> 

자바 스크립트 :

var clickX = new Array(); 
var clickY = new Array(); 
var clickDrag = new Array(); 
var paint; 
var canvas; 
var context; 

function prep_canvas() { 

canvas = $('#canvas')[0]; 
context = canvas.getContext("2d"); 

} 

$('#canvas').live('vmousedown', function(e){ 
    var mouseX = e.pageX - this.offsetLeft; 
    var mouseY = e.pageY - this.offsetTop; 

    paint = true; 
    addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop); 
    redraw(); 
}); 


$('#canvas').live('vmousemove', function(e){ 
    if(paint){ 
    addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true); 
    redraw(); 
    } 
}); 


$('#canvas').live('vmouseup', function(e){ 
    paint = false; 
}); 


function addClick(x, y, dragging) 
{ 
    clickX.push(x); 
    clickY.push(y); 
    clickDrag.push(dragging); 
} 


function redraw(){ 
    canvas.width = canvas.width; // Clears the canvas 

    context.strokeStyle = "black"; 
    context.lineJoin = "round"; 
    context.lineWidth = 2; 

    for(var i=0; i < clickX.length; i++) 
    {  
    context.beginPath(); 
    if(clickDrag[i] && i){ 
     context.moveTo(clickX[i-1], clickY[i-1]); 
    }else{ 
     context.moveTo(clickX[i]-1, clickY[i]); 
    } 
    context.lineTo(clickX[i], clickY[i]); 
    context.closePath(); 
    context.stroke(); 
    } 
} 
+0

iPhone 에뮬레이터에서 테스트하지 않는지 확인하십시오. 또한 전체 화면 모드에서 캔버스를 실행하거나 PhoneGap으로 포팅 된 앱으로 실행하면 iOS 5의 JavaScript가 iOS 4처럼 실행됩니다. – BumbleB2na

+0

또한 여러 프레임의 캔버스를 사용하여 각 프레임의 모든 것을 다시 그리지 않아도되는 방법이 있습니다 이는 모바일 브라우저에서 매우 성가신 일입니다. 두 개의 캔버스 레이어가 서로 겹치면 캔버스에 현재의 선을 너무 자주 뒤에 그려서 캔버스에 선의 가장 새로운 부분을 앞에 그릴 수 있습니다. – BumbleB2na

+0

소원 나는 더 멀리 도울 수 있었다. 여기에 대한 답변은 휴대 전화에서 시도 할 수있는 라이브 데모가 있으며이 사람이 매번 캔버스를 다시 그려야한다고 생각하지 않습니다. http://stackoverflow.com/questions/7478501/how-to-get-smooth -mouse-events-for-a-canvas-drawing-style-app – BumbleB2na

답변

0

나는이 다음에 BumbleB2na에 의해 언급 된 두 캔버스 방법에서 ...하지만 어떤 모양도 사용하지 않고 단지 선을 남겨 둡니다.)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<meta name="viewport" content="width=device-width, user-scalable=no,initial-scale = 1.0"> 
<link rel="apple-touch-icon" href="touch-icon-iphone.png" /> 
<link rel="apple-touch-icon" sizes="72x72" href="touch-icon-ipad.png" /> 
<link rel="apple-touch-icon" sizes="114x114" href="touch-icon-iphone4.png" /> 
<link rel="apple-touch-startup-image" href="startup-iphone.png"> 
<meta name="apple-mobile-web-app-capable" content="yes" /> 
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> 
<title>Untitled Document</title> 
<style type="text/css"> 
body {background:#ccc; margin:0; padding:0} 
html {margin:0; padding:0;} 
#container { position: relative; margin:0; padding:0px; } 
#canvas { border: 1px solid #000; background-color:#FFF; position:relative; width:298px; margin-left:11px; margin-top:5px; } 
</style> 
</head> 

<body onload="listen()"> 
<div id="container"> 
    <canvas id="canvas" width="298" height="298"> 
    </canvas><br/> 
    <button onclick="clearImage()">Clear</button> 
    </div> 
</body> 
<script type="text/javascript"> 
var canvas = document.getElementById('canvas'); 
if(canvas){var context= canvas.getContext('2d');} 
var tool; 
tool = new tool_pencil(); 

document.body.addEventListener('touchmove',function(event){ event.preventDefault(); },false); 
function listen(){ 
    canvas = document.getElementById('canvas'); 
    if(canvas){ 
     context= canvas.getContext('2d'); 
     context.fillStyle = "rgb(255,255,255)"; 
     context.fillRect(0, 0, canvas.width, canvas.height); 
     iphone = ((window.navigator.userAgent.match('iPhone'))||(window.navigator.userAgent.match('iPod')))?true:false; 
     ipad = (window.navigator.userAgent.match('iPad'))?true:false; 
     if(iphone||ipad){ 
      canvas.addEventListener('touchstart', ev_canvas, false); 
      canvas.addEventListener('touchend', ev_canvas, false); 
      canvas.addEventListener('touchmove', ev_canvas, false); 
     } 
     else{ 
      canvas.addEventListener('mousedown', ev_canvas, false); 
      canvas.addEventListener('mousemove', ev_canvas, false); 
      canvas.addEventListener('mouseup', ev_canvas, false); 
     } 
    } 
} 

function tool_pencil() { 
    var tool = this; 
    this.started = false; 
    this.mousedown = function (ev) { 
     context.beginPath(); 
     context.moveTo(ev._x, ev._y); 
     tool.started = true; 
    }; 

    this.mousemove = function (ev) { 
     if (tool.started) { 
      context.lineTo(ev._x, ev._y); 
      context.stroke(); 
     } 
    }; 

    this.mouseup = function (ev) { 
     if (tool.started) { 
      tool.mousemove(ev); 
      tool.started = false; 
      //img_update(); 
     } 
    }; 
    this.touchstart = function (ev) { 
     ev.preventDefault(); 
     context.beginPath(); 
     context.moveTo(ev._x, ev._y); 
     tool.started = true; 
    }; 

    this.touchmove = function (ev) { 
     ev.preventDefault(); 
     if (tool.started) { 
      context.lineTo(ev._x, ev._y); 
      context.stroke(); 
     } 
    }; 

    this.touchend = function (ev) { 
     ev.preventDefault(); 
     if (tool.started) { 
      tool.started = false; 
     } 
    }; 
} 

// The general-purpose event handler. This function just determines the mouse position relative to the canvas element. 
function ev_canvas (ev) { 
    iphone = ((window.navigator.userAgent.match('iPhone'))||(window.navigator.userAgent.match('iPod')))?true:false; 
    ipad = (window.navigator.userAgent.match('iPad'))?true:false; 
    if (((iphone)||(ipad))&&(ev.touches[0])){ //iPad 
     ev._x = ev.touches[0].clientX; 
     ev._y = ev.touches[0].clientY; 
    } 
    else if (ev.layerX || ev.layerX == 0) { // Firefox 
     ev._x = ev.layerX; 
     ev._y = ev.layerY; 
    } 
    else if (ev.offsetX || ev.offsetX == 0) { // Opera 
     ev._x = ev.offsetX; 
     ev._y = ev.offsetY; 
    } 
    // Call the event handler of the tool. 
    var func = tool[ev.type]; 
    if (func) { 
     func(ev); 
    } 
} 

function clearImage(){ 
    var yes=confirm('Clear drawing?'); 
    if(yes){ 
     context.clearRect(0, 0, canvas.width, canvas.height); 
     context.fillStyle = "rgb(255,255,255)"; 
     context.fillRect(0, 0, canvas.width, canvas.height); 
    } 
} 

</script> 
</html> 
+0

완벽하게 작동했습니다! 어떻게 찾았습니까? 바라기를 나는 다음 번에 스스로 대답을 찾을 수있다. :) – Crashalot

+1

필자는 '캔버스 페인트 프로그램'또는 비슷한 것을 검색했을 것이라고 생각하지만 터치 이벤트에 대한 직접 조작을했습니다. 다행히 도왔습니다 –

+0

안녕하세요 @ RobotWoods, 연필 도구로 그려진 선을 어떻게 부드럽게 만들 수 있는지 알고 계십니까? 사용자가 완벽하게 직선을 그리면 않는 한 들쭉날쭉하고 약간 흐린 것처럼 보이므로 부드러운 원 또는 곡선 그리기가 불가능합니다. – Crashalot

관련 문제