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

Side by Side 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, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 <link rel="import" href="../polymer/polymer.html">
2
3 <polymer-element name="polymer-scrub" attributes="animation target scale scrubTy pe wrap nudgeTime snapPoints snapThreshold startSnap">
4 <script>
5 /**
6 * TODO:
7 * - add easing to snap
8 * - test delay
9 * - multiple iterations for input animation
10 * - test CustomEffect
11 */
12 (function() {
13 var clamp = function(inValue, inMin, inMax) {
14 return Math.max(inMin, Math.min(inValue, inMax)) ;
15 }
16
17 Polymer('polymer-scrub', {
18 target: null,
19 animation: null,
20 scale: 1,
21 scrubType: 'x',
22 nudgeTime: 1e-6,
23 snapPoints: null,
24 startSnap: 0,
25 snapThreshold: 0,
26 wrap: false,
27 observe: {
28 target: 'makeScrub',
29 animation: 'makeScrub',
30 scale: 'makeScrub',
31 scrubType: 'makeScrub',
32 nudgeTime: 'makeScrub',
33 snapPoints: 'makeScrub',
34 startSnap: 'makeScrub',
35 snapThreshold: 'makeScrub',
36 wrap: 'makeScrub'
37 },
38 get node() {
39 return this._node;
40 },
41 set node(inNode) {
42 if (this.node) {
43 this.enableEvents(this.node, thi s.scrubEvents, false);
44 this.node.removeAttribute('touch -action');
45 }
46 this._node = inNode;
47 // TODO(sorvell): remove when pointer-ev ents does the right thing.
48 var html = document.querySelector('html' );
49 if (!html.hasAttribute('touch-action')) {
50 html.setAttribute('touch-action' , 'none');
51 }
52 this.node.setAttribute('touch-action', ' none');
53 if (this.node) {
54 this.scrubEvents = [
55 {type: 'click', handler: this.click.bind(this)}
56 ];
57 var moreEvents = [];
58 if (this.scrubType == 'zoom') {
59 this.scrubProp = 'zoom';
60 moreEvents = [
61 {type: 'tracksta rt', handler: this.trackStart.bind(this)},
62 {type: 'track', handler: this.track.bind(this)},
63 {type: 'trackend ', handler: this.trackEnd.bind(this)}
64 ];
65 } else {
66 this.directionProp = thi s.scrubType + 'Direction';
67 this.scrubProp = 'd' + t his.scrubType;
68 // TODO(sorvell): includ e flick.
69 moreEvents = [
70 {type: 'tracksta rt', handler: this.trackStart.bind(this)},
71 {type: 'track', handler: this.track.bind(this)},
72 {type: 'trackend ', handler: this.trackEnd.bind(this)}
73 ];
74 }
75 this.scrubEvents = this.scrubEve nts.concat(moreEvents);
76 this.enableEvents(this.node, thi s.scrubEvents, true);
77 }
78 },
79 destroy: function() {
80 if (this.node) {
81 this.enableEvents(this.node, thi s.scrubEvents, false);
82 this.node.removeAttribute('touch -action');
83 }
84 },
85 enableEvents: function(inNode, inEventInfos, inE nable) {
86 var m = inEnable ? 'addEventListener' : 'removeEventListener';
87 inEventInfos.forEach(function(info) {
88 inNode[m](info.type, info.handle r);
89 })
90 },
91 calcDirection: function(e) {
92 // note: gesture events don't yet provid e direction
93 if (this.scrubType == 'zoom') {
94 var d = e.zoom == 1 ? 0 : (e.zoo m > 1 ? -1 : 1);
95 if (this.scrubbing) {
96 if (!this.scrubbing.dire ction) {
97 this.scrubbing.d irection = d;
98 }
99 return this.scrubbing.di rection;
100 } else {
101 return d;
102 }
103 } else {
104 return e[this.directionProp];
105 }
106 },
107 calcTimeForEvent: function(e) {
108 var dt = e[this.scrubProp] / this.scrubb ing.timeScalar;
109 if (this.scrubType == 'zoom') {
110 var z = (e.zoom - 1) * 0.5;
111 dt = Math.max(-1, Math.min(1, z) );
112 }
113 return this.scrubbing.startTime + dt;
114 },
115 calcSnapPoints: function(inFraction) {
116 var snapPoints = [0];
117 snapPoints = snapPoints.concat(this.snap Points || []);
118 snapPoints.push(1);
119 var sign = inFraction >= 0 ? 1 : -1;
120 var p = Math.abs(inFraction), l;
121 //console.log('snap', inFraction);
122 for (var i=0, l=snapPoints.length, prev= 0, snap, s, e; i<l; i++) {
123 snap = snapPoints[i];
124 if (prev <= p && snap > p) {
125 s = sign * prev;
126 e = sign * snap;
127 return {start: Math.min( s, e), end: Math.max(s, e)};
128 }
129 prev = snap;
130 }
131 return {start: snapPoints[0], end: snapP oints[1]};
132 },
133 canScrub: function(e) {
134 return !this.scrubbingStopped && this.ca lcDirection(e);
135 },
136 maybeScrub: function(e) {
137 if (this.canScrub(e)) {
138 this.beginScrub(e);
139 }
140 },
141 beginScrub: function(e) {
142 this.scrubEvent = e;
143 var d = this.calcDirection(e);
144 this.forward = d < 0;
145 // invoke(this, "onStartScrub", this);
146 var length = this.node[this.scrubType == 'y' ?
147 'offsetHeight' : 'offset Width'];
148 if (!this.scrubbingStopped) {
149 this.scrubAnimation();
150 this.scrubbing = {
151 startTime: this.currentT ime,
152 timeScalar: length / (th is.duration * this.scale)
153 }
154 }
155 },
156 trackStart: function(e) {
157 this.resetScrub();
158 this.maybeScrub(e);
159 },
160 track: function(e) {
161 if (this.scrubbing) {
162 this.currentTime = this.calcTime ForEvent(e);
163 } else {
164 this.maybeScrub(e);
165 }
166 },
167 trackEnd: function(e) {
168 if (this.scrubbing) {
169 this.playToSnap(this.calcDirecti on(e));
170 this.resetScrub();
171 }
172 this.squelchNextClick();
173 },
174 click: function(e) {
175 if (this.scrubClick) {
176 if (!this.squelchClick) {
177 this.scrubAnimation();
178 this.forward = 1;
179 this.scrubEvent = e;
180 // invoke(this, "onStart Scrub", this);
181 if (!this.scrubbingStopp ed) {
182 this.playTo(3);
183 }
184 this.resetScrub();
185 }
186 e.preventDefault();
187 }
188 },
189 squelchNextClick: function() {
190 this.squelchClick = true;
191 setTimeout(function() {
192 this.squelchClick = false;
193 }.bind(this), 0);
194 },
195 stopScrubbing: function() {
196 this.scrubbingStopped = true;
197 this.scrubbing = null;
198 },
199 resetScrub: function() {
200 this.scrubbing = null;
201 this.scrubEvent = null;
202 this.scrubbingStopped = false;
203 },
204 canAnimate: function(inDirection) {
205 return this.wrap || (inDirection < 0 && this.currentTime != 0) ||
206 (inDirection > 0 && this.current Time < this.maxTime);
207 },
208 playToSnap: function(inDirection) {
209 this.scrubAnimation();
210 if (this.canAnimate(inDirection)) {
211 var currentFraction = this.curre ntTime / this.duration;
212 var snaps = this.calcSnapPoints( currentFraction);
213 var reversing = (inDirection*thi s.scale < 0);
214 var snap = reversing ? snaps.sta rt : snaps.end;
215 if (this.snapThreshold) {
216 var threshold = this.sna pThreshold * (snaps.end - snaps.start);
217 if (reversing) {
218 snap = (snaps.en d - currentFraction < threshold) ? snaps.end : snaps.start;
219 } else {
220 snap = (currentF raction - snaps.start < threshold) ? snaps.start : snaps.end;
221 }
222 }
223 this.playTo(snap * this.duration );
224 }
225 },
226 snapNext: function() {
227 this.scrubAnimation();
228 this.currentTime += this.nudgeTime;
229 this.playToSnap(this.scale);
230 },
231 snapPrevious: function() {
232 this.scrubAnimation();
233 this.currentTime -= this.nudgeTime;
234 this.playToSnap(-this.scale);
235 },
236 playTo: function(inTime, inDuration) {
237 this.scrubAnimation();
238 var rate = inDuration ? Math.abs(inTime - t) / inDuration : 1;
239 var duration = this.animation.specified. duration;
240 var t = this.currentTime;
241 var reversing = (inTime < t);
242 if (reversing) {
243 this.segment = new SeqGroup([
244 new SeqGroup([this.anima tion], {direction: 'reverse'})
245 ], {
246 duration: (duration - in Time),
247 playbackRate: rate,
248 delay: -(duration - t)
249 });
250 } else {
251 this.segment = new SeqGroup([thi s.animation], {
252 duration: inTime,
253 playbackRate: rate,
254 delay: -t
255 });
256 }
257 this.segment.onend = function() {
258 this.fire('polymer-scrub-animati on-end');
259 }.bind(this);
260 document.timeline.play(this.segment);
261 },
262 scrubAnimation: function() {
263 if (this.animation.parent) {
264 var reversing = this.animation.p arent.specified.direction === 'reverse';
265 var segmentDuration = reversing ?
266 this.animation.specified .duration - this.segment.specified.duration :
267 this.segment.specified.d uration;
268 // remove animation from segment
269 this.animation.remove();
270 this.segment.parent && this.segm ent.remove();
271 // reset the animation to the la st segment duration
272 document.timeline.play(this.anim ation).paused = true;
273 this.currentTime = segmentDurati on;
274 }
275 },
276 /*
277 addAnimToSegment: function(inDirection, inSnaps) {
278 var reversing = (inDirection*this.scale < 0);
279 if (reversing != this.segment._reversing ) {
280 this.segment.reverse();
281 // install proper easing
282 this.segment.timing.timingFuncti on = reversing ? 'ease-in' : 'ease-out';
283 }
284 var start = inSnaps.start * this.duratio n, end = inSnaps.end * this.duration;
285 this.segment.timing.duration = reversing ? this.currentTime - start :
286 end - this.currentTime;
287 // TODO(sorvell): delay calculation for reversing must be understood
288 this.animation.timing.delay = reversing ? -start : -this.currentTime;
289 this.segment.currentTime = 0;
290 // TODO(sorvell): bug: must play here to ensure the global tick keeps going
291 //console.log('segment duration', this.s egment.timing.duration, 'animation delay', this.animation.timing.delay);
292 document.timeline.play(this.animation);
293 this.segment.add(this.animation);
294 },
295 */
296 set currentTime(inTime) {
297 var t = inTime;
298 if (this.wrap) {
299 t = t % this.duration;
300 if (t < 0) {
301 t = this.duration + t;
302 }
303 } else {
304 t = clamp(t, 0, this.maxTime);
305 }
306 this.animation.player.currentTime = t;
307 },
308 get currentTime() {
309 // TODO(sorvell): currentTime can drift( ?) so make sure not to == duration
310 // or we'll pop over to next iteration.
311 return this.wrap ? this.animation.player .currentTime % this.duration :
312 clamp(this.animation.player.curr entTime, 0, this.maxTime);
313 },
314 get duration() {
315 return this.animation.duration;
316 },
317 get maxTime() {
318 return this.duration - (this.wrap ? 0 : this.nudgeTime);
319 },
320 makeScrub: function() {
321 this.destroy();
322 if (this.target && this.animation) {
323 // fallback to scrubbing x if zo oming not available.
324 if (this.scrubType) {
325 if (!('ontouchstart' in window) && (this.scrubType == 'zoom')) {
326 this.scrubType = 'x';
327 }
328 }
329 if (!this.snapPoints) {
330 this.snapPoints = [];
331 }
332 if (this.animation) {
333 // create a player and p ause the animation
334 document.timeline.play(t his.animation).paused = true;
335 if (this.startSnap) {
336 this.currentTime = this.startSnap * this.duration;
337 }
338 } else {
339 console.warn('No animati on set for scrub');
340 }
341 this.node = this.target;
342 }
343 }
344 });
345 })();
346 </script>
347 </polymer-element>
OLDNEW
« 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