Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Unified Diff: pkg/polymer/lib/elements/polymer-scrub/polymer-scrub.html

Issue 175443005: [polymer] import all elements (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: updated from bower Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/polymer/lib/elements/polymer-scrub/polymer-scrub.html
diff --git a/pkg/polymer/lib/elements/polymer-scrub/polymer-scrub.html b/pkg/polymer/lib/elements/polymer-scrub/polymer-scrub.html
new file mode 100644
index 0000000000000000000000000000000000000000..572623040f6475fb5479eb1f5f470c9bb98ed47e
--- /dev/null
+++ b/pkg/polymer/lib/elements/polymer-scrub/polymer-scrub.html
@@ -0,0 +1,347 @@
+<link rel="import" href="../polymer/polymer.html">
+
+<polymer-element name="polymer-scrub" attributes="animation target scale scrubType wrap nudgeTime snapPoints snapThreshold startSnap">
+ <script>
+ /**
+ * TODO:
+ * - add easing to snap
+ * - test delay
+ * - multiple iterations for input animation
+ * - test CustomEffect
+ */
+ (function() {
+ var clamp = function(inValue, inMin, inMax) {
+ return Math.max(inMin, Math.min(inValue, inMax));
+ }
+
+ Polymer('polymer-scrub', {
+ target: null,
+ animation: null,
+ scale: 1,
+ scrubType: 'x',
+ nudgeTime: 1e-6,
+ snapPoints: null,
+ startSnap: 0,
+ snapThreshold: 0,
+ wrap: false,
+ observe: {
+ target: 'makeScrub',
+ animation: 'makeScrub',
+ scale: 'makeScrub',
+ scrubType: 'makeScrub',
+ nudgeTime: 'makeScrub',
+ snapPoints: 'makeScrub',
+ startSnap: 'makeScrub',
+ snapThreshold: 'makeScrub',
+ wrap: 'makeScrub'
+ },
+ get node() {
+ return this._node;
+ },
+ set node(inNode) {
+ if (this.node) {
+ this.enableEvents(this.node, this.scrubEvents, false);
+ this.node.removeAttribute('touch-action');
+ }
+ this._node = inNode;
+ // TODO(sorvell): remove when pointer-events does the right thing.
+ var html = document.querySelector('html');
+ if (!html.hasAttribute('touch-action')) {
+ html.setAttribute('touch-action', 'none');
+ }
+ this.node.setAttribute('touch-action', 'none');
+ if (this.node) {
+ this.scrubEvents = [
+ {type: 'click', handler: this.click.bind(this)}
+ ];
+ var moreEvents = [];
+ if (this.scrubType == 'zoom') {
+ this.scrubProp = 'zoom';
+ moreEvents = [
+ {type: 'trackstart', handler: this.trackStart.bind(this)},
+ {type: 'track', handler: this.track.bind(this)},
+ {type: 'trackend', handler: this.trackEnd.bind(this)}
+ ];
+ } else {
+ this.directionProp = this.scrubType + 'Direction';
+ this.scrubProp = 'd' + this.scrubType;
+ // TODO(sorvell): include flick.
+ moreEvents = [
+ {type: 'trackstart', handler: this.trackStart.bind(this)},
+ {type: 'track', handler: this.track.bind(this)},
+ {type: 'trackend', handler: this.trackEnd.bind(this)}
+ ];
+ }
+ this.scrubEvents = this.scrubEvents.concat(moreEvents);
+ this.enableEvents(this.node, this.scrubEvents, true);
+ }
+ },
+ destroy: function() {
+ if (this.node) {
+ this.enableEvents(this.node, this.scrubEvents, false);
+ this.node.removeAttribute('touch-action');
+ }
+ },
+ enableEvents: function(inNode, inEventInfos, inEnable) {
+ var m = inEnable ? 'addEventListener' : 'removeEventListener';
+ inEventInfos.forEach(function(info) {
+ inNode[m](info.type, info.handler);
+ })
+ },
+ calcDirection: function(e) {
+ // note: gesture events don't yet provide direction
+ if (this.scrubType == 'zoom') {
+ var d = e.zoom == 1 ? 0 : (e.zoom > 1 ? -1 : 1);
+ if (this.scrubbing) {
+ if (!this.scrubbing.direction) {
+ this.scrubbing.direction = d;
+ }
+ return this.scrubbing.direction;
+ } else {
+ return d;
+ }
+ } else {
+ return e[this.directionProp];
+ }
+ },
+ calcTimeForEvent: function(e) {
+ var dt = e[this.scrubProp] / this.scrubbing.timeScalar;
+ if (this.scrubType == 'zoom') {
+ var z = (e.zoom - 1) * 0.5;
+ dt = Math.max(-1, Math.min(1, z));
+ }
+ return this.scrubbing.startTime + dt;
+ },
+ calcSnapPoints: function(inFraction) {
+ var snapPoints = [0];
+ snapPoints = snapPoints.concat(this.snapPoints || []);
+ snapPoints.push(1);
+ var sign = inFraction >= 0 ? 1 : -1;
+ var p = Math.abs(inFraction), l;
+ //console.log('snap', inFraction);
+ for (var i=0, l=snapPoints.length, prev=0, snap, s, e; i<l; i++) {
+ snap = snapPoints[i];
+ if (prev <= p && snap > p) {
+ s = sign * prev;
+ e = sign * snap;
+ return {start: Math.min(s, e), end: Math.max(s, e)};
+ }
+ prev = snap;
+ }
+ return {start: snapPoints[0], end: snapPoints[1]};
+ },
+ canScrub: function(e) {
+ return !this.scrubbingStopped && this.calcDirection(e);
+ },
+ maybeScrub: function(e) {
+ if (this.canScrub(e)) {
+ this.beginScrub(e);
+ }
+ },
+ beginScrub: function(e) {
+ this.scrubEvent = e;
+ var d = this.calcDirection(e);
+ this.forward = d < 0;
+ // invoke(this, "onStartScrub", this);
+ var length = this.node[this.scrubType == 'y' ?
+ 'offsetHeight' : 'offsetWidth'];
+ if (!this.scrubbingStopped) {
+ this.scrubAnimation();
+ this.scrubbing = {
+ startTime: this.currentTime,
+ timeScalar: length / (this.duration * this.scale)
+ }
+ }
+ },
+ trackStart: function(e) {
+ this.resetScrub();
+ this.maybeScrub(e);
+ },
+ track: function(e) {
+ if (this.scrubbing) {
+ this.currentTime = this.calcTimeForEvent(e);
+ } else {
+ this.maybeScrub(e);
+ }
+ },
+ trackEnd: function(e) {
+ if (this.scrubbing) {
+ this.playToSnap(this.calcDirection(e));
+ this.resetScrub();
+ }
+ this.squelchNextClick();
+ },
+ click: function(e) {
+ if (this.scrubClick) {
+ if (!this.squelchClick) {
+ this.scrubAnimation();
+ this.forward = 1;
+ this.scrubEvent = e;
+ // invoke(this, "onStartScrub", this);
+ if (!this.scrubbingStopped) {
+ this.playTo(3);
+ }
+ this.resetScrub();
+ }
+ e.preventDefault();
+ }
+ },
+ squelchNextClick: function() {
+ this.squelchClick = true;
+ setTimeout(function() {
+ this.squelchClick = false;
+ }.bind(this), 0);
+ },
+ stopScrubbing: function() {
+ this.scrubbingStopped = true;
+ this.scrubbing = null;
+ },
+ resetScrub: function() {
+ this.scrubbing = null;
+ this.scrubEvent = null;
+ this.scrubbingStopped = false;
+ },
+ canAnimate: function(inDirection) {
+ return this.wrap || (inDirection < 0 && this.currentTime != 0) ||
+ (inDirection > 0 && this.currentTime < this.maxTime);
+ },
+ playToSnap: function(inDirection) {
+ this.scrubAnimation();
+ if (this.canAnimate(inDirection)) {
+ var currentFraction = this.currentTime / this.duration;
+ var snaps = this.calcSnapPoints(currentFraction);
+ var reversing = (inDirection*this.scale < 0);
+ var snap = reversing ? snaps.start : snaps.end;
+ if (this.snapThreshold) {
+ var threshold = this.snapThreshold * (snaps.end - snaps.start);
+ if (reversing) {
+ snap = (snaps.end - currentFraction < threshold) ? snaps.end : snaps.start;
+ } else {
+ snap = (currentFraction - snaps.start < threshold) ? snaps.start : snaps.end;
+ }
+ }
+ this.playTo(snap * this.duration);
+ }
+ },
+ snapNext: function() {
+ this.scrubAnimation();
+ this.currentTime += this.nudgeTime;
+ this.playToSnap(this.scale);
+ },
+ snapPrevious: function() {
+ this.scrubAnimation();
+ this.currentTime -= this.nudgeTime;
+ this.playToSnap(-this.scale);
+ },
+ playTo: function(inTime, inDuration) {
+ this.scrubAnimation();
+ var rate = inDuration ? Math.abs(inTime - t) / inDuration : 1;
+ var duration = this.animation.specified.duration;
+ var t = this.currentTime;
+ var reversing = (inTime < t);
+ if (reversing) {
+ this.segment = new SeqGroup([
+ new SeqGroup([this.animation], {direction: 'reverse'})
+ ], {
+ duration: (duration - inTime),
+ playbackRate: rate,
+ delay: -(duration - t)
+ });
+ } else {
+ this.segment = new SeqGroup([this.animation], {
+ duration: inTime,
+ playbackRate: rate,
+ delay: -t
+ });
+ }
+ this.segment.onend = function() {
+ this.fire('polymer-scrub-animation-end');
+ }.bind(this);
+ document.timeline.play(this.segment);
+ },
+ scrubAnimation: function() {
+ if (this.animation.parent) {
+ var reversing = this.animation.parent.specified.direction === 'reverse';
+ var segmentDuration = reversing ?
+ this.animation.specified.duration - this.segment.specified.duration :
+ this.segment.specified.duration;
+ // remove animation from segment
+ this.animation.remove();
+ this.segment.parent && this.segment.remove();
+ // reset the animation to the last segment duration
+ document.timeline.play(this.animation).paused = true;
+ this.currentTime = segmentDuration;
+ }
+ },
+ /*
+ addAnimToSegment: function(inDirection, inSnaps) {
+ var reversing = (inDirection*this.scale < 0);
+ if (reversing != this.segment._reversing) {
+ this.segment.reverse();
+ // install proper easing
+ this.segment.timing.timingFunction = reversing ? 'ease-in' : 'ease-out';
+ }
+ var start = inSnaps.start * this.duration, end = inSnaps.end * this.duration;
+ this.segment.timing.duration = reversing ? this.currentTime - start :
+ end - this.currentTime;
+ // TODO(sorvell): delay calculation for reversing must be understood
+ this.animation.timing.delay = reversing ? -start : -this.currentTime;
+ this.segment.currentTime = 0;
+ // TODO(sorvell): bug: must play here to ensure the global tick keeps going
+ //console.log('segment duration', this.segment.timing.duration, 'animation delay', this.animation.timing.delay);
+ document.timeline.play(this.animation);
+ this.segment.add(this.animation);
+ },
+ */
+ set currentTime(inTime) {
+ var t = inTime;
+ if (this.wrap) {
+ t = t % this.duration;
+ if (t < 0) {
+ t = this.duration + t;
+ }
+ } else {
+ t = clamp(t, 0, this.maxTime);
+ }
+ this.animation.player.currentTime = t;
+ },
+ get currentTime() {
+ // TODO(sorvell): currentTime can drift(?) so make sure not to == duration
+ // or we'll pop over to next iteration.
+ return this.wrap ? this.animation.player.currentTime % this.duration :
+ clamp(this.animation.player.currentTime, 0, this.maxTime);
+ },
+ get duration() {
+ return this.animation.duration;
+ },
+ get maxTime() {
+ return this.duration - (this.wrap ? 0 : this.nudgeTime);
+ },
+ makeScrub: function() {
+ this.destroy();
+ if (this.target && this.animation) {
+ // fallback to scrubbing x if zooming not available.
+ if (this.scrubType) {
+ if (!('ontouchstart' in window) && (this.scrubType == 'zoom')) {
+ this.scrubType = 'x';
+ }
+ }
+ if (!this.snapPoints) {
+ this.snapPoints = [];
+ }
+ if (this.animation) {
+ // create a player and pause the animation
+ document.timeline.play(this.animation).paused = true;
+ if (this.startSnap) {
+ this.currentTime = this.startSnap * this.duration;
+ }
+ } else {
+ console.warn('No animation set for scrub');
+ }
+ this.node = this.target;
+ }
+ }
+ });
+ })();
+ </script>
+</polymer-element>
« no previous file with comments | « pkg/polymer/lib/elements/polymer-scrub/index.html ('k') | pkg/polymer/lib/elements/polymer-selection/.bower.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698