简体   繁体   中英

Drag a canvas element on a circle path

I would like to achieve jQuery Knob-like effect using HTML5 Canvas, but with a circle knob/cursor, instead of the stroke cursor effect that jQuery Knob does.

Based on jQuery Knob code, I was managed to connect the onMouseMove event with my circle knob/cursor so the circle knob moves according to the X and Y coordinates of where the mouse is. However I cannot "restrict" the knob to move only on/along the circle path just like this example , so if I click/mousedown inside the circle path, the circle knob moves to inside the path.

Is there any way to achieve this only using Canavas and jQuery, not Raphael like the example above?

One of my thoughts was to move the circle knob back on track (on the path) whenever mousemove event occurs outside the path (like this ). However no luck in succeeding the calculation for this. Is there any math/geometry formula I can use to achieve this?

Just a little bit of trigonometry will answer your question!

This code will find the point on a circle closest to a mouseclick.

var rads = Math.atan2(mouseY - knobCenterY, mouseX - knobCenterX);
var indicatorX=knobRadius*Math.cos(rads)+knobCenterX;
var indicatorY=knobRadius*Math.sin(rads)+knobCenterY;

This code will put an indicator on the knob closest to where the user clicks

And here is a Fiddle --- http://jsfiddle.net/m1erickson/pL5jP/

    <!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>
    <!--[if lt IE 9]><script type="text/javascript" src="../excanvas.js"></script><![endif]-->

    <style>
        body{ background-color: ivory; }
        canvas{border:1px solid red;}
    </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 circleArc=Math.PI*2;

        // drawing design properties
        var knobCenterX=100;
        var knobCenterY=100;
        var knobRadius=50;
        var knobColor="green";
        var indicatorRadius=5;
        var indicatorColor="yellow";

        Draw(canvas.width/2,1); // just to get started

        function Draw(mouseX,mouseY){
            // given mousePosition, what is the nearest point on the knob
            var rads = Math.atan2(mouseY - knobCenterY, mouseX - knobCenterX);
            var indicatorX=knobRadius*Math.cos(rads)+knobCenterX;
            var indicatorY=knobRadius*Math.sin(rads)+knobCenterY;
            // start drawing
            ctx.clearRect(0,0,canvas.width,canvas.height);
            // draw knob
            ctx.beginPath();
            ctx.arc(knobCenterX,knobCenterY,knobRadius,0,circleArc,false);
            ctx.fillStyle="ivory";
            ctx.fill();
            ctx.lineWidth=2;
            ctx.strokeStyle=knobColor;
            ctx.stroke();
            // draw indicator
            ctx.beginPath();
            ctx.arc(indicatorX, indicatorY, indicatorRadius, 0, circleArc, false);
            ctx.fillStyle = indicatorColor;
            ctx.fill();
            ctx.lineWidth = 2;
            ctx.strokeStyle = 'black';
            ctx.stroke();
        }

        function handleMouseDown(e){
          MouseX=parseInt(e.clientX-offsetX);
          MouseY=parseInt(e.clientY-offsetY);
          Draw(MouseX,MouseY);
        }

        $("#canvas").mousedown(function(e){handleMouseDown(e);});

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

    </head>

    <body>

        <br/><p>Click anywhere in the canvas to set the knob indicator</p><br/>
        <canvas id="canvas" width=200 height=200></canvas>

    </body>
    </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM