Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create curves from straight lines?

Tags:

java

canvas

gwt

I have straight lines on a canvas, that are defined by start and end Point(x,y).

Now I want the user to click anywhere within the line, and while dragging the mouse, the line should be formed to a curve.

I know there are quadraticCurveTo() and bezierCurveTo() methods for a Canvas. But they all require 1-2 control points. From where do I take these controlpoints if I do not present them to the user? Can I calculate them based on where the user clicks?

like image 360
membersound Avatar asked Jan 31 '26 04:01

membersound


2 Answers

How to drag a straight line into a curve

enter image description here

Given 3 points (start, end and mouse), here is how you calculate the control point that will draw a Quadratic Bezier curve between these 3 points:

        // calc a control point
        var cpX = 2*mouseX -startX/2 -endX/2;
        var cpY = 2*mouseY -startY/2 -endY/2;

And the rest is as simple as redrawing the curve whenever the user drags the mouse

        // draw a quad-curve
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.quadraticCurveTo(cpX, cpY, endX, endY);
        ctx.stroke();

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/pp7Zy/

<!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:10px; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    // get the position of the canvas
    // relative to the window
    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    // set the start and end points
    var startX=25;
    var startY=50;
    var endX=275;
    var endY=200;
    // some vars for the mouse position
    var mouseX;
    var mouseY;
    var isDragging=false;

    // set curve color and stroke-width
    ctx.strokeStyle="blue"
    ctx.fillStyle="red"
    ctx.lineWidth=5;

    // draw the startpoint, endpoint and line
    // just to get the user some reference points
    ctx.beginPath();
    ctx.moveTo(startX,startY);
    ctx.lineTo(endX,endY);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(startX,startY);
    ctx.arc(startX,startY, 10, 0, 2 * Math.PI, false);
    ctx.moveTo(endX,endY);
    ctx.arc(endX,endY, 10, 0, 2 * Math.PI, false);
    ctx.fill();


    // when the user drags the mouse draw a quad-curve
    // between the 2 points and the mouse position
    function handleMouseMove(e){
        mouseX=parseInt(e.clientX-offsetX);
        mouseY=parseInt(e.clientY-offsetY);

        // calc a control point
        var cpX = 2*mouseX -startX/2 -endX/2;
        var cpY = 2*mouseY -startY/2 -endY/2;

        ctx.clearRect(0,0,canvas.width,canvas.height);

        // draw a quad-curve
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.quadraticCurveTo(cpX, cpY, endX, endY);
        ctx.stroke();

        // draw the Start, End and Control points
        ctx.beginPath();
        ctx.moveTo(startX,startY);
        ctx.arc(startX,startY, 10, 0, 2 * Math.PI, false);
        ctx.moveTo(cpX,cpY);
        ctx.arc(cpX,cpY, 10, 0, 2 * Math.PI, false);
        ctx.moveTo(endX,endY);
        ctx.arc(endX,endY, 10, 0, 2 * Math.PI, false);
        ctx.fill();
    }

    $("#canvas").mousedown(function(e){isDragging=true;});
    $("#canvas").mouseup(function(e){isDragging=false;});
    $("#canvas").mousemove(function(e){if(isDragging){handleMouseMove(e);}});

}); // end $(function(){});
</script>

</head>

<body>
    <p>Drag mouse to create quadratic bezier</p>
    <p>that goes through the mouse position</p>
    <canvas id="canvas" width=400 height=400></canvas>
</body>
</html>
like image 72
markE Avatar answered Feb 01 '26 21:02

markE


Yes, you can just calculate them based on where the user clicks.

When the user is dragging the mouse from somewhere in the line A-B to new location A, that location X can be the single control point of a quadratic curve. Replace the line A-B with the quadratic curve A-X-B

like image 28
Simon Sarris Avatar answered Feb 01 '26 20:02

Simon Sarris