summaryrefslogtreecommitdiffstats
path: root/third_party/polymer/components-chromium/paper-ripple/raw-extracted.js
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/polymer/components-chromium/paper-ripple/raw-extracted.js')
-rw-r--r--third_party/polymer/components-chromium/paper-ripple/raw-extracted.js410
1 files changed, 410 insertions, 0 deletions
diff --git a/third_party/polymer/components-chromium/paper-ripple/raw-extracted.js b/third_party/polymer/components-chromium/paper-ripple/raw-extracted.js
new file mode 100644
index 0000000..95faeb6
--- /dev/null
+++ b/third_party/polymer/components-chromium/paper-ripple/raw-extracted.js
@@ -0,0 +1,410 @@
+
+
+//
+// INK EQUATIONS
+//
+
+// Animation constants.
+var globalSpeed = 1;
+var waveOpacityDecayVelocity = 0.8 / globalSpeed; // opacity per second.
+var waveInitialOpacity = 0.25;
+var waveLingerOnTouchUp = 0.2;
+var waveMaxRadius = 150;
+
+// TODOs:
+// - rather than max distance to corner, use hypotenuos(sp) (diag)
+// - use quadratic for the fall off, move fast at the beginning,
+// - on cancel, immediately fade out, reverse the direction
+
+function waveRadiusFn(touchDownMs, touchUpMs, ww, hh) {
+ // Convert from ms to s.
+ var touchDown = touchDownMs / 1000;
+ var touchUp = touchUpMs / 1000;
+ var totalElapsed = touchDown + touchUp;
+ var waveRadius = Math.min(Math.max(ww, hh), waveMaxRadius) * 1.1 + 5;
+ var dduration = 1.1 - .2 * (waveRadius / waveMaxRadius);
+ var tt = (totalElapsed / dduration);
+
+ var ssize = waveRadius * (1 - Math.pow(80, -tt));
+ return Math.abs(ssize);
+}
+
+function waveOpacityFn(td, tu) {
+ // Convert from ms to s.
+ var touchDown = td / 1000;
+ var touchUp = tu / 1000;
+ var totalElapsed = touchDown + touchUp;
+
+ if (tu <= 0) { // before touch up
+ return waveInitialOpacity;
+ }
+ return Math.max(0, waveInitialOpacity - touchUp * waveOpacityDecayVelocity);
+}
+
+function waveOuterOpacityFn(td, tu) {
+ // Convert from ms to s.
+ var touchDown = td / 1000;
+ var touchUp = tu / 1000;
+
+ // Linear increase in background opacity, capped at the opacity
+ // of the wavefront (waveOpacity).
+ var outerOpacity = touchDown * 0.3;
+ var waveOpacity = waveOpacityFn(td, tu);
+ return Math.max(0, Math.min(outerOpacity, waveOpacity));
+
+}
+
+function waveGravityToCenterPercentageFn(td, tu, r) {
+ // Convert from ms to s.
+ var touchDown = td / 1000;
+ var touchUp = tu / 1000;
+ var totalElapsed = touchDown + touchUp;
+
+ return Math.min(1.0, touchUp * 6);
+}
+
+
+// Determines whether the wave should be completely removed.
+function waveDidFinish(wave, radius) {
+ var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp);
+ // Does not linger any more.
+ // var lingerTimeMs = waveLingerOnTouchUp * 1000;
+
+ // If the wave opacity is 0 and the radius exceeds the bounds
+ // of the element, then this is finished.
+ if (waveOpacity < 0.01 && radius >= wave.maxRadius) {
+ return true;
+ }
+ return false;
+};
+
+//
+// DRAWING
+//
+
+function animateIcon() {
+ var el = document.getElementById('button_toolbar0');
+ el.classList.add('animate');
+ setTimeout(function(){
+ el.classList.remove('animate');
+ el.classList.toggle('selected');
+ }, 500);
+}
+
+
+function drawRipple(canvas, x, y, radius, innerColor, outerColor, innerColorAlpha, outerColorAlpha) {
+ var ctx = canvas.getContext('2d');
+ if (outerColor) {
+ ctx.fillStyle = outerColor;
+ ctx.fillRect(0,0,canvas.width, canvas.height);
+ }
+
+ ctx.beginPath();
+ ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
+ ctx.fillStyle = innerColor;
+ ctx.fill();
+}
+
+function drawLabel(canvas, label, fontSize, color, alignment) {
+ var ctx = canvas.getContext('2d');
+ ctx.font= fontSize + 'px Helvetica';
+
+ var metrics = ctx.measureText(label);
+ var width = metrics.width;
+ var height = metrics.height;
+ ctx.fillStyle = color;
+
+ var xPos = (canvas.width/2 - width)/2;
+
+ if (alignment === 'left') { xPos = 16; }
+
+ ctx.fillText(label, xPos, canvas.height/2 - (canvas.height/2 - fontSize +2) / 2);
+}
+
+//
+// BUTTON SETUP
+//
+
+function createWave(elem) {
+ var elementStyle = window.getComputedStyle(elem);
+ var fgColor = elementStyle.color;
+
+ var wave = {
+ waveColor: fgColor,
+ maxRadius: 0,
+ isMouseDown: false,
+ mouseDownStart: 0.0,
+ mouseUpStart: 0.0,
+ tDown: 0,
+ tUp: 0
+ };
+ return wave;
+}
+
+function removeWaveFromScope(scope, wave) {
+ if (scope.waves) {
+ var pos = scope.waves.indexOf(wave);
+ scope.waves.splice(pos, 1);
+ }
+};
+
+
+function setUpPaperByClass( classname ) {
+ var elems = document.querySelectorAll( classname );
+ [].forEach.call( elems, function( el ) {
+ setUpPaper(el);
+ });
+}
+
+function setUpPaper(elem) {
+ var pixelDensity = 2;
+
+ var elementStyle = window.getComputedStyle(elem);
+ var fgColor = elementStyle.color;
+ var bgColor = elementStyle.backgroundColor;
+ elem.width = elem.clientWidth;
+ elem.setAttribute('width', elem.clientWidth * pixelDensity + "px");
+ elem.setAttribute('height', elem.clientHeight * pixelDensity + "px");
+
+ var isButton = elem.classList.contains( 'button' ) || elem.classList.contains( 'button_floating' ) | elem.classList.contains( 'button_menu' );
+ var isToolbarButton = elem.classList.contains( 'button_toolbar' );
+
+ elem.getContext('2d').scale(pixelDensity, pixelDensity)
+
+ var scope = {
+ backgroundFill: true,
+ element: elem,
+ label: 'Button',
+ waves: [],
+ };
+
+
+ scope.label = elem.getAttribute('value') || elementStyle.content;
+ scope.labelFontSize = elementStyle.fontSize.split("px")[0];
+
+ drawLabel(elem, scope.label, scope.labelFontSize, fgColor, elem.style.textAlign);
+
+
+ //
+ // RENDER FOR EACH FRAME
+ //
+ var onFrame = function() {
+ var shouldRenderNextFrame = false;
+
+ // Clear the canvas
+ var ctx = elem.getContext('2d');
+ ctx.clearRect(0, 0, elem.width, elem.height);
+
+ var deleteTheseWaves = [];
+ // The oldest wave's touch down duration
+ var longestTouchDownDuration = 0;
+ var longestTouchUpDuration = 0;
+ // Save the last known wave color
+ var lastWaveColor = null;
+
+ for (var i = 0; i < scope.waves.length; i++) {
+ var wave = scope.waves[i];
+
+ if (wave.mouseDownStart > 0) {
+ wave.tDown = now() - wave.mouseDownStart;
+ }
+ if (wave.mouseUpStart > 0) {
+ wave.tUp = now() - wave.mouseUpStart;
+ }
+
+ // Determine how long the touch has been up or down.
+ var tUp = wave.tUp;
+ var tDown = wave.tDown;
+ longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown);
+ longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp);
+
+ // Obtain the instantenous size and alpha of the ripple.
+ var radius = waveRadiusFn(tDown, tUp, elem.width, elem.height);
+ var waveAlpha = waveOpacityFn(tDown, tUp);
+ var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha);
+ lastWaveColor = wave.waveColor;
+
+ // Position of the ripple.
+ var x = wave.startPosition.x;
+ var y = wave.startPosition.y;
+
+ // Ripple gravitational pull to the center of the canvas.
+ if (wave.endPosition) {
+
+ var translateFraction = waveGravityToCenterPercentageFn(tDown, tUp, wave.maxRadius);
+
+ // This translates from the origin to the center of the view based on the max dimension of
+ var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) );
+
+ x += translateFraction * (wave.endPosition.x - wave.startPosition.x);
+ y += translateFraction * (wave.endPosition.y - wave.startPosition.y);
+ }
+
+ // If we do a background fill fade too, work out the correct color.
+ var bgFillColor = null;
+ if (scope.backgroundFill) {
+ var bgFillAlpha = waveOuterOpacityFn(tDown, tUp);
+ bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha);
+ }
+
+ // Draw the ripple.
+ drawRipple(elem, x, y, radius, waveColor, bgFillColor);
+
+ // Determine whether there is any more rendering to be done.
+ var shouldRenderWaveAgain = !waveDidFinish(wave, radius);
+ shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain;
+ if (!shouldRenderWaveAgain) {
+ deleteTheseWaves.push(wave);
+ }
+ }
+
+ if (shouldRenderNextFrame) {
+ window.requestAnimationFrame(onFrame);
+ } else {
+ // If there is nothing to draw, clear any drawn waves now because
+ // we're not going to get another requestAnimationFrame any more.
+ var ctx = elem.getContext('2d');
+ ctx.clearRect(0, 0, elem.width, elem.height);
+ }
+
+ // Draw the label at the very last point so it is on top of everything.
+ drawLabel(elem, scope.label, scope.labelFontSize, fgColor, elem.style.textAlign);
+
+ for (var i = 0; i < deleteTheseWaves.length; ++i) {
+ var wave = deleteTheseWaves[i];
+ removeWaveFromScope(scope, wave);
+ }
+ };
+
+ //
+ // MOUSE DOWN HANDLER
+ //
+
+ elem.addEventListener('mousedown', function(e) {
+ var wave = createWave(e.target);
+ var elem = scope.element;
+
+ wave.isMouseDown = true;
+ wave.tDown = 0.0;
+ wave.tUp = 0.0;
+ wave.mouseUpStart = 0.0;
+ wave.mouseDownStart = now();
+
+ var width = e.target.width / 2; // Retina canvas
+ var height = e.target.height / 2;
+ var touchX = e.clientX - e.target.offsetLeft - e.target.offsetParent.offsetLeft;
+ var touchY = e.clientY - e.target.offsetTop - e.target.offsetParent.offsetTop;
+ wave.startPosition = {x:touchX, y:touchY};
+
+ if (elem.classList.contains("recenteringTouch")) {
+ wave.endPosition = {x: width / 2, y: height / 2};
+ wave.slideDistance = dist(wave.startPosition, wave.endPosition);
+ }
+ wave.containerSize = Math.max(width, height);
+ wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height});
+ elem.classList.add("activated");
+ scope.waves.push(wave);
+ window.requestAnimationFrame(onFrame);
+ return false;
+ });
+
+ //
+ // MOUSE UP HANDLER
+ //
+
+ elem.addEventListener('mouseup', function(e) {
+ elem.classList.remove("activated");
+
+ for (var i = 0; i < scope.waves.length; i++) {
+ // Declare the next wave that has mouse down to be mouse'ed up.
+ var wave = scope.waves[i];
+ if (wave.isMouseDown) {
+ wave.isMouseDown = false
+ wave.mouseUpStart = now();
+ wave.mouseDownStart = 0;
+ wave.tUp = 0.0;
+ break;
+ }
+ }
+ return false;
+ });
+
+ elem.addEventListener('mouseout', function(e) {
+ elem.classList.remove("activated");
+
+ for (var i = 0; i < scope.waves.length; i++) {
+ // Declare the next wave that has mouse down to be mouse'ed up.
+ var wave = scope.waves[i];
+ if (wave.isMouseDown) {
+ wave.isMouseDown = false
+ wave.mouseUpStart = now();
+ wave.mouseDownStart = 0;
+ wave.tUp = 0.0;
+ wave.cancelled = true;
+ break;
+ }
+ }
+ return false;
+ });
+
+ return scope;
+};
+
+// Shortcuts.
+var pow = Math.pow;
+var now = function() { return new Date().getTime(); };
+
+// Quad beizer where t is between 0 and 1.
+function quadBezier(t, p0, p1, p2, p3) {
+ return pow(1 - t, 3) * p0 +
+ 3 * pow(1 - t, 2) * t * p1 +
+ (1 - t) * pow(t, 2) * p2 +
+ pow(t, 3) * p3;
+}
+
+function easeIn(t) {
+ return quadBezier(t, 0.4, 0.0, 1, 1);
+}
+
+function cssColorWithAlpha(cssColor, alpha) {
+ var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
+ if (typeof alpha == 'undefined') {
+ alpha = 1;
+ }
+ if (!parts) {
+ return 'rgba(255, 255, 255, ' + alpha + ')';
+ }
+ return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')';
+}
+
+function dist(p1, p2) {
+ return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
+}
+
+function distanceFromPointToFurthestCorner(point, size) {
+ var tl_d = dist(point, {x: 0, y: 0});
+ var tr_d = dist(point, {x: size.w, y: 0});
+ var bl_d = dist(point, {x: 0, y: size.h});
+ var br_d = dist(point, {x: size.w, y: size.h});
+ return Math.max(Math.max(tl_d, tr_d), Math.max(bl_d, br_d));
+}
+
+
+function toggleDialog() {
+ var el = document.getElementById('dialog');
+ el.classList.toggle("visible");
+}
+
+function toggleMenu() {
+ var el = document.getElementById('menu');
+ el.classList.toggle("visible");
+}
+
+
+// Initialize
+
+function init() {
+ setUpPaperByClass( '.paper' );
+}
+
+window.addEventListener('DOMContentLoaded', init, false);