Skip to content

Commit

Permalink
Adds support for 3D rotations. v.0.2.0.
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit c13aa0b
Author: Jeremy Kahn <[email protected]>
Date:   Thu Aug 15 10:04:19 2013 -0500

    Removes some  in CrosshairView.

commit c116c84
Author: Jeremy Kahn <[email protected]>
Date:   Thu Aug 15 09:51:24 2013 -0500

    Shorten up redundant easing strings.

commit 313162f
Author: Jeremy Kahn <[email protected]>
Date:   Thu Aug 15 09:44:51 2013 -0500

    Rebuilds 0.2.0.

commit dcfe2a1
Author: Jeremy Kahn <[email protected]>
Date:   Thu Aug 15 09:33:27 2013 -0500

    Unbinds Cubelets when CorsshairViews are torn down.

commit 43b70dc
Author: Jeremy Kahn <[email protected]>
Date:   Wed Aug 14 17:10:10 2013 -0500

    Builds v.0.2.0.

commit 680c5c9
Author: Jeremy Kahn <[email protected]>
Date:   Wed Aug 14 17:00:29 2013 -0500

    Updates Help section to reflect Cubelet updates.

commit 41262c4
Author: Jeremy Kahn <[email protected]>
Date:   Wed Aug 14 16:25:20 2013 -0500

    Fixes rotation field alignment.

commit 6182821
Author: Jeremy Kahn <[email protected]>
Date:   Wed Aug 14 15:52:37 2013 -0500

    Syncs Cubelet and KeyframeFormView states.

commit 5f991e0
Author: Jeremy Kahn <[email protected]>
Date:   Wed Aug 14 15:34:38 2013 -0500

    Hooks up rotation changing to the UI.

commit 0447afa
Author: Jeremy Kahn <[email protected]>
Date:   Wed Aug 14 10:54:28 2013 -0500

    Rotating the Cubelet rotates the crosshair.

commit 948b20a
Author: Jeremy Kahn <[email protected]>
Date:   Tue Aug 13 15:14:52 2013 -0700

    Remove old rotation code.

commit 2387716
Author: Jeremy Kahn <[email protected]>
Date:   Tue Aug 13 15:08:47 2013 -0700

    Prevents Cubelet dragging from moving the crosshairs.  Hides/shows the Cubelets.

commit 146f729
Author: Jeremy Kahn <[email protected]>
Date:   Tue Aug 13 14:54:33 2013 -0700

    Drops some Cubelets into the app.
  • Loading branch information
jeremyckahn committed Aug 15, 2013
1 parent ea96755 commit 424aba6
Show file tree
Hide file tree
Showing 20 changed files with 118 additions and 114 deletions.
3 changes: 2 additions & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"define": true,
"publish": true,
"require": true,
"subscribe": true
"subscribe": true,
"unsubscribe": true
},

