| Index: third_party/polymer/components-chromium/paper-ripple/raw-extracted.js
|
| 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 0000000000000000000000000000000000000000..95faeb62cea319513a65288919cc0d3a4e5e5137
|
| --- /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);
|
|
|