Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS tween branch #49

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
272 changes: 241 additions & 31 deletions build/tina.js

Large diffs are not rendered by default.

61 changes: 35 additions & 26 deletions build/tina.min.js

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions examples/css/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Tina - CSS</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="../styles.css">
<style type="text/css">
#demodiv {
position: absolute;
left: 50px;
top: 50px;
height: 100px;
width: 100px;
background-color: aquamarine;
}
</style>
</head>
<body>
<span class="title"> tina - CSS</span>
<div class="democontainer">
<div id="demodiv"></div>
</div>

<!--<script src="../../build/tina.js" type="text/javascript"></script>-->
<script src="https://rawgit.com/Wizcorp/tina/master/build/tina.min.js" type="text/javascript"></script>-->
<script src="index.js" type="text/javascript"></script>
<a href="http://jsfiddle.net/cstoquer/k8dghonL/"> jsfiddle </a>
</body>
</html>
32 changes: 32 additions & 0 deletions examples/css/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

var demoDiv = document.getElementById('demodiv');

//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

TINA.onUpdate(function update(t, dt) {
// At this point, all my tweens are up to date for the current iteration
});

//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

var duration = 2000;
var bouncing = 4;

// NOTE: The available CSS properties options are currently:
// top, bottom, left, right, width, height and opacity
var csstween = new TINA.CSSTween(demodiv, ['top', 'width', 'opacity', 'height'])
.from({
top: 50,
width: 100,
height: 100,
opacity: 1
})
.to({
top: 200,
width: 200,
height: 200,
opacity: 0
}, 2000)
.iterations(Infinity)
.pingpong(true)
.start();
9 changes: 8 additions & 1 deletion examples/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ body {
font-family: verdana;
}

.democontainer,
canvas {
margin: 20px auto;
border-radius: 5px;
box-shadow: 1px 1px 10px #333;
display: block;
}

.democontainer {
position: relative;
width: 400px;
height: 400px;
}

a {
color: #AAA;
}
Expand Down Expand Up @@ -40,4 +47,4 @@ a:active {

.hidden {
display: none;
}
}
30 changes: 23 additions & 7 deletions src/AbstractTween.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
var Transition = require('./Transition');
var TransitionRelative = require('./TransitionRelative');

var easingFunctions = require('./easing');
var interpolationFunctions = require('./interpolation');
var Transition = require('./Transition');
var TransitionCSS = require('./TransitionCSS');
var TransitionRelative = require('./TransitionRelative');
var easingFunctions = require('./easing');
var interpolationFunctions = require('./interpolation');


// Temporisation, used for waiting
Expand Down Expand Up @@ -45,6 +45,13 @@ function AbstractTween(object, properties) {
}
}

// Determine if we are are tweening a CSS object
// The undefined check is to avoid a crash when running Tina in
// environments where the DOM is not available, such as in node.
if (typeof CSSStyleDeclaration !== 'undefined') {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if it is undefined? What should the behavior be?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of the check is actually to prevent a crash when running Tina outside the browser, in node (i.e. benchmarking). I can't actually imagine a case where CSSStyleDeclaration would be undefined (and required) in a typical use case. I have to admit, I haven't written a lot of code where the same code path has to run both in the front end and backend - so if there is a more appropriate pattern to avoid these issues, I'd be happy to hear it. :)

Either way, I will make that clearer in the comment.

this._css = (object instanceof CSSStyleDeclaration) ? true : false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it's not necessary to keep the _css`` properties onthis``` since the variable is only used locally

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry actually no, my bad

}

// Properties to tween
this._properties = properties;

Expand Down Expand Up @@ -155,7 +162,16 @@ AbstractTween.prototype.to = function (toObject, duration, easing, easingParam,
// Getting previous transition ending as the beginning for the new transition
var fromObject = this._getLastTransitionEnding();

var TransitionConstructor = (this._relative === true) ? TransitionRelative : Transition;
// Determine the appropriate transition constructor for the given object
var TransitionConstructor = null;
if (this._relative === true) {
TransitionConstructor = TransitionRelative;
} else if (this._css === true) {
TransitionConstructor = TransitionCSS;
} else {
TransitionConstructor = Transition;
}

var transition = new TransitionConstructor(
this._properties,
fromObject,
Expand Down Expand Up @@ -220,4 +236,4 @@ AbstractTween.prototype._validate = function () {
}

return true;
};
};
27 changes: 27 additions & 0 deletions src/CSSMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
*
* Maps the given properties to a unit type
*
* Currently only supports basic CSS methods - in order to support more advance CSS3 properties, such as
* transform, we will need to modify the way the properties array is handled and moved through the system.
* In the case of CSS methods such as "transform: rotate(Xdeg)" - the mapping will need to be more advanced,
* possibly adding a prefix / suffix mapping.
*
* @param {array} properties - Properties of the object to tween
* @returns {array} - The suffix mapped to the property name
*
*/
module.exports = function (properties) {

var cssMap = { height: 'px', width: 'px', top: 'px', left: 'px', bottom: 'px', right: 'px', opacity: '' };
var mapping = {};

for (var i = 0; i < properties.length; i++) {
if (properties[i] in cssMap) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should we do if the property is not in cssMap?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very good question. I guess the most appropriate course of action would be to throw an error. If we can't provide a CSS Tween for that given property, it probably shouldn't fail silently.

However, having a quick look through the source for Tina I can't see any other instances of a thrown error. So I'm not sure what the site policy for error handling is. Any thoughts would be appreciated.

var property = properties[i];
mapping[property] = cssMap[property];
}
}