"asi": false,
Expand Down
2 changes: 1 addition & 1 deletion bin/app.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions bin/libs.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Stylie",
"version": "0.1.9",
"version": "0.2.0",
"main": "./index.html",
"dependencies": {
"shifty": "0.8.6",
Expand All @@ -11,6 +11,7 @@
"requirejs": "~2.1.6",
"jquery": "~2.0.2",
"jquery-dragon": "~0.1.4",
"jquery-cubelet": "~0.0.1",
"mustache": "~0.7.2",
"minpubsub": ""
},
Expand Down
9 changes: 5 additions & 4 deletions dev.html
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ <h2>CSS animation made easy!</h2>
<h3>The Stylie Workflow</h3>
<p>When you first open the app, you will see a little ball moving from left to right. You probably don't want to animate an image of a ball, so click the &quot;HTML&quot; tab in the control panel on the right. This textarea contains the HTML that is being animated. You can put whatever you want in here, but let's stick some text in there for starters:</p>
<pre>&lt;h1&gt;Hello there!&lt;/h1&gt;</pre>
<p>The preview updates automatically. Next, you&#x27;ll want to change the beginning and ending positions of the animation. Just click and drag the crosshairs to your liking. When your cursor is not focused on a text input, you can hold the Shift key to make rotation handles appear on the crosshairs. Click and drag the handles to modify the starting and ending rotation positions.</p>
<img src="img/shift_example.png" alt="A screenshot of Stylie while the rotation handles are shown">
<p>The preview updates automatically. Next, you&#x27;ll want to change the beginning and ending positions of the animation. Just click and drag the crosshairs to your liking. When your cursor is not focused on a text input, you can hold the Shift key to make rotation Cubelets appear over the crosshairs. Click and drag the Cubelets to modify the the X and Y rotation axes, and drag the extended rotation arm to modify the Z axis rotation.</p>
<img src="img/shift_example.png" alt="A screenshot of Stylie while the rotation Cubelets are shown">
<h3>Keyframe editing</h3>
<p>You can add, remove and edit keyframes. This is done in the &quot;Keyframes&quot; tab. When you first open Stylie, you are presented with the default keyframes. Keyframe 0 cannot be moved and has no easing properties associated with it, but all of the other keyframes do. To add a new keyframe, click the &quot;Add a Keyframe&quot; button in the upper right portion of the tab.</p>
<img src="img/keyframes_tab.png" alt="A screenshot of the Keyframes tab.">
<p>You can add as many keyframes as you'd like. You can also reorder keyframes by clicking their millisecond value and pressing the Enter key.</p>
<p>RX, RY and RZ refer to the three rotation axes. You can add as many keyframes as you'd like. You can also reorder keyframes by clicking their millisecond value and pressing the Enter key.</p>
<img src="img/keyframe_editing.png" alt="A screenshot of keyframes being edited.">
<p>You can tweak individual keyframe properties by pressing the &quot;up&quot; and &quot;down&quot; arrow keys when focusing on a property's text input. You can change individual properties' easing formula by selecting it from the dropdown next to each text input. To remove a keyframe, click the &quot;X&quot; in the upper right corner of a keyframe.</p>
<h3>Motion control</h3>
Expand Down Expand Up @@ -192,7 +192,7 @@ <h3>Key bindings</h3>
</tr>
<tr>
<td>Shift <em>(hold)</em></td>
<td>Show keyframe rotation handles</td>
<td>Show keyframe rotation Cubelets</td>
</tr>
</tbody>
</table>
Expand All @@ -205,6 +205,7 @@ <h3>This tool is open source</h3>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/jquery-dragon/src/jquery.dragon.js"></script>
<script src="bower_components/jquery-dragon/src/jquery.dragon-slider.js"></script>
<script src="bower_components/jquery-cubelet/dist/jquery.cubelet.js"></script>
<script src="bower_components/underscore/underscore.js"></script>
<script src="bower_components/backbone/backbone.js"></script>
<script src="bower_components/mustache/mustache.js"></script>
Expand Down
Binary file modified img/keyframe_editing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/keyframes_tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/shift_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Stylie",
"version": "0.1.9",
"version": "0.2.0",
"homepage": "https://github.com/jeremyckahn/stylie",
"author": "Jeremy Kahn <[email protected]>",
"description": "A CSS3 keyframe generator",
Expand Down
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ define(function () {
,'ANIMATION_LENGTH_CHANGED': 'animation-length-changed'
,'ALERT_ERROR': 'error-alert'
,'KEYFRAME_ORDER_CHANGED': 'keyframe-order-changed'
,'ROTATION_MODE_START': 'rotation-mode-start'
,'ROTATION_MODE_STOP': 'rotation-mode-stop'

,'INITIAL_ANIMATION_DURATION': 2000
,'RENDER_GRANULARITY': 100
Expand Down
6 changes: 4 additions & 2 deletions src/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ require([
? winWidth - (winWidth / (i + 1))
: 40 // TODO: Should this be a constant?
,'y': crosshairStartingY
,'r': 0
}, 'linear linear linear');
,'rX': 0
,'rY': 0
,'rZ': 0
}, 'linear');
});

