mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 05:58:26 +08:00
perf(button-effect): using dom controller
This commit is contained in:
@ -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 {
|
||||||
|
@ -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,47 +8,52 @@ 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) {
|
||||||
const rect = this.el.getBoundingClientRect();
|
let x: number, y: number, size: number;
|
||||||
const width = rect.width;
|
|
||||||
const height = rect.height;
|
|
||||||
const size = Math.sqrt(width * width + height * height) * 2;
|
|
||||||
const x = pageX - rect.left - size / 2;
|
|
||||||
const y = pageY - rect.top - size / 2;
|
|
||||||
|
|
||||||
this.schedule({x, y, size});
|
this.dom.read(() => {
|
||||||
|
const rect = this.el.getBoundingClientRect();
|
||||||
|
const width = rect.width;
|
||||||
|
const height = rect.height;
|
||||||
|
size = Math.sqrt(width * width + height * height) * 2;
|
||||||
|
x = pageX - rect.left - (size / 2);
|
||||||
|
y = pageY - rect.top - (size / 2);
|
||||||
|
});
|
||||||
|
this.dom.write(() => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add('button-effect');
|
||||||
|
const style = div.style;
|
||||||
|
const duration = Math.max(800 * Math.sqrt(size / 350) + 0.5, 260);
|
||||||
|
style.top = y + 'px';
|
||||||
|
style.left = x + 'px';
|
||||||
|
style.width = size + 'px';
|
||||||
|
style.height = size + 'px';
|
||||||
|
style.animationDuration = duration + 'ms';
|
||||||
|
|
||||||
|
this.el.appendChild(div);
|
||||||
|
setTimeout(() => this.el.removeChild(div), duration + 50);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private schedule({x, y, size}: Ripple) {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
div.classList.add('button-effect');
|
|
||||||
const style = div.style;
|
|
||||||
const duration = Math.max(800 * Math.sqrt(size / TOUCH_DOWN_ACCEL) + 0.5, 260);
|
|
||||||
style.top = y + 'px';
|
|
||||||
style.left = x + 'px';
|
|
||||||
style.width = size + 'px';
|
|
||||||
style.height = size + 'px';
|
|
||||||
style.animationDuration = duration + 'ms';
|
|
||||||
|
|
||||||
this.el.appendChild(div);
|
|
||||||
setTimeout(() => this.el.removeChild(div), duration + 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
const TOUCH_DOWN_ACCEL = 350;
|
|
||||||
const DELAY = 50;
|
|
||||||
|
Reference in New Issue
Block a user