mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
186 lines
5.4 KiB
TypeScript
186 lines
5.4 KiB
TypeScript
/**
|
|
* Lovingly Adapted from Material Design Lite
|
|
* Copyright Google, 2015, Licensed under the Apache 2 license.
|
|
* https://github.com/google/material-design-lite
|
|
*/
|
|
|
|
import {ElementRef, forwardRef} from 'angular2/angular2';
|
|
|
|
import {MaterialButton} from './button';
|
|
|
|
export class MaterialRippleEffect {
|
|
constructor(button: MaterialButton) {
|
|
this.elementRef = button.elementRef;
|
|
this.element = this.elementRef.nativeElement;
|
|
|
|
var rippleContainer = document.createElement('span');
|
|
rippleContainer.classList.add('md-ripple-container');
|
|
this.rippleElement = document.createElement('span');
|
|
this.rippleElement.classList.add('md-ripple');
|
|
rippleContainer.appendChild(this.rippleElement);
|
|
|
|
this.recentering = false;//this.element.classList.contains(this.CssClasses_.RIPPLE_CENTER);
|
|
|
|
this.INITIAL_SCALE = 'scale(0.0001, 0.0001)';
|
|
this.INITIAL_SIZE = '1px';
|
|
this.INITIAL_OPACITY = '0.4';
|
|
this.FINAL_OPACITY = '0';
|
|
this.FINAL_SCALE = '';
|
|
|
|
|
|
//this.boundRippleBlurHandler = this.blurHandler.bind(this);
|
|
//this.rippleElement_.addEventListener('mouseup', this.boundRippleBlurHandler);
|
|
|
|
this.elementRef.nativeElement.appendChild(rippleContainer);
|
|
|
|
this._initRipple();
|
|
}
|
|
|
|
_initRipple() {
|
|
this.frameCount = 0;
|
|
this.rippleSize = 0;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
|
|
// Touch start produces a compat mouse down event, which would cause a
|
|
// second ripples. To avoid that, we use this property to ignore the first
|
|
// mouse down after a touch start.
|
|
this.ignoringMouseDown = false;
|
|
|
|
this.boundDownHandler = this.downHandler.bind(this);
|
|
this.element.addEventListener('mousedown', this.boundDownHandler);
|
|
this.element.addEventListener('touchstart', this.boundDownHandler);
|
|
|
|
this.boundUpHandler = this.upHandler.bind(this);
|
|
this.element.addEventListener('mouseup', this.boundUpHandler);
|
|
this.element.addEventListener('mouseleave', this.boundUpHandler);
|
|
this.element.addEventListener('touchend', this.boundUpHandler);
|
|
this.element.addEventListener('blur', this.boundUpHandler);
|
|
}
|
|
|
|
/**
|
|
* Handle mouse / finger down on element.
|
|
* @param {Event} event The event that fired.
|
|
* @private
|
|
*/
|
|
downHandler(event) {
|
|
'use strict';
|
|
|
|
if (!this.rippleElement.style.width && !this.rippleElement.style.height) {
|
|
var rect = this.element.getBoundingClientRect();
|
|
this.boundHeight = rect.height;
|
|
this.boundWidth = rect.width;
|
|
this.rippleSize = Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2;
|
|
this.rippleElement.style.width = this.rippleSize + 'px';
|
|
this.rippleElement.style.height = this.rippleSize + 'px';
|
|
}
|
|
|
|
this.rippleElement.classList.add('is-visible');
|
|
|
|
if (event.type === 'mousedown' && this.ignoringMouseDown) {
|
|
this.ignoringMouseDown = false;
|
|
} else {
|
|
if (event.type === 'touchstart') {
|
|
this.ignoringMouseDown = true;
|
|
}
|
|
var frameCount = this.getFrameCount();
|
|
if (frameCount > 0) {
|
|
return;
|
|
}
|
|
this.setFrameCount(1);
|
|
var bound = event.currentTarget.getBoundingClientRect();
|
|
var x;
|
|
var y;
|
|
// Check if we are handling a keyboard click.
|
|
if (event.clientX === 0 && event.clientY === 0) {
|
|
x = Math.round(bound.width / 2);
|
|
y = Math.round(bound.height / 2);
|
|
} else {
|
|
var clientX = event.clientX ? event.clientX : event.touches[0].clientX;
|
|
var clientY = event.clientY ? event.clientY : event.touches[0].clientY;
|
|
x = Math.round(clientX - bound.left);
|
|
y = Math.round(clientY - bound.top);
|
|
}
|
|
this.setRippleXY(x, y);
|
|
this.setRippleStyles(true);
|
|
window.requestAnimationFrame(this.animFrameHandler.bind(this));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle mouse / finger up on element.
|
|
* @param {Event} event The event that fired.
|
|
* @private
|
|
*/
|
|
upHandler(event) {
|
|
'use strict';
|
|
|
|
// Don't fire for the artificial "mouseup" generated by a double-click.
|
|
if (event && event.detail !== 2) {
|
|
setTimeout(() => {
|
|
this.rippleElement.classList.remove('is-visible');
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
getFrameCount() {
|
|
return this.frameCount;
|
|
}
|
|
|
|
setFrameCount(fC) {
|
|
this.frameCount = fC;
|
|
}
|
|
|
|
getRippleElement() {
|
|
return this.rippleElement;
|
|
}
|
|
|
|
setRippleXY(newX, newY) {
|
|
this.x = newX;
|
|
this.y = newY;
|
|
}
|
|
|
|
setRippleStyles(start) {
|
|
if (this.rippleElement !== null) {
|
|
var transformString;
|
|
var scale;
|
|
var size;
|
|
var offset = 'translate(' + this.x + 'px, ' + this.y + 'px)';
|
|
|
|
if (start) {
|
|
scale = this.INITIAL_SCALE;
|
|
size = this.INITIAL_SIZE;
|
|
} else {
|
|
scale = this.FINAL_SCALE;
|
|
size = this.rippleSize + 'px';
|
|
if (this.recentering) {
|
|
offset = 'translate(' + this.boundWidth / 2 + 'px, ' + this.boundHeight / 2 + 'px)';
|
|
}
|
|
}
|
|
|
|
transformString = 'translate(-50%, -50%) ' + offset + scale;
|
|
|
|
this.rippleElement.style.webkitTransform = transformString;
|
|
this.rippleElement.style.msTransform = transformString;
|
|
this.rippleElement.style.transform = transformString;
|
|
|
|
if (start) {
|
|
this.rippleElement.classList.remove('md-ripple-animating');
|
|
} else {
|
|
this.rippleElement.classList.add('md-ripple-animating');
|
|
}
|
|
}
|
|
}
|
|
|
|
animFrameHandler() {
|
|
if (this.frameCount-- > 0) {
|
|
window.requestAnimationFrame(this.animFrameHandler.bind(this));
|
|
} else {
|
|
this.setRippleStyles(false);
|
|
}
|
|
}
|
|
|
|
elementClicked(event) {}
|
|
}
|