app.view.canvas = new CanvasView({
Expand Down
6 changes: 4 additions & 2 deletions src/model/actor.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ define(['src/app', 'src/constants', 'src/collection/keyframes'
this.keyframe(newKeyframeMillisecond, {
'x': lastKeyframeAttrs.x + constant.NEW_KEYFRAME_X_OFFSET
,'y': lastKeyframeAttrs.y
,'r': 0
}, 'linear linear linear');
,'rX': 0
,'rY': 0
,'rZ': 0
}, 'linear');

app.view.canvas.backgroundView.update();
}
Expand Down
8 changes: 6 additions & 2 deletions src/model/keyframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ define(['src/app', 'src/constants'], function (app, constant) {
'transform':
['translate(', this.get('x')
,'px, ', this.get('y')
,'px) rotate(', this.get('r')
,'px) rotateX(', this.get('rX')
,'deg) rotateY(', this.get('rY')
,'deg) rotateZ(', this.get('rZ')
,app.config.isCenteredToPath
? 'deg) translate(-50%, -50%)'
: 'deg)'
Expand All @@ -76,7 +78,9 @@ define(['src/app', 'src/constants'], function (app, constant) {
return {
'x': this.get('x')
,'y': this.get('y')
,'r': this.get('r')
,'rX': this.get('rX')
,'rY': this.get('rY')
,'rZ': this.get('rZ')
};
}

Expand Down
88 changes: 38 additions & 50 deletions src/ui/crosshair.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ define(['src/app', 'src/constants', 'src/utils'],
return Backbone.View.extend({

'events': {
'mousedown .rotation-arm': 'onClickRotationArm'
'mousedown .rotation-control': 'onMousedownRotationControl'
}

,'initialize': function (opts) {
Expand All @@ -17,28 +17,40 @@ define(['src/app', 'src/constants', 'src/utils'],
,'dragEnd': _.bind(this.dragEnd, this)
});

this.$el.css('transform', 'rotate(0deg)');
this._$crosshairContainer = this.$el.find('.crosshair-container');
this._$cubelet = this.$el.find('.rotation-control');
this._$cubelet
.hide()
.cubeletInit()
.cubeletApplyRotationToElement(this._$crosshairContainer);

this._$cubelet.on('change', _.bind(this.onCubeletChange, this));

this._rotationModeStartHandle = subscribe(
constant.ROTATION_MODE_START, _.bind(this.onRotationModeStart, this));
this._rotationModeStopHandle = subscribe(
constant.ROTATION_MODE_STOP, _.bind(this.onRotationModeStop, this));

this.model.on('change', _.bind(this.render, this));
this._isRotating = false;
this.model.crosshairView = this;
this.render();
}

,'onClickRotationArm': function (evt) {
this.startRotating(evt.clientX, evt.clientY);
,'onMousedownRotationControl': function (evt) {
evt.stopPropagation();
}

,'onMouseupRotatorArm': function (evt) {
this.stopRotating();
,'onRotationModeStart': function () {
this._$cubelet.show();
}

,'onMouseMoveRotator': function (evt) {
this.rotateForDragDelta(evt.clientX, evt.clientY);
,'onRotationModeStop': function () {
this._$cubelet.hide();
}

,'onKeyupRotator': function (evt) {
this.stopRotating();
,'onCubeletChange': function () {
this.updateModel();
this._$cubelet.cubeletApplyRotationToElement(this._$crosshairContainer);
}

,'dragStart': function (evt, ui) {
Expand All @@ -55,16 +67,25 @@ define(['src/app', 'src/constants', 'src/utils'],
this.$el.css({
'left': this.model.get('x') + 'px'
,'top': this.model.get('y') + 'px'
,'transform': 'rotate(' + this.model.get('r') + 'deg)'
});
var rotationCoords = this._$cubelet.cubeletGetCoords();
this._$cubelet.cubeletSetCoords({
'x': this.model.get('rX')
,'y': this.model.get('rY')
,'z': this.model.get('rZ')
});
this._$cubelet.cubeletApplyRotationToElement(this._$crosshairContainer);
}

,'updateModel': function () {
var rotationCoords = this._$cubelet.cubeletGetCoords();
var pxTo = util.pxToNumber;
this.model.set({
'x': pxTo(this.$el.css('left'))
,'y': pxTo(this.$el.css('top'))
,'r': util.getRotation(this.$el)
,'rX': rotationCoords.x
,'rY': rotationCoords.y
,'rZ': rotationCoords.z
});
publish(constant.PATH_CHANGED);
app.collection.actors.getCurrent().updateKeyframeFormViews();
Expand All @@ -75,45 +96,12 @@ define(['src/app', 'src/constants', 'src/utils'],
app.view.canvas.backgroundView.update(true);
}

,'startRotating': function (startingX, startingY) {
this._previousRotationDragX = 0;
this._previousRotationDragY = 0;
this._currentRotationDragX = startingX;
this._currentRotationDragY = startingY;
this._mouseupHandler = _.bind(this.onMouseupRotatorArm, this);
this._mousemoveHandler = _.bind(this.onMouseMoveRotator, this);
this._keyupHandler = _.bind(this.onKeyupRotator, this);
this._isRotating = true;
$win
.on('mouseup', this._mouseupHandler)
.on('mousemove', this._mousemoveHandler)
.on('keyup', this._keyupHandler);
}

,'stopRotating': function () {
this._isRotating = false;
this.updateModel();
$win
.off('mouseup', this._mouseupHandler)
.off('mousemove', this._mousemoveHandler)
.off('keyup', this._keyupHandler);
}

,'rotateForDragDelta': function (currentX, currentY) {
this._previousRotationDragX = this._currentRotationDragX;
this._previousRotationDragY = this._currentRotationDragY;
this._currentRotationDragX = currentX;
this._currentRotationDragY = currentY;
var deltaX = currentX - this._previousRotationDragX;
var deltaY = currentY - this._previousRotationDragY;
var totalDelta = deltaX + deltaY;
var currentRotation = util.getRotation(this.$el);
var newRotation = currentRotation + totalDelta;
this.$el.css('transform', 'rotate(' + newRotation + 'deg)');
}

,'tearDown': function () {
this._$crosshairContainer.remove();
this._$cubelet.remove();
this.remove();
unsubscribe(this._rotationModeStartHandle);
unsubscribe(this._rotationModeStopHandle);
util.deleteAllProperties(this);
}

Expand Down
8 changes: 4 additions & 4 deletions src/ui/crosshairs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ define(['src/app', 'src/ui/crosshair'], function (app, CrosshairView) {

var CROSSHAIR_TEMPLATE = [
'<div class="crosshair">'
,'<div class="dashmark horiz"></div>'
,'<div class="dashmark vert"></div>'
,'<div class="rotation-arm">'
,'<div class="rotation-handle">'
,'<div class="crosshair-container">'
,'<div class="dashmark horiz"></div>'
,'<div class="dashmark vert"></div>'
,'</div>'
,'<div class="rotation-control"></div>'
,'</div>'].join('');

return Backbone.View.extend({
Expand Down
4 changes: 3 additions & 1 deletion src/ui/hotkey-handler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
define(['src/app'], function (app) {
define(['src/app', 'src/constants'], function (app, constant) {

return Backbone.View.extend({

Expand All @@ -18,6 +18,7 @@ define(['src/app'], function (app) {

} else if (evt.shiftKey) {
this.$el.addClass('shift-down');
publish(constant.ROTATION_MODE_START);

} else if (evt.keyCode === 67) { // "C" key
app.view.controlPane.toggle();
Expand All @@ -41,6 +42,7 @@ define(['src/app'], function (app) {

,'onKeyup': function (evt) {
this.$el.removeClass('shift-down');
publish(constant.ROTATION_MODE_STOP);
}

});
Expand Down
26 changes: 19 additions & 7 deletions src/ui/keyframe-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ define([
this.$pinnedButtonArray.append($template);
}

_.each(['x', 'y', 'r'], function (property) {
_.each(['x', 'y', 'rX', 'rY', 'rZ'], function (property) {
var template = Mustache.render(KEYFRAME_PROPERTY_TEMPLATE, {
'property': property
,'propertyLabel': property.toUpperCase()
Expand All @@ -116,7 +116,7 @@ define([
}

,'initIncrementers': function () {
_.each([this.$inputX, this.$inputY, this.$inputR], function ($el) {
_.each([this.$inputX, this.$inputY, this.$inputRX, this.$inputRY, this.$inputRZ], function ($el) {
var $input = $el.find('input');
var keyframeAttr = $input.data('keyframeattr');
this['incrementerView' + keyframeAttr.toUpperCase()] =
Expand Down Expand Up @@ -194,14 +194,23 @@ define([
,'render': function () {
this.renderHeader();

// Yikes!
//
// TODO: Make this less repetitive.
if (this.model.get('x') !== parseFloat(this.$inputX.val())) {
this.incrementerViewX.$el.val(this.model.get('x'));
}
if (this.model.get('y') !== parseFloat(this.$inputY.val())) {
this.incrementerViewY.$el.val(this.model.get('y'));
}
if (this.model.get('r') !== parseFloat(this.$inputR.val())) {
this.incrementerViewR.$el.val(this.model.get('r'));
if (this.model.get('rX') !== parseFloat(this.$inputRX.val())) {
this.incrementerViewRX.$el.val(this.model.get('rX'));
}
if (this.model.get('rY') !== parseFloat(this.$inputRY.val())) {
this.incrementerViewRY.$el.val(this.model.get('rY'));
}
if (this.model.get('rZ') !== parseFloat(this.$inputRZ.val())) {
this.incrementerViewRZ.$el.val(this.model.get('rZ'));
}
}

Expand All @@ -212,8 +221,11 @@ define([
,'updateEasingString': function () {
var xEasing = this.easeSelectViewX.$el.val();
var yEasing = this.easeSelectViewY.$el.val();
var rEasing = this.easeSelectViewR.$el.val();
var newEasingString = [xEasing, yEasing, rEasing].join(' ');
var rXEasing = this.easeSelectViewRX.$el.val();
var rYEasing = this.easeSelectViewRY.$el.val();
var rZEasing = this.easeSelectViewRZ.$el.val();
var newEasingString = [
xEasing, yEasing, rXEasing, rYEasing, rZEasing].join(' ');

this.model.setEasingString(newEasingString);

Expand Down Expand Up @@ -251,7 +263,7 @@ define([
}

,'tearDown': function () {
_.each(['X', 'Y', 'R'], function (axis) {
_.each(['X', 'Y', 'RX', 'RY', 'RZ'], function (axis) {
this['easeSelectView' + axis].tearDown();
this['incrementerView' + axis].tearDown();
this['$input' + axis].remove();
Expand Down
7 changes: 0 additions & 7 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ define(['src/app'], function (app) {
return params;
}

,'getRotation': function ($el) {
// Need to read the style attribute here, not the CSS transform property.
// $.fn.css returns the transform info in matrix format, which is harder
// to work with.
return parseFloat($el.attr('style').match(/rotate\((-*\d+)deg\)/)[1]);
}

,'deleteAllProperties': function (obj) {
_.each(obj, function (value, key) {
delete obj[key];
Expand Down
Loading

0 comments on commit 424aba6

Please sign in to comment.