2014-02-06 11 views
2

내 캔버스에서 그림을 그리려면 페인트에서 타원 옵션과 같은 것을 사용하고 싶습니다. 나는 이것을 부분적으로 성취했다. 문제는 내가 원의 반경을 얻을 수 없다는 것입니다. 현재 15로 하드 코딩했습니다. 또한 정확한 원이 아닌 타원 (페인트와 동일)을 그립니다. 이것은 마우스 이벤트를 사용하여 캔버스에서 원을 그리는 데 필요한 코드입니다. 위에서 언급 한 요구 사항을 달성하기 위해 코드를 도와주세요.마우스 이벤트를 사용하여 HTML5 캔버스에서 원/타원 그리기

function tool_circle() { 
     var tool = this; 
     this.started = false; 

     this.mousedown = function (ev) { 
      tool.started = true; 
      tool.x0 = ev._x; 
      tool.y0 = ev._y; 
     }; 

     this.mousemove = function (ev) { 
      if (!tool.started) { 
       return; 
      } 

      context.fillStyle = 'red'; 

      var distance = Math.sqrt(Math.pow(tool.x0 - ev._x, 2) + Math.pow(tool.y0 - ev._y)); 
      context.beginPath(); 

      context.arc(tool.x0, tool.y0,15, 0, Math.PI * 2, false); 
      context.stroke(); 
      context.fill(); 
     }; 

     this.mouseup = function (ev) { 
      if (tool.started) { 
       tool.mousemove(ev); 
       tool.started = false; 
       img_update(); 
      } 
     }; 
    } 

답변

2

다음은 타원을 드래그하는 방법의 예입니다.

데모 : http://jsfiddle.net/m1erickson/3SFJy/

enter image description here

타원형 드래그 앤 그릴 2 개 베 지어 곡선을 사용하여 예제 코드 : 베 지어 곡선을 사용하여 내가 그러나 마르크의 대답과 같은 비슷한 것

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 

<style> 
body{ background-color: ivory; padding:0px;} 
#canvas{ border:1px solid blue; } 
</style> 

<script> 
$(function(){ 

    var canvas=document.getElementById("canvas"); 
    var ctx=canvas.getContext("2d"); 
    var canvasOffset=$("#canvas").offset(); 
    var offsetX=canvasOffset.left; 
    var offsetY=canvasOffset.top; 
    var startX; 
    var startY; 
    var isDown=false; 

    function drawOval(x,y){ 
     ctx.clearRect(0,0,canvas.width,canvas.height); 
     ctx.beginPath(); 
     ctx.moveTo(startX, startY + (y-startY)/2); 
     ctx.bezierCurveTo(startX, startY, x, startY, x, startY + (y-startY)/2); 
     ctx.bezierCurveTo(x, y, startX, y, startX, startY + (y-startY)/2); 
     ctx.closePath(); 
     ctx.stroke(); 
    } 

    function handleMouseDown(e){ 
     e.preventDefault(); 
     e.stopPropagation(); 
     startX=parseInt(e.clientX-offsetX); 
     startY=parseInt(e.clientY-offsetY); 
     isDown=true; 
    } 

    function handleMouseUp(e){ 
     if(!isDown){ return; } 
     e.preventDefault(); 
     e.stopPropagation(); 
     isDown=false; 
    } 

    function handleMouseOut(e){ 
     if(!isDown){ return; } 
     e.preventDefault(); 
     e.stopPropagation(); 
     isDown=false; 
    } 

    function handleMouseMove(e){ 
     if(!isDown){ return; } 
     e.preventDefault(); 
     e.stopPropagation(); 
     mouseX=parseInt(e.clientX-offsetX); 
     mouseY=parseInt(e.clientY-offsetY); 
     drawOval(mouseX,mouseY); 
    } 

    $("#canvas").mousedown(function(e){handleMouseDown(e);}); 
    $("#canvas").mousemove(function(e){handleMouseMove(e);}); 
    $("#canvas").mouseup(function(e){handleMouseUp(e);}); 
    $("#canvas").mouseout(function(e){handleMouseOut(e);}); 

}); // end $(function(){}); 
</script> 
</head> 
<body> 
    <h4>Drag to create a circle or oval</h4> 
    <canvas id="canvas" width=300 height=300></canvas> 
</body> 
</html> 
+0

안녕 @markE를 얻기 위해 하나의 반경하지만, 동적 스케일링을 사용하여, 나는 동일한 일을 할 모바일 앱 (Phonegap wrapped) 터치 이벤트. mouseup, mousemove를 touchstart, touchmove events로 대체하여 코드를 시험해 보았습니다. 이러한 이벤트는 로그를 볼 수 있지만 타원/원을 그릴 수 없기 때문에 트리거됩니다. 터치 이벤트를 위해 내가해야 할 특별한 것이 있습니까?사전에 감사드립니다 (저는 캔버스를 처음 사용합니다 :)) – hashcoder

5

을 것이다 타원을 그리지 만, 아마 필요한 반경을 줄 수는 없습니다. 이를 위해

수동 타원을 그리는 기능

이 필요하고, 그것은 오히려 간단합니다 -

이 기능은 그 경계 내에서 정확히를 타원 을 코너 시작점과과 끝 지점을 가지고 그릴 것입니다 :

Live demo

Snapshot from demo

