Search code examples
javascriptrotationmootools

Draggable and Rotatable Object in Javascript (Mootools)


Ok, I feel like a big dummy for not remembering remedial math(s), but for the life of me I can't recall how to do basic trigonometry (I'm a backend developer so I've literally never used this in my life).

I'm working on a draggable / rotatable object in MooTools that somewhat resembles the process of scaling and rotating images in Photoshop. Basically 5 control elements. The center drags the object, and the corner controls rotate the object. Best way to show it:

var Box = new Class({

    element: null,
    boxes: {},
    rotators: {},
    draggers: {},
    size: 10,
    controls: {
        'center': {
            x: [45, 45],
            y: [45, 45]
        },
            'topleft': {
            x: [0, 0],
            y: [0, 0]
        },
            'topright': {
            x: [90, 90],
            y: [0, 0]
        },
            'bottomleft': {
            x: [0, 0],
            y: [90, 90]
        },
            'bottomright': {
            x: [90, 90],
            y: [90, 90]
        }
    },

    initialize: function (el) {

        // the element to use
        this.element = el;

        // Create dragger boxes
        Object.each(this.controls, function (value, key, i) {

            // Boxes
            this.boxes[key] = new Element('div', {
                'id': key,
                    'class': 'box',
            }).setStyles({
                'left': value.x[0] + 'px',
                'top': value.y[0] + 'px',
                'height': this.size + 'px',
                'width': this.size + 'px'
            }).inject(this.element);

            // Draggers
            this.draggers[key] = new Drag(key, {
                limit: {
                    x: value.x,
                    y: value.y
                },
                onDrag: function (el, e) {

                    // Get this
                    el.addClass('dragging');

                    // The center moves it
                    if (el.id == 'center') {

                        // Move it around
                        el.getParent().setStyles({
                            left: (e.client.x - 45),
                            top: (e.client.y - 45)
                        });

                        // Else, rotating
                    } else {

                        // Get the current rotation of the object
                        var rotation = el.getParent().getStyle('transform');

                        // If it hasn't been set ( for whatever reason )
                        if (rotation == null) rotation = "0";

                        // The coordinates of the box clicked
                        var center = $('center').getCoordinates();
                        var coords = el.getCoordinates();

                        // Rotate
                        var rotate = (rotation.replace(/[A-Za-z\(\)$-]/g, "")).toInt() + 2;

                        // Log the rotation
                        console.log(rotate);

                        // Set the styling for the parent
                        el.getParent().setStyles({
                            'transform': 'rotate(' + rotate + 'deg)',
                                '-o-transform': 'rotate(' + rotate + 'deg)',
                                '-ms-transform': 'rotate(' + rotate + 'deg)',
                                '-webkit-transform': 'rotate(' + rotate + 'deg)'
                        });

                        // if
                    }

                },
                onComplete: function (el) {
                    el.removeClass('dragging');
                }
                // draggers
            });

            // bind it all together
        }.bind(this));

        // initialize
    }

    // box
});

new Box($('box'));

I've got the draggable part and the rotation piece in there, but I can't figure out how to calculate the angle of rotation. Can anyone help a big dummy with this problem?

Here's the playground: http://jsfiddle.net/jessejamesrichard/j4uV2/3/

A million thanks in advance.


Solution

  • This question actually doesn't have all that much to do with Mootools, since you've got all the JS/Mootools parts working completely already - all you have left is replace the +2 for the new angle with the correct one.

    To calculate the correct angle I'd recommend 'teaching' the rotation draggers their base rotation relative to the center, ie. 45, 135, 225 and 315 degrees. Then when one of them is dragged, you do Math.atan2(e.client.y - center.y, e.client.x - center.x) to get the rotation in radians relative to the center, convert it to degrees by multiplying with (180/Math.PI), add the drag corner's base rotation to it, and apply that result to the transformation.

    Should work, but I'm leaving you the challenge of the actual putting it together ;)