Search code examples
javascriptmathdrag-and-droplogicfarbtastic

Move object around circle javascript


enter image description here

Above is just image to get a link for fiddle its role is nothing in question.

I am trying to move an object along circle (actually a rectangular canvas with border-radius=100% so behaving as circle). But only able to move it and not able to resrict the movemment in the circle)

Here is my JS Fiddle Link. Note: Please scroll down in js code and view the only code written under following comments

//---- Code of interest begins-----// to //---code of interest ends---//

My desired output will be like this wheel farbtastic. Though it is open source yet i have been unable to use its mouse move event code in my colour wheel

While trying to search I found Canvas move object in circle but I can not use it because i do not know d and do not know what is across. So unable to get theta with arccos(1-(d/r)^2/2)


Solution

  • The easiest way I think is to calculate the angle and apply css3 rotate transform to an element.

    I let you the example here..

    Read the comments, specially on the rotate() function

    http://jsfiddle.net/Z37FF/3/

    HTML

        <body>
            <div id="circle">
            <div id="circle-in"></div>
            <div id="picker">
            <div id="picker-circle"></div>
            </div>
            </div>  
        </body>
    

    CSS

        #circle{
            position: relative;
            width: 300px;
            height: 300px;
            border-radius: 50%;
            background: #000;
        }
    
        #circle-in{
            position: absolute;
            top: 35px;
            left: 35px;
            width: 230px;
            height: 230px;
            border-radius: 50%;
            background: #fff;
        }
    
        #picker{
            position: absolute;
            top: 50%;
            left: 50%;
            height: 30px;
            margin-top: -15px;
            width: 50%;
    
            /* important: sets the transform origin to the center of the circle */
            transform-origin: center left;
        }
    
        #picker-circle{
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background: #fff;
            margin: 0 3px 0 auto;
            cursor: move;
        }
    

    JS

    document.addEventListener('DOMContentLoaded', function(){
        var circle = document.getElementById('circle'),
            picker = document.getElementById('picker'),
            pickerCircle = picker.firstElementChild,
            rect = circle.getBoundingClientRect(),
    
            center = {
                x: rect.left + rect.width / 2,
                y: rect.top + rect.height / 2
            },
    
            rotate = function(x, y){
                var deltaX = x - center.x,
                    deltaY = y - center.y,
    
                // The atan2 method returns a numeric value between -pi and pi representing the angle theta of an (x,y) point.
                // This is the counterclockwise angle, measured in radians, between the positive X axis, and the point (x,y).
                // Note that the arguments to this function pass the y-coordinate first and the x-coordinate second.
                // atan2 is passed separate x and y arguments, and atan is passed the ratio of those two arguments.
                // * from Mozilla's MDN
    
                // Basically you give it an [y, x] difference of two points and it give you back an angle
                // The 0 point of the angle is right (the initial position of the picker is also right)
    
                    angle = Math.atan2(deltaY, deltaX) * 180 / Math.PI
    
                // Math.atan2(deltaY, deltaX) => [-PI +PI]
                // We must convert it to deg so...
                // / Math.PI => [-1 +1]
                // * 180 => [-180 +180]
    
                return angle
            },
    
            // DRAGSTART
            mousedown = function(event){
                event.preventDefault()
                document.body.style.cursor = 'move'
                mousemove(event)
                document.addEventListener('mousemove', mousemove)
                document.addEventListener('mouseup', mouseup)
            },
    
            // DRAG
            mousemove = function(event){
                picker.style.transform = 'rotate(' + rotate(event.x, event.y) + 'deg)'
            },
    
            // DRAGEND
            mouseup = function(){
                document.body.style.cursor = null;
                document.removeEventListener('mouseup', mouseup)
                document.removeEventListener('mousemove', mousemove)
            }
    
    
    
        // DRAG START
        pickerCircle.addEventListener('mousedown', mousedown)
    
        // ENABLE STARTING THE DRAG IN THE BLACK CIRCLE
        circle.addEventListener('mousedown', function(event){
            if(event.target == this) mousedown(event)
        })
    })