diff options
Diffstat (limited to 'systrace/catapult/third_party/polymer/components/paper-ripple/paper-ripple.html')
-rw-r--r-- | systrace/catapult/third_party/polymer/components/paper-ripple/paper-ripple.html | 763 |
1 files changed, 0 insertions, 763 deletions
diff --git a/systrace/catapult/third_party/polymer/components/paper-ripple/paper-ripple.html b/systrace/catapult/third_party/polymer/components/paper-ripple/paper-ripple.html deleted file mode 100644 index 3fb18a3..0000000 --- a/systrace/catapult/third_party/polymer/components/paper-ripple/paper-ripple.html +++ /dev/null @@ -1,763 +0,0 @@ -<!-- -@license -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<link rel="import" href="../polymer/polymer.html"> -<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> - -<!-- -Material design: [Surface reaction](https://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-surface-reaction) - -`paper-ripple` provides a visual effect that other paper elements can -use to simulate a rippling effect emanating from the point of contact. The -effect can be visualized as a concentric circle with motion. - -Example: - - <div style="position:relative"> - <paper-ripple></paper-ripple> - </div> - -Note, it's important that the parent container of the ripple be relative position, otherwise -the ripple will emanate outside of the desired container. - -`paper-ripple` listens to "mousedown" and "mouseup" events so it would display ripple -effect when touches on it. You can also defeat the default behavior and -manually route the down and up actions to the ripple element. Note that it is -important if you call `downAction()` you will have to make sure to call -`upAction()` so that `paper-ripple` would end the animation loop. - -Example: - - <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> - ... - downAction: function(e) { - this.$.ripple.downAction({detail: {x: e.x, y: e.y}}); - }, - upAction: function(e) { - this.$.ripple.upAction(); - } - -Styling ripple effect: - - Use CSS color property to style the ripple: - - paper-ripple { - color: #4285f4; - } - - Note that CSS color property is inherited so it is not required to set it on - the `paper-ripple` element directly. - -By default, the ripple is centered on the point of contact. Apply the `recenters` -attribute to have the ripple grow toward the center of its container. - - <paper-ripple recenters></paper-ripple> - -You can also center the ripple inside its container from the start. - - <paper-ripple center></paper-ripple> - -Apply `circle` class to make the rippling effect within a circle. - - <paper-ripple class="circle"></paper-ripple> - -@group Paper Elements -@element paper-ripple -@hero hero.svg -@demo demo/index.html ---> - -<dom-module id="paper-ripple"> - - <template> - <style> - :host { - display: block; - position: absolute; - border-radius: inherit; - overflow: hidden; - top: 0; - left: 0; - right: 0; - bottom: 0; - - /* See PolymerElements/paper-behaviors/issues/34. On non-Chrome browsers, - * creating a node (with a position:absolute) in the middle of an event - * handler "interrupts" that event handler (which happens when the - * ripple is created on demand) */ - pointer-events: none; - } - - :host([animating]) { - /* This resolves a rendering issue in Chrome (as of 40) where the - ripple is not properly clipped by its parent (which may have - rounded corners). See: http://jsbin.com/temexa/4 - - Note: We only apply this style conditionally. Otherwise, the browser - will create a new compositing layer for every ripple element on the - page, and that would be bad. */ - -webkit-transform: translate(0, 0); - transform: translate3d(0, 0, 0); - } - - #background, - #waves, - .wave-container, - .wave { - pointer-events: none; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } - - #background, - .wave { - opacity: 0; - } - - #waves, - .wave { - overflow: hidden; - } - - .wave-container, - .wave { - border-radius: 50%; - } - - :host(.circle) #background, - :host(.circle) #waves { - border-radius: 50%; - } - - :host(.circle) .wave-container { - overflow: hidden; - } - </style> - - <div id="background"></div> - <div id="waves"></div> - </template> -</dom-module> -<script> - (function() { - var Utility = { - distance: function(x1, y1, x2, y2) { - var xDelta = (x1 - x2); - var yDelta = (y1 - y2); - - return Math.sqrt(xDelta * xDelta + yDelta * yDelta); - }, - - now: window.performance && window.performance.now ? - window.performance.now.bind(window.performance) : Date.now - }; - - /** - * @param {HTMLElement} element - * @constructor - */ - function ElementMetrics(element) { - this.element = element; - this.width = this.boundingRect.width; - this.height = this.boundingRect.height; - - this.size = Math.max(this.width, this.height); - } - - ElementMetrics.prototype = { - get boundingRect () { - return this.element.getBoundingClientRect(); - }, - - furthestCornerDistanceFrom: function(x, y) { - var topLeft = Utility.distance(x, y, 0, 0); - var topRight = Utility.distance(x, y, this.width, 0); - var bottomLeft = Utility.distance(x, y, 0, this.height); - var bottomRight = Utility.distance(x, y, this.width, this.height); - - return Math.max(topLeft, topRight, bottomLeft, bottomRight); - } - }; - - /** - * @param {HTMLElement} element - * @constructor - */ - function Ripple(element) { - this.element = element; - this.color = window.getComputedStyle(element).color; - - this.wave = document.createElement('div'); - this.waveContainer = document.createElement('div'); - this.wave.style.backgroundColor = this.color; - this.wave.classList.add('wave'); - this.waveContainer.classList.add('wave-container'); - Polymer.dom(this.waveContainer).appendChild(this.wave); - - this.resetInteractionState(); - } - - Ripple.MAX_RADIUS = 300; - - Ripple.prototype = { - get recenters() { - return this.element.recenters; - }, - - get center() { - return this.element.center; - }, - - get mouseDownElapsed() { - var elapsed; - - if (!this.mouseDownStart) { - return 0; - } - - elapsed = Utility.now() - this.mouseDownStart; - - if (this.mouseUpStart) { - elapsed -= this.mouseUpElapsed; - } - - return elapsed; - }, - - get mouseUpElapsed() { - return this.mouseUpStart ? - Utility.now () - this.mouseUpStart : 0; - }, - - get mouseDownElapsedSeconds() { - return this.mouseDownElapsed / 1000; - }, - - get mouseUpElapsedSeconds() { - return this.mouseUpElapsed / 1000; - }, - - get mouseInteractionSeconds() { - return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds; - }, - - get initialOpacity() { - return this.element.initialOpacity; - }, - - get opacityDecayVelocity() { - return this.element.opacityDecayVelocity; - }, - - get radius() { - var width2 = this.containerMetrics.width * this.containerMetrics.width; - var height2 = this.containerMetrics.height * this.containerMetrics.height; - var waveRadius = Math.min( - Math.sqrt(width2 + height2), - Ripple.MAX_RADIUS - ) * 1.1 + 5; - - var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS); - var timeNow = this.mouseInteractionSeconds / duration; - var size = waveRadius * (1 - Math.pow(80, -timeNow)); - - return Math.abs(size); - }, - - get opacity() { - if (!this.mouseUpStart) { - return this.initialOpacity; - } - - return Math.max( - 0, - this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVelocity - ); - }, - - get outerOpacity() { - // Linear increase in background opacity, capped at the opacity - // of the wavefront (waveOpacity). - var outerOpacity = this.mouseUpElapsedSeconds * 0.3; - var waveOpacity = this.opacity; - - return Math.max( - 0, - Math.min(outerOpacity, waveOpacity) - ); - }, - - get isOpacityFullyDecayed() { - return this.opacity < 0.01 && - this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); - }, - - get isRestingAtMaxRadius() { - return this.opacity >= this.initialOpacity && - this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); - }, - - get isAnimationComplete() { - return this.mouseUpStart ? - this.isOpacityFullyDecayed : this.isRestingAtMaxRadius; - }, - - get translationFraction() { - return Math.min( - 1, - this.radius / this.containerMetrics.size * 2 / Math.sqrt(2) - ); - }, - - get xNow() { - if (this.xEnd) { - return this.xStart + this.translationFraction * (this.xEnd - this.xStart); - } - - return this.xStart; - }, - - get yNow() { - if (this.yEnd) { - return this.yStart + this.translationFraction * (this.yEnd - this.yStart); - } - - return this.yStart; - }, - - get isMouseDown() { - return this.mouseDownStart && !this.mouseUpStart; - }, - - resetInteractionState: function() { - this.maxRadius = 0; - this.mouseDownStart = 0; - this.mouseUpStart = 0; - - this.xStart = 0; - this.yStart = 0; - this.xEnd = 0; - this.yEnd = 0; - this.slideDistance = 0; - - this.containerMetrics = new ElementMetrics(this.element); - }, - - draw: function() { - var scale; - var translateString; - var dx; - var dy; - - this.wave.style.opacity = this.opacity; - - scale = this.radius / (this.containerMetrics.size / 2); - dx = this.xNow - (this.containerMetrics.width / 2); - dy = this.yNow - (this.containerMetrics.height / 2); - - - // 2d transform for safari because of border-radius and overflow:hidden clipping bug. - // https://bugs.webkit.org/show_bug.cgi?id=98538 - this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + dy + 'px)'; - this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy + 'px, 0)'; - this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; - this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; - }, - - /** @param {Event=} event */ - downAction: function(event) { - var xCenter = this.containerMetrics.width / 2; - var yCenter = this.containerMetrics.height / 2; - - this.resetInteractionState(); - this.mouseDownStart = Utility.now(); - - if (this.center) { - this.xStart = xCenter; - this.yStart = yCenter; - this.slideDistance = Utility.distance( - this.xStart, this.yStart, this.xEnd, this.yEnd - ); - } else { - this.xStart = event ? - event.detail.x - this.containerMetrics.boundingRect.left : - this.containerMetrics.width / 2; - this.yStart = event ? - event.detail.y - this.containerMetrics.boundingRect.top : - this.containerMetrics.height / 2; - } - - if (this.recenters) { - this.xEnd = xCenter; - this.yEnd = yCenter; - this.slideDistance = Utility.distance( - this.xStart, this.yStart, this.xEnd, this.yEnd - ); - } - - this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( - this.xStart, - this.yStart - ); - - this.waveContainer.style.top = - (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'; - this.waveContainer.style.left = - (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; - - this.waveContainer.style.width = this.containerMetrics.size + 'px'; - this.waveContainer.style.height = this.containerMetrics.size + 'px'; - }, - - /** @param {Event=} event */ - upAction: function(event) { - if (!this.isMouseDown) { - return; - } - - this.mouseUpStart = Utility.now(); - }, - - remove: function() { - Polymer.dom(this.waveContainer.parentNode).removeChild( - this.waveContainer - ); - } - }; - - Polymer({ - is: 'paper-ripple', - - behaviors: [ - Polymer.IronA11yKeysBehavior - ], - - properties: { - /** - * The initial opacity set on the wave. - * - * @attribute initialOpacity - * @type number - * @default 0.25 - */ - initialOpacity: { - type: Number, - value: 0.25 - }, - - /** - * How fast (opacity per second) the wave fades out. - * - * @attribute opacityDecayVelocity - * @type number - * @default 0.8 - */ - opacityDecayVelocity: { - type: Number, - value: 0.8 - }, - - /** - * If true, ripples will exhibit a gravitational pull towards - * the center of their container as they fade away. - * - * @attribute recenters - * @type boolean - * @default false - */ - recenters: { - type: Boolean, - value: false - }, - - /** - * If true, ripples will center inside its container - * - * @attribute recenters - * @type boolean - * @default false - */ - center: { - type: Boolean, - value: false - }, - - /** - * A list of the visual ripples. - * - * @attribute ripples - * @type Array - * @default [] - */ - ripples: { - type: Array, - value: function() { - return []; - } - }, - - /** - * True when there are visible ripples animating within the - * element. - */ - animating: { - type: Boolean, - readOnly: true, - reflectToAttribute: true, - value: false - }, - - /** - * If true, the ripple will remain in the "down" state until `holdDown` - * is set to false again. - */ - holdDown: { - type: Boolean, - value: false, - observer: '_holdDownChanged' - }, - - /** - * If true, the ripple will not generate a ripple effect - * via pointer interaction. - * Calling ripple's imperative api like `simulatedRipple` will - * still generate the ripple effect. - */ - noink: { - type: Boolean, - value: false - }, - - _animating: { - type: Boolean - }, - - _boundAnimate: { - type: Function, - value: function() { - return this.animate.bind(this); - } - } - }, - - get target () { - return this.keyEventTarget; - }, - - keyBindings: { - 'enter:keydown': '_onEnterKeydown', - 'space:keydown': '_onSpaceKeydown', - 'space:keyup': '_onSpaceKeyup' - }, - - attached: function() { - // Set up a11yKeysBehavior to listen to key events on the target, - // so that space and enter activate the ripple even if the target doesn't - // handle key events. The key handlers deal with `noink` themselves. - if (this.parentNode.nodeType == 11) { // DOCUMENT_FRAGMENT_NODE - this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host; - } else { - this.keyEventTarget = this.parentNode; - } - var keyEventTarget = /** @type {!EventTarget} */ (this.keyEventTarget); - this.listen(keyEventTarget, 'up', 'uiUpAction'); - this.listen(keyEventTarget, 'down', 'uiDownAction'); - }, - - detached: function() { - this.unlisten(this.keyEventTarget, 'up', 'uiUpAction'); - this.unlisten(this.keyEventTarget, 'down', 'uiDownAction'); - this.keyEventTarget = null; - }, - - get shouldKeepAnimating () { - for (var index = 0; index < this.ripples.length; ++index) { - if (!this.ripples[index].isAnimationComplete) { - return true; - } - } - - return false; - }, - - simulatedRipple: function() { - this.downAction(null); - - // Please see polymer/polymer#1305 - this.async(function() { - this.upAction(); - }, 1); - }, - - /** - * Provokes a ripple down effect via a UI event, - * respecting the `noink` property. - * @param {Event=} event - */ - uiDownAction: function(event) { - if (!this.noink) { - this.downAction(event); - } - }, - - /** - * Provokes a ripple down effect via a UI event, - * *not* respecting the `noink` property. - * @param {Event=} event - */ - downAction: function(event) { - if (this.holdDown && this.ripples.length > 0) { - return; - } - - var ripple = this.addRipple(); - - ripple.downAction(event); - - if (!this._animating) { - this._animating = true; - this.animate(); - } - }, - - /** - * Provokes a ripple up effect via a UI event, - * respecting the `noink` property. - * @param {Event=} event - */ - uiUpAction: function(event) { - if (!this.noink) { - this.upAction(event); - } - }, - - /** - * Provokes a ripple up effect via a UI event, - * *not* respecting the `noink` property. - * @param {Event=} event - */ - upAction: function(event) { - if (this.holdDown) { - return; - } - - this.ripples.forEach(function(ripple) { - ripple.upAction(event); - }); - - this._animating = true; - this.animate(); - }, - - onAnimationComplete: function() { - this._animating = false; - this.$.background.style.backgroundColor = null; - this.fire('transitionend'); - }, - - addRipple: function() { - var ripple = new Ripple(this); - - Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); - this.$.background.style.backgroundColor = ripple.color; - this.ripples.push(ripple); - - this._setAnimating(true); - - return ripple; - }, - - removeRipple: function(ripple) { - var rippleIndex = this.ripples.indexOf(ripple); - - if (rippleIndex < 0) { - return; - } - - this.ripples.splice(rippleIndex, 1); - - ripple.remove(); - - if (!this.ripples.length) { - this._setAnimating(false); - } - }, - - /** - * This conflicts with Element#antimate(). - * https://developer.mozilla.org/en-US/docs/Web/API/Element/animate - * @suppress {checkTypes} - */ - animate: function() { - if (!this._animating) { - return; - } - var index; - var ripple; - - for (index = 0; index < this.ripples.length; ++index) { - ripple = this.ripples[index]; - - ripple.draw(); - - this.$.background.style.opacity = ripple.outerOpacity; - - if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { - this.removeRipple(ripple); - } - } - - if (!this.shouldKeepAnimating && this.ripples.length === 0) { - this.onAnimationComplete(); - } else { - window.requestAnimationFrame(this._boundAnimate); - } - }, - - _onEnterKeydown: function() { - this.uiDownAction(); - this.async(this.uiUpAction, 1); - }, - - _onSpaceKeydown: function() { - this.uiDownAction(); - }, - - _onSpaceKeyup: function() { - this.uiUpAction(); - }, - - // note: holdDown does not respect noink since it can be a focus based - // effect. - _holdDownChanged: function(newVal, oldVal) { - if (oldVal === undefined) { - return; - } - if (newVal) { - this.downAction(); - } else { - this.upAction(); - } - } - - /** - Fired when the animation finishes. - This is useful if you want to wait until - the ripple animation finishes to perform some action. - - @event transitionend - @param {{node: Object}} detail Contains the animated node. - */ - }); - })(); -</script> |