Skip to content

Commit 3c4827c

Browse files
alsoRotate extension and wheel feature improved
1 parent 1cfa315 commit 3c4827c

File tree

1 file changed

+118
-84
lines changed

1 file changed

+118
-84
lines changed

jquery.ui.rotatable.js

+118-84
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,19 @@ $.widget('ui.rotatable', $.ui.mouse, {
5555
/*animate: false,
5656
animateDuration: 'slow',
5757
animateEasing: 'swing',*/
58-
rotate: function (event, ui) {}, // callback while rotating
59-
start: function (event, ui) {}, // callback when rotation starts
60-
stop: function (event, ui) {}, // callback when rotation stops
58+
start: function (event, ui) { return true; }, // callback when rotation starts
59+
rotate: function (event, ui) { return true; }, // callback while rotating
60+
stop: function (event, ui) { return true; }, // callback when rotation stops
6161
wheel: true,
62-
wheelStep: 7.5
62+
wheelingVerticalStep: null,
63+
wheelingHorizontalStep: null
6364
},
6465
plugins: {},
6566
handlers: {},
6667
elementStartAngle: 0,
6768
elementCurrentAngle: 0,
6869
elementStopAngle: 0,
6970
mouseStartAngle: 0,
70-
isRotating: false,
71-
hasRotated: false,
7271

7372
_num: function (value) {
7473
return parseFloat(value) || 0;
@@ -86,10 +85,6 @@ $.widget('ui.rotatable', $.ui.mouse, {
8685
return roundedTempNumber / factor;
8786
},
8887

89-
_mod: function (n, m) {
90-
return ((n % m) + m) % m;
91-
},
92-
9388
_canBeParent: function () {
9489
if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
9590
return false;
@@ -114,14 +109,25 @@ $.widget('ui.rotatable', $.ui.mouse, {
114109
return radians * 180 / Math.PI;
115110
},
116111

112+
_calculateAbsoluteAngle: function (exactDegrees) {
113+
if (exactDegrees > 360) {
114+
return exactDegrees - 360;
115+
}
116+
if (exactDegrees < 0) {
117+
return exactDegrees + 360;
118+
}
119+
return exactDegrees;
120+
},
121+
117122
_calculateSnap: function (degrees) {
118123
return (Math.round(degrees / this.options.snapStep) * this.options.snapStep);
119124
},
120125

121126
_getElementOffset: function () {
122-
this._do(0);
123-
var offset = this.element.offset();
124-
this._do(this.elementCurrentAngle);
127+
var element = this.element;
128+
this.perform(element, 0);
129+
var offset = element.offset();
130+
this.perform(element, this.elementCurrentAngle);
125131
return offset;
126132
},
127133

@@ -171,22 +177,25 @@ $.widget('ui.rotatable', $.ui.mouse, {
171177

172178
_calculateRotationAngleViaMousePosition: function (event) {
173179
var origin = this._calculateOrigin();
174-
var xFromOrigin = event.pageX - origin.x;
175-
var yFromOrigin = event.pageY - origin.y;
176-
var mouseAngle = this._angleInDegrees(Math.atan2(yFromOrigin, xFromOrigin));
177-
var rotateAngle = mouseAngle - this.mouseStartAngle + this.elementStartAngle;
178-
if (this.options.snap || event.shiftKey) {
179-
rotateAngle = this._calculateSnap(rotateAngle);
180+
var mouseAngle = this._calculateMouseAngle(event, origin);
181+
var rotationAngle = mouseAngle - this.mouseStartAngle + this.elementStartAngle;
182+
if (this.options.snap) {
183+
rotationAngle = this._calculateSnap(rotationAngle);
180184
}
181-
return this._mod(rotateAngle, 360);
185+
return this._calculateAbsoluteAngle(rotationAngle);
182186
},
183187

184-
_do: function (angle) {
185-
var element = this.element;
188+
_calculateMouseAngle: function (event, origin) {
189+
var horizontalOffsetFromOrigin = event.pageX - origin.x;
190+
var verticalOffsetFromOrigin = event.pageY - origin.y;
191+
return this._angleInDegrees(Math.atan2(verticalOffsetFromOrigin, horizontalOffsetFromOrigin));
192+
},
193+
194+
perform: function (element, angle) {
186195
var oldAngle = null;
187196
var currentTransform = element.css('transform');
188197
if (currentTransform === undefined) {
189-
return;
198+
return 0;
190199
}
191200
if (this._isRotationOriginPositionGiven()) {
192201
element.css('transform-origin', this._getRotationOriginPositionLeft() + 'px ' + this._getRotationOriginPositionTop() + 'px');
@@ -245,6 +254,12 @@ $.widget('ui.rotatable', $.ui.mouse, {
245254
}
246255
}
247256
element.css('transform', newTransform);
257+
return angle;
258+
},
259+
260+
_angle: function (angle) {
261+
this.elementCurrentAngle = this._calculateAbsoluteAngle(this._num(angle));
262+
return this.perform(this.element, this.elementCurrentAngle);
248263
},
249264

250265
_create: function() {
@@ -260,8 +275,7 @@ $.widget('ui.rotatable', $.ui.mouse, {
260275
this.element.bind('wheel', this.handlers._mouseWheel);
261276
}
262277
this.rotationOriginPosition(o.rotationOriginPosition);
263-
this.elementCurrentAngle = this._mod(this.options.angle || 0, 360);
264-
this._do(this.elementCurrentAngle);
278+
this._angle(o.angle);
265279
this._mouseInit();
266280
},
267281

@@ -323,18 +337,13 @@ $.widget('ui.rotatable', $.ui.mouse, {
323337
return this.element;
324338
},
325339

326-
_propagate: function (n, event) { // propagates events
327-
$.ui.plugin.call(this, n, [ event, this.ui() ]);
328-
(n !== 'rotate' && this._trigger(n, event, this.ui()));
329-
},
330-
331340
_setOption: function (key, value) {
332341
this._super(key, value);
333342
},
334343

335344
_mouseCapture: function (event) { // event handler
336-
var o = this.options;
337-
if (!this.element || this.element.disabled || o.disabled) {
345+
var element = this.element, o = this.options;
346+
if (!element || element.disabled || o.disabled) {
338347
return false;
339348
}
340349
if (o.handle) {
@@ -344,98 +353,121 @@ $.widget('ui.rotatable', $.ui.mouse, {
344353
}
345354
}
346355
else {
347-
if (event.target !== this.element[0]) {
356+
if (event.target !== element[0]) {
348357
return false;
349358
}
350359
}
351360
return true;
352361
},
353362

354363
_mouseStart: function (event) { // event handler
364+
var element = this.element;
355365
var jqHandle = this._getJqHandle();
356366
var origin = this._calculateOrigin();
357-
var startXFromOrigin = event.pageX - origin.x;
358-
var startYFromOrigin = event.pageY - origin.y;
359-
this.mouseStartAngle = this._angleInDegrees(Math.atan2(startYFromOrigin, startXFromOrigin));
367+
this.mouseStartAngle = this._calculateMouseAngle(event, origin);
360368
this.elementStartAngle = this.elementCurrentAngle;
361-
this.isRotating = true;
362-
this.hasRotated = false;
363-
this.element.addClass('ui-rotatable-rotating');
369+
element.removeClass('ui-rotatable-rotated');
370+
element.addClass('ui-rotatable-rotating');
364371
if (jqHandle.length > 0) {
365372
if (jqHandle.css('cursor') === 'grab') {
366373
jqHandle.css('cursor', 'grabbing');
367374
}
368375
}
369-
this._propagate('start', event);
370-
return true;
376+
var ui = this.ui();
377+
$.ui.plugin.call(this, 'start', [ event, ui ]); // calling extension methods
378+
return this._trigger('start', event, ui); // calling callback
371379
},
372380

373-
_mouseDrag: function (event) { // event handler
374-
if (!this.element || this.element.disabled || this.options.disabled) {
381+
_mouseDrag: function (event, originalUi) { // event handler
382+
var element = this.element, o = this.options;
383+
if (!element || element.disabled || o.disabled) {
375384
return false;
376385
}
377-
var rotateAngle = this._calculateRotationAngleViaMousePosition(event);
386+
var rotationAngle = this._calculateRotationAngleViaMousePosition(event);
378387
var previousRotateAngle = this.elementCurrentAngle;
379-
this.elementCurrentAngle = rotateAngle;
380-
if (this._propagate('rotate', event) === false) {
381-
this.elementCurrentAngle = previousRotateAngle;
382-
return false;
383-
}
388+
this.elementCurrentAngle = rotationAngle;
384389
var ui = this.ui();
385-
if (this._trigger('rotate', event, ui) === false) {
390+
$.ui.plugin.call(this, 'rotate', [ event, ui ]); // calling extension methods
391+
if (this._trigger('rotate', event, ui) === false) { // when callback returns false
386392
this.elementCurrentAngle = previousRotateAngle;
387393
return false;
388394
}
389-
else if (ui.angle.current !== rotateAngle) {
390-
rotateAngle = ui.angle.current;
391-
this.elementCurrentAngle = rotateAngle;
392-
}
393-
this._do(rotateAngle);
394-
if (previousRotateAngle !== rotateAngle) {
395-
this.hasRotated = true;
395+
if (previousRotateAngle !== this._angle(rotationAngle)) {
396+
element.addClass('ui-rotatable-rotated');
396397
}
397398
return false;
398399
},
399400

400401
_mouseStop: function (event) { // event handler
401-
if (!this.element) {
402+
var element = this.element;
403+
if (!element) {
402404
return false;
403405
}
404-
var jqHandle = this._getJqHandle();
405-
this.isRotating = false;
406406
this.elementStopAngle = this.elementCurrentAngle;
407-
this.element.removeClass('ui-rotatable-rotating');
407+
element.removeClass('ui-rotatable-rotating');
408+
var jqHandle = this._getJqHandle();
408409
if (jqHandle.length > 0) {
409410
if (jqHandle.css('cursor') === 'grabbing') {
410411
jqHandle.css('cursor', 'grab');
411412
}
412413
}
413-
this._propagate('stop', event);
414+
var ui = this.ui();
415+
$.ui.plugin.call(this, 'stop', [ event, ui ]); // calling extension methods
416+
this._trigger('stop', event, ui); // calling callback
414417
return false;
415418
},
416419

417420
_mouseWheel: function (event) { // event handler
418-
if (!this.element || this.element.disabled || this.options.disabled) {
419-
return false;
421+
var o = this.options;
422+
if (!this.element || this.element.disabled || o.disabled) {
423+
return true;
424+
}
425+
var wheelingVerticalStep = 1;
426+
var wheelingHorizontalStep = 1;
427+
var snapStep = this._num(o.snapStep);
428+
if (snapStep !== 0) {
429+
wheelingVerticalStep = snapStep;
430+
wheelingHorizontalStep = snapStep;
431+
}
432+
if (typeof o.wheelingVerticalStep === 'number') {
433+
wheelingHorizontalStep = wheelingVerticalStep = o.wheelingVerticalStep;
434+
}
435+
if (typeof o.wheelingHorizontalStep === 'number') {
436+
wheelingHorizontalStep = o.wheelingHorizontalStep;
420437
}
421-
var angle = Math.round(event.originalEvent.deltaY * this._num(this.options.wheelStep));
422-
if (this.options.snap || event.shiftKey) {
438+
var angle = 0;
439+
if (this._num(event.originalEvent.deltaY) > 0) {
440+
angle = wheelingVerticalStep;
441+
}
442+
else if (this._num(event.originalEvent.deltaY) < 0) {
443+
angle = -1 * wheelingVerticalStep;
444+
}
445+
else if (this._num(event.originalEvent.deltaX) > 0) {
446+
angle = wheelingHorizontalStep;
447+
}
448+
else if (this._num(event.originalEvent.deltaX) < 0) {
449+
angle = -1 * wheelingHorizontalStep;
450+
}
451+
if (o.snap) {
423452
angle = this._calculateSnap(angle);
424453
}
454+
if (angle === 0) {
455+
return true;
456+
}
425457
angle = this.elementCurrentAngle + angle;
426-
this.angle(angle);
427-
this._trigger('rotate', event, this.ui());
428-
return true;
458+
this._angle(angle);
459+
var ui = this.ui();
460+
$.ui.plugin.call(this, 'rotate', [ event, ui ]); // calling extension methods
461+
this._trigger('rotate', event, ui);
462+
return false; // false means preventing default
429463
},
430464

431465
angle: function (angle) { // accessor
432466
var o = this.options;
433467
if (angle === undefined) {
434468
return o.angle;
435469
}
436-
o.angle = angle;
437-
this.elementCurrentAngle = this._mod(angle, 360);
438-
this._do(o.angle);
470+
o.angle = this._angle(angle);
439471
},
440472

441473
handle: function (handle) {
@@ -477,6 +509,7 @@ $.widget('ui.rotatable', $.ui.mouse, {
477509
return {
478510
element: this.element,
479511
angle: {
512+
mouseStart: this.mouseStartAngle,
480513
start: this.elementStartAngle,
481514
current: this.elementCurrentAngle,
482515
stop: this.elementStopAngle
@@ -488,10 +521,18 @@ $.widget('ui.rotatable', $.ui.mouse, {
488521

489522
// Rotatable Extensions
490523

524+
$.ui.plugin.add('rotatable', 'animate', {
525+
526+
stop: function (event, ui) {
527+
// todo: complete here
528+
}
529+
530+
});
531+
491532
$.ui.plugin.add('rotatable', 'alsoRotate', {
492533

493-
start: function () {
494-
var that = $(this).rotatable('instance'), o = that.options;
534+
start: function (event, ui) {
535+
var instance = $(this).rotatable('instance'), o = instance.options;
495536
$(o.alsoRotate).each(function () {
496537
var element = $(this);
497538
element.data('ui-rotatable-alsorotate', {});
@@ -500,28 +541,21 @@ $.ui.plugin.add('rotatable', 'alsoRotate', {
500541
},
501542

502543
rotate: function (event, ui) {
503-
var that = $(this).rotatable('instance'), o = that.options; console.log(JSON.stringify(o, null, 2));
544+
var instance = $(this).rotatable('instance'), o = instance.options;
504545
$(o.alsoRotate).each(function () {
505546
var element = $(this);
506547
var start = element.data('ui-rotatable-alsorotate');
548+
instance.perform(element, instance.elementCurrentAngle);
507549
// todo: complete here
508550
});
509551
},
510552

511-
stop: function () {
553+
stop: function (event, ui) {
512554
$(this).removeData('ui-rotatable-alsorotate');
513555
}
514556

515557
});
516558

517-
$.ui.plugin.add('rotatable', 'animate', {
518-
519-
stop: function () {
520-
// todo: complete here
521-
}
522-
523-
});
524-
525559
// /Rotatable Extensions
526560

527561
var widgetsRotatable = $.ui.rotatable;

0 commit comments

Comments
 (0)