return mapping;
};
13 changes: 6 additions & 7 deletions src/CSSTween.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var Tween = require('./Tween');

var NestedTween = require('./NestedTween');
/**
*
* @classdesc
Expand All @@ -17,10 +16,10 @@ function CSSTween(object, properties) {

var tweenedObject = (typeof object === 'string') ? document.querySelector(object) : object;

// TODO: change inheritance to NestedTween for support of css transform properties
// and add an internal method for replacing unprefixed properties by prefixed properties when necessary
Tween.call(this, tweenedObject.style, properties);
// TODO: Add an internal method for replacing unprefixed properties by prefixed properties when necessary
NestedTween.call(this, tweenedObject.style, properties);
}
CSSTween.prototype = Object.create(Tween.prototype);

CSSTween.prototype = Object.create(NestedTween.prototype);
CSSTween.prototype.constructor = CSSTween;
module.exports = CSSTween;
module.exports = CSSTween;
135 changes: 135 additions & 0 deletions src/TransitionCSS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Provides transitions for CSS style objects
var CSSMap = require('./CSSMap');

// One property
function update(object, t) {
var p = this.prop;
object[p] = (this.from[p] * (1 - t) + this.to[p] * t) + this.cssMap[p];
}

// Several Properties
function updateP(object, t) {
var q = this.props;
for (var i = 0; i < this.props.length; i += 1) {
var p = q[i];
object[p] = (this.from[p] * (1 - t) + this.to[p] * t) + this.cssMap[p];
}
}

// Interpolation
function updateI(object, t) {
var p = this.prop;
object[p] = this.interps[p](t, this.from[p], this.to[p], this.interpParams[p]) + this.cssMap[p];
}

// Interpolation
// Several Properties
function updatePI(object, t) {
var q = this.props;
for (var i = 0; i < q.length; i += 1) {
var p = q[i];
object[p] = this.interps[p](t, this.from[p], this.to[p], this.interpParams[p]) + this.cssMap[p];
}
}

// Easing
function updateE(object, t) {
t = this.easing(t, this.easingParam);
var p = this.prop;
object[p] = (this.from[p] * (1 - t) + this.to[p] * t) + this.cssMap[p];
}

// Easing
// Several Properties
function updatePE(object, t, interpFunc) {
var q = this.props;
t = this.easing(t, this.easingParam);
for (var i = 0; i < q.length; i += 1) {
var p = q[i];
object[p] = (this.from[p] * (1 - t) + this.to[p] * t) + this.cssMap[p];
}
}

// Easing
// Interpolation
function updateIE(object, t, interpFunc) {
var p = this.prop;
t = this.easing(t, this.easingParam);
object[p] = this.interps[p](t, this.from[p], this.to[p], this.interpParams[p]) + this.cssMap[p];
}

// Easing
// Interpolation
// Several Properties
function updatePIE(object, t, interpFunc) {
var q = this.props;
t = this.easing(t, this.easingParam);
for (var i = 0; i < q.length; i += 1) {
var p = q[i];
object[p] = this.interps[p](t, this.from[p], this.to[p], this.interpParams[p]) + this.cssMap[p];
}
}


var updateMethods = [
[
[update, updateP],
[updateI, updatePI]
], [
[updateE, updatePE],
[updateIE, updatePIE]
]
];

function TransitionCSS(properties, from, to, start, duration, easing,
easingParam, interpolations, interpolationParams) {

this.start = start;
this.end = start + duration;
this.duration = duration;
this.from = from;
this.to = to;
this.cssMap = CSSMap(properties);

// Easing flag - Whether an easing function is used
// 0 => Using linear easing
// 1 => Using custom easing
var easingFlag;
if (easing) {
easingFlag = 1;
this.easing = easing;
this.easingParam = easingParam;
} else {
easingFlag = 0;
}

// Interpolation flag - Whether an interpolation function is used
// 0 => No Interpolation
// 1 => At least one interpolation
var interpFlag;
if (interpolations === null) {
interpFlag = 0;
} else {
interpFlag = 1;
this.interps = interpolations;
this.interpParams = interpolationParams || {};
}

// Property flag - Whether the transition has several properties
// 0 => Only one property
// 1 => Several properties
var propsFlag;
if (properties.length === 1) {
propsFlag = 0;
this.prop = properties[0]; // string
this.props = null;
} else {
propsFlag = 1;
this.prop = null;
this.props = properties; // array
}

this.update = updateMethods[easingFlag][interpFlag][propsFlag];
}

module.exports = TransitionCSS;
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var TINA = require('./TINA.js');

// TINA.CSSTween = require('./CSSTween');
TINA.CSSTween = require('./CSSTween');
TINA.Delay = require('./Delay');
TINA.BriefExtension = require('./BriefExtension');
TINA.BriefPlayable = require('./BriefPlayable');
Expand Down