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

Side by Side Diff: third_party/polymer/components/paper-ripple/paper-ripple.html

Issue 1215543002: Remove Polymer 0.5. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix unit test Created 5 years, 5 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
OLDNEW
(Empty)
1 <!--
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
6 Code distributed by Google as part of the polymer project is also
7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
8 -->
9
10 <!--
11 `paper-ripple` provides a visual effect that other paper elements can
12 use to simulate a rippling effect emanating from the point of contact. The
13 effect can be visualized as a concentric circle with motion.
14
15 Example:
16
17 <paper-ripple></paper-ripple>
18
19 `paper-ripple` listens to "down" and "up" events so it would display ripple
20 effect when touches on it. You can also defeat the default behavior and
21 manually route the down and up actions to the ripple element. Note that it is
22 important if you call downAction() you will have to make sure to call upAction()
23 so that `paper-ripple` would end the animation loop.
24
25 Example:
26
27 <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple>
28 ...
29 downAction: function(e) {
30 this.$.ripple.downAction({x: e.x, y: e.y});
31 },
32 upAction: function(e) {
33 this.$.ripple.upAction();
34 }
35
36 Styling ripple effect:
37
38 Use CSS color property to style the ripple:
39
40 paper-ripple {
41 color: #4285f4;
42 }
43
44 Note that CSS color property is inherited so it is not required to set it on
45 the `paper-ripple` element directly.
46
47 By default, the ripple is centered on the point of contact. Apply `recenteringT ouch`
48 class to have the ripple grow toward the center of its container.
49
50 <paper-ripple class="recenteringTouch"></paper-ripple>
51
52 Apply `circle` class to make the rippling effect within a circle.
53
54 <paper-ripple class="circle"></paper-ripple>
55
56 @group Paper Elements
57 @element paper-ripple
58 @homepage github.io
59 -->
60
61 <!--
62 Fired when the animation finishes. This is useful if you want to wait until the ripple
63 animation finishes to perform some action.
64
65 @event core-transitionend
66 @param {Object} detail
67 @param {Object} detail.node The animated node
68 -->
69
70 <link rel="import" href="../polymer/polymer.html" >
71
72 <polymer-element name="paper-ripple" attributes="initialOpacity opacityDecayVelo city">
73 <template>
74
75 <style>
76
77 :host {
78 display: block;
79 position: relative;
80 border-radius: inherit;
81 overflow: hidden;
82 }
83
84 :host-context([noink]) {
85 pointer-events: none;
86 }
87
88 #bg, #waves, .wave-container, .wave {
89 pointer-events: none;
90 position: absolute;
91 top: 0;
92 left: 0;
93 width: 100%;
94 height: 100%;
95 }
96
97 #bg, .wave {
98 opacity: 0;
99 }
100
101 #waves, .wave {
102 overflow: hidden;
103 }
104
105 .wave-container, .wave {
106 border-radius: 50%;
107 }
108
109 :host(.circle) #bg,
110 :host(.circle) #waves {
111 border-radius: 50%;
112 }
113
114 :host(.circle) .wave-container {
115 overflow: hidden;
116 }
117
118 </style>
119
120 <div id="bg"></div>
121 <div id="waves">
122 </div>
123
124 </template>
125 <script>
126
127 (function() {
128
129 var waveMaxRadius = 150;
130 //
131 // INK EQUATIONS
132 //
133 function waveRadiusFn(touchDownMs, touchUpMs, anim) {
134 // Convert from ms to s
135 var touchDown = touchDownMs / 1000;
136 var touchUp = touchUpMs / 1000;
137 var totalElapsed = touchDown + touchUp;
138 var ww = anim.width, hh = anim.height;
139 // use diagonal size of container to avoid floating point math sadness
140 var waveRadius = Math.min(Math.sqrt(ww * ww + hh * hh), waveMaxRadius) * 1 .1 + 5;
141 var duration = 1.1 - .2 * (waveRadius / waveMaxRadius);
142 var tt = (totalElapsed / duration);
143
144 var size = waveRadius * (1 - Math.pow(80, -tt));
145 return Math.abs(size);
146 }
147
148 function waveOpacityFn(td, tu, anim) {
149 // Convert from ms to s.
150 var touchDown = td / 1000;
151 var touchUp = tu / 1000;
152 var totalElapsed = touchDown + touchUp;
153
154 if (tu <= 0) { // before touch up
155 return anim.initialOpacity;
156 }
157 return Math.max(0, anim.initialOpacity - touchUp * anim.opacityDecayVeloci ty);
158 }
159
160 function waveOuterOpacityFn(td, tu, anim) {
161 // Convert from ms to s.
162 var touchDown = td / 1000;
163 var touchUp = tu / 1000;
164
165 // Linear increase in background opacity, capped at the opacity
166 // of the wavefront (waveOpacity).
167 var outerOpacity = touchDown * 0.3;
168 var waveOpacity = waveOpacityFn(td, tu, anim);
169 return Math.max(0, Math.min(outerOpacity, waveOpacity));
170 }
171
172 // Determines whether the wave should be completely removed.
173 function waveDidFinish(wave, radius, anim) {
174 var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
175
176 // If the wave opacity is 0 and the radius exceeds the bounds
177 // of the element, then this is finished.
178 return waveOpacity < 0.01 && radius >= Math.min(wave.maxRadius, waveMaxRad ius);
179 };
180
181 function waveAtMaximum(wave, radius, anim) {
182 var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
183
184 return waveOpacity >= anim.initialOpacity && radius >= Math.min(wave.maxRa dius, waveMaxRadius);
185 }
186
187 //
188 // DRAWING
189 //
190 function drawRipple(ctx, x, y, radius, innerAlpha, outerAlpha) {
191 // Only animate opacity and transform
192 if (outerAlpha !== undefined) {
193 ctx.bg.style.opacity = outerAlpha;
194 }
195 ctx.wave.style.opacity = innerAlpha;
196
197 var s = radius / (ctx.containerSize / 2);
198 var dx = x - (ctx.containerWidth / 2);
199 var dy = y - (ctx.containerHeight / 2);
200
201 ctx.wc.style.webkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0)';
202 ctx.wc.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0)';
203
204 // 2d transform for safari because of border-radius and overflow:hidden cl ipping bug.
205 // https://bugs.webkit.org/show_bug.cgi?id=98538
206 ctx.wave.style.webkitTransform = 'scale(' + s + ',' + s + ')';
207 ctx.wave.style.transform = 'scale3d(' + s + ',' + s + ',1)';
208 }
209
210 //
211 // SETUP
212 //
213 function createWave(elem) {
214 var elementStyle = window.getComputedStyle(elem);
215 var fgColor = elementStyle.color;
216
217 var inner = document.createElement('div');
218 inner.style.backgroundColor = fgColor;
219 inner.classList.add('wave');
220
221 var outer = document.createElement('div');
222 outer.classList.add('wave-container');
223 outer.appendChild(inner);
224
225 var container = elem.$.waves;
226 container.appendChild(outer);
227
228 elem.$.bg.style.backgroundColor = fgColor;
229
230 var wave = {
231 bg: elem.$.bg,
232 wc: outer,
233 wave: inner,
234 waveColor: fgColor,
235 maxRadius: 0,
236 isMouseDown: false,
237 mouseDownStart: 0.0,
238 mouseUpStart: 0.0,
239 tDown: 0,
240 tUp: 0
241 };
242 return wave;
243 }
244
245 function removeWaveFromScope(scope, wave) {
246 if (scope.waves) {
247 var pos = scope.waves.indexOf(wave);
248 scope.waves.splice(pos, 1);
249 // FIXME cache nodes
250 wave.wc.remove();
251 }
252 };
253
254 // Shortcuts.
255 var pow = Math.pow;
256 var now = Date.now;
257 if (window.performance && performance.now) {
258 now = performance.now.bind(performance);
259 }
260
261 function cssColorWithAlpha(cssColor, alpha) {
262 var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
263 if (typeof alpha == 'undefined') {
264 alpha = 1;
265 }
266 if (!parts) {
267 return 'rgba(255, 255, 255, ' + alpha + ')';
268 }
269 return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + a lpha + ')';
270 }
271
272 function dist(p1, p2) {
273 return Math.sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
274 }
275
276 function distanceFromPointToFurthestCorner(point, size) {
277 var tl_d = dist(point, {x: 0, y: 0});
278 var tr_d = dist(point, {x: size.w, y: 0});
279 var bl_d = dist(point, {x: 0, y: size.h});
280 var br_d = dist(point, {x: size.w, y: size.h});
281 return Math.max(tl_d, tr_d, bl_d, br_d);
282 }
283
284 Polymer('paper-ripple', {
285
286 /**
287 * The initial opacity set on the wave.
288 *
289 * @attribute initialOpacity
290 * @type number
291 * @default 0.25
292 */
293 initialOpacity: 0.25,
294
295 /**
296 * How fast (opacity per second) the wave fades out.
297 *
298 * @attribute opacityDecayVelocity
299 * @type number
300 * @default 0.8
301 */
302 opacityDecayVelocity: 0.8,
303
304 backgroundFill: true,
305 pixelDensity: 2,
306
307 eventDelegates: {
308 down: 'downAction',
309 up: 'upAction'
310 },
311
312 ready: function() {
313 this.waves = [];
314 },
315
316 downAction: function(e) {
317 var wave = createWave(this);
318
319 this.cancelled = false;
320 wave.isMouseDown = true;
321 wave.tDown = 0.0;
322 wave.tUp = 0.0;
323 wave.mouseUpStart = 0.0;
324 wave.mouseDownStart = now();
325
326 var rect = this.getBoundingClientRect();
327 var width = rect.width;
328 var height = rect.height;
329 var touchX = e.x - rect.left;
330 var touchY = e.y - rect.top;
331
332 wave.startPosition = {x:touchX, y:touchY};
333
334 if (this.classList.contains("recenteringTouch")) {
335 wave.endPosition = {x: width / 2, y: height / 2};
336 wave.slideDistance = dist(wave.startPosition, wave.endPosition);
337 }
338 wave.containerSize = Math.max(width, height);
339 wave.containerWidth = width;
340 wave.containerHeight = height;
341 wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, { w: width, h: height});
342
343 // The wave is circular so constrain its container to 1:1
344 wave.wc.style.top = (wave.containerHeight - wave.containerSize) / 2 + 'p x';
345 wave.wc.style.left = (wave.containerWidth - wave.containerSize) / 2 + 'p x';
346 wave.wc.style.width = wave.containerSize + 'px';
347 wave.wc.style.height = wave.containerSize + 'px';
348
349 this.waves.push(wave);
350
351 if (!this._loop) {
352 this._loop = this.animate.bind(this, {
353 width: width,
354 height: height
355 });
356 requestAnimationFrame(this._loop);
357 }
358 // else there is already a rAF
359 },
360
361 upAction: function() {
362 for (var i = 0; i < this.waves.length; i++) {
363 // Declare the next wave that has mouse down to be mouse'ed up.
364 var wave = this.waves[i];
365 if (wave.isMouseDown) {
366 wave.isMouseDown = false
367 wave.mouseUpStart = now();
368 wave.mouseDownStart = 0;
369 wave.tUp = 0.0;
370 break;
371 }
372 }
373 this._loop && requestAnimationFrame(this._loop);
374 },
375
376 cancel: function() {
377 this.cancelled = true;
378 },
379
380 animate: function(ctx) {
381 var shouldRenderNextFrame = false;
382
383 var deleteTheseWaves = [];
384 // The oldest wave's touch down duration
385 var longestTouchDownDuration = 0;
386 var longestTouchUpDuration = 0;
387 // Save the last known wave color
388 var lastWaveColor = null;
389 // wave animation values
390 var anim = {
391 initialOpacity: this.initialOpacity,
392 opacityDecayVelocity: this.opacityDecayVelocity,
393 height: ctx.height,
394 width: ctx.width
395 }
396
397 for (var i = 0; i < this.waves.length; i++) {
398 var wave = this.waves[i];
399
400 if (wave.mouseDownStart > 0) {
401 wave.tDown = now() - wave.mouseDownStart;
402 }
403 if (wave.mouseUpStart > 0) {
404 wave.tUp = now() - wave.mouseUpStart;
405 }
406
407 // Determine how long the touch has been up or down.
408 var tUp = wave.tUp;
409 var tDown = wave.tDown;
410 longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown);
411 longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp);
412
413 // Obtain the instantenous size and alpha of the ripple.
414 var radius = waveRadiusFn(tDown, tUp, anim);
415 var waveAlpha = waveOpacityFn(tDown, tUp, anim);
416 var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha);
417 lastWaveColor = wave.waveColor;
418
419 // Position of the ripple.
420 var x = wave.startPosition.x;
421 var y = wave.startPosition.y;
422
423 // Ripple gravitational pull to the center of the canvas.
424 if (wave.endPosition) {
425
426 // This translates from the origin to the center of the view based on the max dimension of
427 var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) );
428
429 x += translateFraction * (wave.endPosition.x - wave.startPosition.x) ;
430 y += translateFraction * (wave.endPosition.y - wave.startPosition.y) ;
431 }
432
433 // If we do a background fill fade too, work out the correct color.
434 var bgFillColor = null;
435 if (this.backgroundFill) {
436 var bgFillAlpha = waveOuterOpacityFn(tDown, tUp, anim);
437 bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha);
438 }
439
440 // Draw the ripple.
441 drawRipple(wave, x, y, radius, waveAlpha, bgFillAlpha);
442
443 // Determine whether there is any more rendering to be done.
444 var maximumWave = waveAtMaximum(wave, radius, anim);
445 var waveDissipated = waveDidFinish(wave, radius, anim);
446 var shouldKeepWave = !waveDissipated || maximumWave;
447 // keep rendering dissipating wave when at maximum radius on upAction
448 var shouldRenderWaveAgain = wave.mouseUpStart ? !waveDissipated : !max imumWave;
449 shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain ;
450 if (!shouldKeepWave || this.cancelled) {
451 deleteTheseWaves.push(wave);
452 }
453 }
454
455 if (shouldRenderNextFrame) {
456 requestAnimationFrame(this._loop);
457 }
458
459 for (var i = 0; i < deleteTheseWaves.length; ++i) {
460 var wave = deleteTheseWaves[i];
461 removeWaveFromScope(this, wave);
462 }
463
464 if (!this.waves.length && this._loop) {
465 // clear the background color
466 this.$.bg.style.backgroundColor = null;
467 this._loop = null;
468 this.fire('core-transitionend');
469 }
470 }
471
472 });
473
474 })();
475
476 </script>
477 </polymer-element>
OLDNEW
« no previous file with comments | « third_party/polymer/components/paper-ripple/metadata.html ('k') | third_party/polymer/components/paper-ripple/test/index.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698