From c6b6a07d06df82765462a63e7ea792e6df6309a9 Mon Sep 17 00:00:00 2001
From: Adam Bradley
Date: Sun, 26 Apr 2015 11:59:44 -0500
Subject: [PATCH] collide updates
---
ionic/collide/animation-process.js | 128 +-----------------
ionic/collide/animation-start.js | 4 +-
ionic/collide/animation-stop.js | 2 +-
ionic/collide/animation.js | 2 +
ionic/collide/calculate-unit-ratios.js | 127 +++++++++++++++++
ionic/collide/collide.js | 2 +-
ionic/collide/complete-call.js | 6 +-
ionic/collide/css.js | 2 +-
ionic/collide/easing.js | 2 +-
ionic/collide/tick.js | 7 +-
.../components/app/test/animations/main.html | 5 +-
ionic/components/app/test/animations/main.js | 42 ++++--
12 files changed, 179 insertions(+), 150 deletions(-)
create mode 100644 ionic/collide/calculate-unit-ratios.js
diff --git a/ionic/collide/animation-process.js b/ionic/collide/animation-process.js
index eb04b0558e..756937a821 100644
--- a/ionic/collide/animation-process.js
+++ b/ionic/collide/animation-process.js
@@ -1,9 +1,11 @@
-/* Forked from Velocity.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import * as util from 'ionic/util/util'
import {Collide} from './collide'
import {CSS} from './css'
import {getEasing} from './easing'
+import {calculateUnitRatios} from './calculate-unit-ratios'
+
const data = Collide.data;
@@ -587,128 +589,6 @@ export function animationProcess(action, elements, elementsIndex, options, prope
}
- /***************************
- parsePropertyValue(), Unit Ratio Calculation
- ***************************/
-
- /* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of
- %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order
- for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred
- from a previous call, startValue may also not be in pixels. Unit conversion logic therefore consists of two steps:
- 1) Calculating the ratio of %/em/rem/vh/vw relative to pixels
- 2) Converting startValue into the same unit of measurement as endValue based on these ratios. */
- /* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property,
- setting values with the target unit type then comparing the returned pixel value. */
- /* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead
- of batching the SETs and GETs together upfront outweights the potential overhead
- of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */
- /* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */
- function calculateUnitRatios() {
-
- /**************************************************************
- parsePropertyValue(), calculateUnitRatios(), Same Ratio Checks
- **************************************************************/
-
- /* The properties below are used to determine whether the element differs sufficiently from this call's
- previously iterated element to also differ in its unit conversion ratios. If the properties match up with those
- of the prior element, the prior element's conversion ratios are used. Like most optimizations in Collide,
- this is done to minimize DOM querying. */
- var sameRatioIndicators = {
- myParent: element.parentNode || document.body, /* GET */
- position: CSS.getPropertyValue(element, 'position'), /* GET */
- fontSize: CSS.getPropertyValue(element, 'fontSize') /* GET */
- };
-
- /* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */
- var samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent));
-
- /* Determine if the same em ratio can be used. em is relative to the element's fontSize. */
- var sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize);
-
- /* Store these ratio indicators call-wide for the next element to compare against. */
- callUnitConversionData.lastParent = sameRatioIndicators.myParent;
- callUnitConversionData.lastPosition = sameRatioIndicators.position;
- callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize;
-
-
- /**********************************************************************
- parsePropertyValue(), calculateUnitRatios(), Element-Specific Units
- **********************************************************************/
-
- var measurement = 100,
- unitRatios = {};
-
- if (!sameEmRatio || !samePercentRatio) {
- var dummy = data(element).isSVG ? document.createElementNS('http://www.w3.org/2000/svg', 'rect') : document.createElement('div');
-
- Collide.init(dummy);
- sameRatioIndicators.myParent.appendChild(dummy);
-
- /* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped.
- Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */
- /* Note: Overflow must be also be controlled for per-axis since the overflow property overwrites its per-axis values. */
- var cssPropNames = [ 'overflow', 'overflowX', 'overflowY' ];
- for (var x = 0; x < overflows.length; x++) {
- Collide.CSS.setPropertyValue(dummy, cssPropNames[x], 'hidden');
- }
-
- Collide.CSS.setPropertyValue(dummy, 'position', sameRatioIndicators.position);
- Collide.CSS.setPropertyValue(dummy, 'fontSize', sameRatioIndicators.fontSize);
- Collide.CSS.setPropertyValue(dummy, 'boxSizing', 'content-box');
-
- /* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */
- cssPropNames = [ 'minWidth', 'maxWidth', 'width', 'minHeight', 'maxHeight', 'height' ];
- for (var x = 0; x < overflows.length; x++) {
- Collide.CSS.setPropertyValue(dummy, cssPropNames[x], measurement + '%');
- }
-
- /* paddingLeft arbitrarily acts as our proxy property for the em ratio. */
- Collide.CSS.setPropertyValue(dummy, 'paddingLeft', measurement + 'em');
-
- /* Divide the returned value by the measurement to get the ratio between 1% and 1px. Default to 1 since working with 0 can produce Infinite. */
- unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, 'width', null, true)) || 1) / measurement; /* GET */
- unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, 'height', null, true)) || 1) / measurement; /* GET */
- unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, 'paddingLeft')) || 1) / measurement; /* GET */
-
- sameRatioIndicators.myParent.removeChild(dummy);
-
- } else {
- unitRatios.emToPx = callUnitConversionData.lastEmToPx;
- unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth;
- unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight;
- }
-
-
- /**********************************************************************
- parsePropertyValue(), calculateUnitRatios(), Element-Agnostic Units
- ***********************************************************************/
-
- /* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked
- once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time
- that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null,
- so we calculate it now. */
- if (callUnitConversionData.remToPx === null) {
- /* Default to browsers' default fontSize of 16px in the case of 0. */
- callUnitConversionData.remToPx = parseFloat(CSS.getPropertyValue(document.body, 'fontSize')) || 16; /* GET */
- }
-
- /* Similarly, viewport units are %-relative to the window's inner dimensions. */
- if (callUnitConversionData.vwToPx === null) {
- callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */
- callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */
- }
-
- unitRatios.remToPx = callUnitConversionData.remToPx;
- unitRatios.vwToPx = callUnitConversionData.vwToPx;
- unitRatios.vhToPx = callUnitConversionData.vhToPx;
-
- if (Collide.debug >= 1) console.log('Unit ratios: ' + JSON.stringify(unitRatios), element);
-
- return unitRatios;
-
- } // END: calculateUnitRatios()
-
-
/****************************************
parsePropertyValue(), Unit Conversion
*****************************************/
@@ -733,7 +613,7 @@ export function animationProcess(action, elements, elementsIndex, options, prope
} else {
/* By this point, we cannot avoid unit conversion (it's undesirable since it causes layout thrashing).
If we haven't already, we trigger calculateUnitRatios(), which runs once per element per call. */
- elementUnitConversionData = elementUnitConversionData || calculateUnitRatios();
+ elementUnitConversionData = elementUnitConversionData || calculateUnitRatios(element, callUnitConversionData);
/* The following RegEx matches CSS properties that have their % values measured relative to the x-axis. */
/* Note: W3C spec mandates that all of margin and padding's properties (even top and bottom) are %-relative to the *width* of the parent element. */
diff --git a/ionic/collide/animation-start.js b/ionic/collide/animation-start.js
index 5b5a978ed9..3769463202 100644
--- a/ionic/collide/animation-start.js
+++ b/ionic/collide/animation-start.js
@@ -1,4 +1,4 @@
-/* Forked from Collide.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import {Collide} from './collide'
import {animationProcess} from './animation-process'
@@ -50,7 +50,7 @@ export function animationStart(elements, options, propertiesMap) {
if (elements && elements.length) {
for (var i = 0, l = elements.length; i < l; i++) {
- if (elements[i] && elements[i].parentElement) {
+ if (elements[i]) {
promises.push(
animationProcess('start', elements, i, options, propertiesMap, callUnitConversionData, call)
diff --git a/ionic/collide/animation-stop.js b/ionic/collide/animation-stop.js
index c3d1315401..8f68a01a92 100644
--- a/ionic/collide/animation-stop.js
+++ b/ionic/collide/animation-stop.js
@@ -1,4 +1,4 @@
-/* Forked from Collide.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import {Collide} from './collide'
diff --git a/ionic/collide/animation.js b/ionic/collide/animation.js
index 4d63b9decc..b5bcba8783 100644
--- a/ionic/collide/animation.js
+++ b/ionic/collide/animation.js
@@ -39,6 +39,8 @@ export class Animation {
percent(ratio) {
this._options.percentComplete = parseFloat(ratio);
animationStart(this._elements, this._options, this._properties);
+
+ startTick();
}
diff --git a/ionic/collide/calculate-unit-ratios.js b/ionic/collide/calculate-unit-ratios.js
new file mode 100644
index 0000000000..fd27cbb0ad
--- /dev/null
+++ b/ionic/collide/calculate-unit-ratios.js
@@ -0,0 +1,127 @@
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
+
+/***************************
+ Unit Ratio Calculation
+***************************/
+
+/* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of
+ %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order
+ for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred
+ from a previous call, startValue may also not be in pixels. Unit conversion logic therefore consists of two steps:
+ 1) Calculating the ratio of %/em/rem/vh/vw relative to pixels
+ 2) Converting startValue into the same unit of measurement as endValue based on these ratios. */
+/* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property,
+ setting values with the target unit type then comparing the returned pixel value. */
+/* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead
+ of batching the SETs and GETs together upfront outweights the potential overhead
+ of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */
+/* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */
+export function calculateUnitRatios(element, callUnitConversionData) {
+
+ /**************************************************************
+ parsePropertyValue(), calculateUnitRatios(), Same Ratio Checks
+ **************************************************************/
+
+ /* The properties below are used to determine whether the element differs sufficiently from this call's
+ previously iterated element to also differ in its unit conversion ratios. If the properties match up with those
+ of the prior element, the prior element's conversion ratios are used. Like most optimizations in Collide,
+ this is done to minimize DOM querying. */
+ var sameRatioIndicators = {
+ myParent: element.parentNode || document.body, /* GET */
+ position: CSS.getPropertyValue(element, 'position'), /* GET */
+ fontSize: CSS.getPropertyValue(element, 'fontSize') /* GET */
+ };
+
+ /* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */
+ var samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent));
+
+ /* Determine if the same em ratio can be used. em is relative to the element's fontSize. */
+ var sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize);
+
+ /* Store these ratio indicators call-wide for the next element to compare against. */
+ callUnitConversionData.lastParent = sameRatioIndicators.myParent;
+ callUnitConversionData.lastPosition = sameRatioIndicators.position;
+ callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize;
+
+
+ /**********************************************************************
+ parsePropertyValue(), calculateUnitRatios(), Element-Specific Units
+ **********************************************************************/
+
+ var measurement = 100,
+ unitRatios = {};
+
+ if (!sameEmRatio || !samePercentRatio) {
+ var dummy = data(element).isSVG ? document.createElementNS('http://www.w3.org/2000/svg', 'rect') : document.createElement('div');
+
+ Collide.init(dummy);
+ sameRatioIndicators.myParent.appendChild(dummy);
+
+ /* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped.
+ Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */
+ /* Note: Overflow must be also be controlled for per-axis since the overflow property overwrites its per-axis values. */
+ var cssPropNames = [ 'overflow', 'overflowX', 'overflowY' ];
+ for (var x = 0; x < overflows.length; x++) {
+ Collide.CSS.setPropertyValue(dummy, cssPropNames[x], 'hidden');
+ }
+
+ Collide.CSS.setPropertyValue(dummy, 'position', sameRatioIndicators.position);
+ Collide.CSS.setPropertyValue(dummy, 'fontSize', sameRatioIndicators.fontSize);
+ Collide.CSS.setPropertyValue(dummy, 'boxSizing', 'content-box');
+
+ /* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */
+ cssPropNames = [ 'minWidth', 'maxWidth', 'width', 'minHeight', 'maxHeight', 'height' ];
+ for (var x = 0; x < overflows.length; x++) {
+ Collide.CSS.setPropertyValue(dummy, cssPropNames[x], measurement + '%');
+ }
+
+ /* paddingLeft arbitrarily acts as our proxy property for the em ratio. */
+ Collide.CSS.setPropertyValue(dummy, 'paddingLeft', measurement + 'em');
+
+ /* Divide the returned value by the measurement to get the ratio between 1% and 1px. Default to 1 since working with 0 can produce Infinite. */
+ unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, 'width', null, true)) || 1) / measurement; /* GET */
+ unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, 'height', null, true)) || 1) / measurement; /* GET */
+ unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, 'paddingLeft')) || 1) / measurement; /* GET */
+
+ sameRatioIndicators.myParent.removeChild(dummy);
+
+ } else {
+ unitRatios.emToPx = callUnitConversionData.lastEmToPx;
+ unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth;
+ unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight;
+ }
+
+
+ /**********************************************************************
+ parsePropertyValue(), calculateUnitRatios(), Element-Agnostic Units
+ ***********************************************************************/
+
+ /* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked
+ once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time
+ that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null,
+ so we calculate it now. */
+ if (callUnitConversionData.remToPx === null) {
+ /* Default to browsers' default fontSize of 16px in the case of 0. */
+ if (!remToPx) {
+ remToPx = parseFloat(CSS.getPropertyValue(document.body, 'fontSize')) || 16; /* GET */
+ }
+ callUnitConversionData.remToPx = remToPx
+ }
+
+ /* Similarly, viewport units are %-relative to the window's inner dimensions. */
+ if (callUnitConversionData.vwToPx === null) {
+ callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */
+ callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */
+ }
+
+ unitRatios.remToPx = callUnitConversionData.remToPx;
+ unitRatios.vwToPx = callUnitConversionData.vwToPx;
+ unitRatios.vhToPx = callUnitConversionData.vhToPx;
+
+ if (Collide.debug >= 1) console.log('Unit ratios: ' + JSON.stringify(unitRatios), element);
+
+ return unitRatios;
+
+};
+
+let remToPx = null;
diff --git a/ionic/collide/collide.js b/ionic/collide/collide.js
index b9799252f1..d200f63734 100644
--- a/ionic/collide/collide.js
+++ b/ionic/collide/collide.js
@@ -1,4 +1,4 @@
-/* Forked from Collide.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import {dom} from 'ionic/util'
diff --git a/ionic/collide/complete-call.js b/ionic/collide/complete-call.js
index e3b257915d..9b3f63a56f 100644
--- a/ionic/collide/complete-call.js
+++ b/ionic/collide/complete-call.js
@@ -1,4 +1,4 @@
-/* Forked from Velocity.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import {Collide} from './collide'
import {CSS} from './css'
@@ -9,7 +9,7 @@ import {CSS} from './css'
***************************/
/* Note: Unlike tick(), which processes all active calls at once, call completion is handled on a per-call basis. */
-export function completeCall (callIndex, isStopped) {
+export function completeCall(callIndex, isStopped) {
/* Ensure the call exists. */
if (!Collide.State.calls[callIndex]) {
@@ -88,7 +88,7 @@ export function completeCall (callIndex, isStopped) {
try {
opts.complete.call(elements, elements);
} catch (error) {
- setTimeout(function() { throw error; }, 1);
+ setTimeout(function() { throw error; });
}
}
diff --git a/ionic/collide/css.js b/ionic/collide/css.js
index f716041752..f8975d8db8 100644
--- a/ionic/collide/css.js
+++ b/ionic/collide/css.js
@@ -1,4 +1,4 @@
-/* Forked from Collide.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import {Collide} from './collide'
diff --git a/ionic/collide/easing.js b/ionic/collide/easing.js
index b2f5e3f985..e5a9757ae3 100644
--- a/ionic/collide/easing.js
+++ b/ionic/collide/easing.js
@@ -1,4 +1,4 @@
-/* Forked from Collide.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import * as util from 'ionic/util/util'
import {Collide} from './collide'
diff --git a/ionic/collide/tick.js b/ionic/collide/tick.js
index 0c01343c3e..6c9e437183 100644
--- a/ionic/collide/tick.js
+++ b/ionic/collide/tick.js
@@ -1,4 +1,4 @@
-/* Forked from Collide.js, MIT License. Julian Shapiro http://twitter.com/shapiro */
+/* Forked from VelocityJS: https://github.com/julianshapiro/velocity | MIT License. Julian Shapiro http://twitter.com/shapiro */
import {dom} from 'ionic/util'
import {Collide} from './collide'
@@ -29,6 +29,8 @@ function tick(timestamp) {
var percentCompleteStop = false;
if (timestamp) {
+ console.debug('tick, calls', Collide.State.calls.length)
+
/* We ignore RAF's high resolution timestamp since it can be significantly offset when the browser is
under high stress; we opt for choppiness over allowing the browser to drop huge chunks of frames. */
var timeCurrent = (new Date).getTime();
@@ -82,7 +84,6 @@ function tick(timestamp) {
/* The tween's completion percentage is relative to the tween's start time, not the tween's start value
(which would result in unpredictable tween durations since JavaScript's timers are not particularly accurate).
Accordingly, we ensure that percentComplete does not exceed 1. */
- debugger
var percentComplete;
if (opts.percentComplete !== undefined) {
percentCompleteStop = true;
@@ -276,7 +277,7 @@ function tick(timestamp) {
} // END: if (timestamp)
/* Note: completeCall() sets the isTicking flag to false when the last call on Collide.State.calls has completed. */
- if (Collide.State.isTicking || percentCompleteStop) {
+ if (Collide.State.isTicking) {
dom.raf(tick);
}
diff --git a/ionic/components/app/test/animations/main.html b/ionic/components/app/test/animations/main.html
index c01749a204..46ecc756cd 100644
--- a/ionic/components/app/test/animations/main.html
+++ b/ionic/components/app/test/animations/main.html
@@ -8,7 +8,7 @@
-
+
@@ -17,7 +17,8 @@