function drawEllipse(x1, y1, x2, y2) { 

    var radiusX = (x2 - x1) * 0.5, /// radius for x based on input 
     radiusY = (y2 - y1) * 0.5, /// radius for y based on input 
     centerX = x1 + radiusX,  /// calc center 
     centerY = y1 + radiusY, 
     step = 0.01,     /// resolution of ellipse 
     a = step,     /// counter 
     pi2 = Math.PI * 2 - step; /// end angle 

    /// start a new path 
    ctx.beginPath(); 

    /// set start point at angle 0 
    ctx.moveTo(centerX + radiusX * Math.cos(0), 
       centerY + radiusY * Math.sin(0)); 

    /// create the ellipse  
    for(; a < pi2; a += step) { 
     ctx.lineTo(centerX + radiusX * Math.cos(a), 
        centerY + radiusY * Math.sin(a)); 
    } 

    /// close it and stroke it for demo 
    ctx.closePath(); 
    ctx.strokeStyle = '#000'; 
    ctx.stroke(); 
} 

데모는 타원이 정확히 그 안에 있음을 보여주기 위해 사각형 영역을 표시합니다.

당신은 당신이 할 수있는 타원을 그려 보자됩니다 마우스 조작을 처리하기 위해 그리기 :

var canvas = document.getElementById('myCanvas'), 
    ctx = canvas.getContext('2d'), 
    w = canvas.width, 
    h = canvas.height, 
    x1,     /// start points 
    y1, 
    isDown = false;  /// if mouse button is down 

/// handle mouse down  
canvas.onmousedown = function(e) { 

    /// get corrected mouse position and store as first point 
    var rect = canvas.getBoundingClientRect(); 
    x1 = e.clientX - rect.left; 
    y1 = e.clientY - rect.top; 
    isDown = true; 
} 

/// clear isDown flag to stop drawing 
canvas.onmouseup = function() { 
    isDown = false; 
} 

/// draw ellipse from start point 
canvas.onmousemove = function(e) { 

    if (!isDown) return; 

    var rect = canvas.getBoundingClientRect(), 
     x2 = e.clientX - rect.left, 
     y2 = e.clientY - rect.top; 

    /// clear canvas 
    ctx.clearRect(0, 0, w, h); 

    /// draw ellipse 
    drawEllipse(x1, y1, x2, y2); 
} 

팁은 주 캔버스의 상단에 상단 캔버스를 작성하고 도면을 할 수 있습니다 거기 자체. 마우스 버튼을 놓으면 드로잉을 메인 캔버스로 전송합니다. 이렇게하면 새 도형을 그릴 때 모든 것을 다시 그릴 필요가 없습니다.

희망이 도움이됩니다.

+0

데모를 보았습니다. 그러나 그것은 하나의 원을 그리는 것을 허용합니다. 캔버스에 원하는만큼 서클을 그릴 수 있습니까? – Pawan

+1

@ user130004 물론 끌어서 그리는 데 사용할 캔버스를 맨 위에 추가하면됩니다. mouseup이 캔버스를 이미 캔버스의 상단에있는 메인 캔버스로 다시 그릴 때. 모든 것을 다시 그리기 원한다면 원 데이터를 배열 (중심 x, t 및 반지름)에 저장하고 그 데이터를 다시 그릴 수 있습니다. – K3N

+1

@ user130004 위 코드의 수정은 다음과 같습니다. http://jsfiddle.net/37vge/21/ – K3N

0

다음은 마우스 드래그를 사용하여 타원을 캔버스에 그립니다.

그것은 타원 효과 :

https://jsfiddle.net/richardcwc/wdf9cocz/

//Canvas 
 
var canvas = document.getElementById('canvas'); 
 
var ctx = canvas.getContext('2d'); 
 
//Variables 
 
var scribble_canvasx = $(canvas).offset().left; 
 
var scribble_canvasy = $(canvas).offset().top; 
 
var scribble_last_mousex = scribble_last_mousey = 0; 
 
var scribble_mousex = scribble_mousey = 0; 
 
var scribble_mousedown = false; 
 

 
//Mousedown 
 
$(canvas).on('mousedown', function(e) { 
 
    scribble_last_mousex = parseInt(e.clientX-scribble_canvasx); 
 
\t scribble_last_mousey = parseInt(e.clientY-scribble_canvasy); 
 
    scribble_mousedown = true; 
 
}); 
 

 
//Mouseup 
 
$(canvas).on('mouseup', function(e) { 
 
    scribble_mousedown = false; 
 
}); 
 

 
//Mousemove 
 
$(canvas).on('mousemove', function(e) { 
 
    scribble_mousex = parseInt(e.clientX-scribble_canvasx); 
 
\t scribble_mousey = parseInt(e.clientY-scribble_canvasy); 
 
    if(scribble_mousedown) { 
 
     ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas 
 
     //Save 
 
     ctx.save(); 
 
     ctx.beginPath(); 
 
     //Dynamic scaling 
 
     var scalex = 1*((scribble_mousex-scribble_last_mousex)/2); 
 
     var scaley = 1*((scribble_mousey-scribble_last_mousey)/2); 
 
     ctx.scale(scalex,scaley); 
 
     //Create ellipse 
 
     var centerx = (scribble_last_mousex/scalex)+1; 
 
     var centery = (scribble_last_mousey/scaley)+1; 
 
     ctx.arc(centerx, centery, 1, 0, 2*Math.PI); 
 
     //Restore and draw 
 
     ctx.restore(); 
 
     ctx.strokeStyle = 'black'; 
 
     ctx.lineWidth = 5; 
 
     ctx.stroke(); 
 
    } 
 
    //Output 
 
    $('#output').html('current: '+scribble_mousex+', '+scribble_mousey+'<br/>last: '+scribble_last_mousex+', '+scribble_last_mousey+'<br/>mousedown: '+scribble_mousedown); 
 
});
canvas { 
 
    cursor: crosshair; 
 
    border: 1px solid #000000; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<canvas id="canvas" width="800" height="500"></canvas> 
 
<div id="output"></div>

관련 문제