perf(button-effect): using dom controller

This commit is contained in:
Manu Mtz.-Almeida
2018-01-17 02:30:57 +01:00
parent 19cf8afcc1
commit 8c05574a07
2 changed files with 44 additions and 41 deletions

View File

@ -12,6 +12,8 @@ ion-button-effect {
@include position(0, 0, 0, 0); @include position(0, 0, 0, 0);
position: absolute; position: absolute;
contain: strict;
} }
.button-effect { .button-effect {
@ -21,11 +23,13 @@ ion-button-effect {
background: $button-effect-ripple-background-color; background: $button-effect-ripple-background-color;
opacity: 0; opacity: 0;
will-change: transform; will-change: transform, opacity;
animation-name: rippleAnimation; animation-name: rippleAnimation;
animation-duration: 1000ms; animation-duration: 200ms;
animation-timing-function: ease-in-out; animation-timing-function: ease-in-out;
contain: strict;
} }
@keyframes rippleAnimation { @keyframes rippleAnimation {

View File

@ -1,12 +1,6 @@
import { Component, Element, Listen, State } from '@stencil/core'; import { Component, Element, Listen, Prop, State } from '@stencil/core';
import { now } from '../../utils/helpers'; import { now } from '../../utils/helpers';
import { DomController } from '../../global/dom-controller';
interface Ripple {
x: number;
y: number;
size: number;
time?: number;
}
@Component({ @Component({
tag: 'ion-button-effect', tag: 'ion-button-effect',
@ -14,37 +8,44 @@ interface Ripple {
}) })
export class ButtonEffect { export class ButtonEffect {
private lastClick = 0; private lastClick = -10000;
@Element() el: HTMLElement; @Element() el: HTMLElement;
@State() state = 0; @State() state = 0;
@Listen('mousedown') @Prop({context: 'dom'}) dom: DomController;
@Listen('touchstart') @Listen('touchstart')
pointerDown(ev: MouseEvent) { touchStart(ev: TouchEvent) {
this.lastClick = now(ev);
const touches = ev.touches[0];
this.addRipple(touches.clientX, touches.clientY);
}
@Listen('mousedown')
mouseDown(ev: MouseEvent) {
const timeStamp = now(ev); const timeStamp = now(ev);
if (this.lastClick < (timeStamp - DELAY)) { if (this.lastClick < (timeStamp - 1000)) {
this.addRipple(ev.clientX, ev.clientY); this.addRipple(ev.pageX, ev.pageY);
this.lastClick = timeStamp;
} }
} }
private addRipple(pageX: number, pageY: number) { private addRipple(pageX: number, pageY: number) {
let x: number, y: number, size: number;
this.dom.read(() => {
const rect = this.el.getBoundingClientRect(); const rect = this.el.getBoundingClientRect();
const width = rect.width; const width = rect.width;
const height = rect.height; const height = rect.height;
const size = Math.sqrt(width * width + height * height) * 2; size = Math.sqrt(width * width + height * height) * 2;
const x = pageX - rect.left - size / 2; x = pageX - rect.left - (size / 2);
const y = pageY - rect.top - size / 2; y = pageY - rect.top - (size / 2);
});
this.schedule({x, y, size}); this.dom.write(() => {
}
private schedule({x, y, size}: Ripple) {
const div = document.createElement('div'); const div = document.createElement('div');
div.classList.add('button-effect'); div.classList.add('button-effect');
const style = div.style; const style = div.style;
const duration = Math.max(800 * Math.sqrt(size / TOUCH_DOWN_ACCEL) + 0.5, 260); const duration = Math.max(800 * Math.sqrt(size / 350) + 0.5, 260);
style.top = y + 'px'; style.top = y + 'px';
style.left = x + 'px'; style.left = x + 'px';
style.width = size + 'px'; style.width = size + 'px';
@ -53,8 +54,6 @@ export class ButtonEffect {
this.el.appendChild(div); this.el.appendChild(div);
setTimeout(() => this.el.removeChild(div), duration + 50); setTimeout(() => this.el.removeChild(div), duration + 50);
});
} }
} }
const TOUCH_DOWN_ACCEL = 350;
const DELAY = 50;