Improve ripple performance. Fixes #142
parent
f6840de8ea
commit
ac5501b9a5
|
@ -1,4 +1,4 @@
|
|||
//-- Typography
|
||||
// scss-lint:disable VendorPrefix
|
||||
@mixin typo-preferred-font($use-preferred: true) {
|
||||
@if $use-preferred {
|
||||
font-family: $preferred-font;
|
||||
|
@ -262,21 +262,18 @@
|
|||
@mixin ripple-loading($name, $width, $height, $opacity: 0.3) {
|
||||
@keyframes #{$name} {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: $opacity;
|
||||
transform: translate3d(-50%, -50%, 0) scale(0);
|
||||
}
|
||||
|
||||
95% {
|
||||
width: $width;
|
||||
height: $height;
|
||||
opacity: 0;
|
||||
transform: translate3d(-50%, -50%, 0) scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
transform: translate3d(-50%, -50%, 0) scale(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ class Button extends React.Component {
|
|||
};
|
||||
|
||||
return React.createElement(element, props,
|
||||
ripple ? <Ripple ref='ripple' loading={loading}/> : null,
|
||||
ripple ? <Ripple ref='ripple' loading={loading} /> : null,
|
||||
tooltip ? <Tooltip className={style.tooltip} label={tooltip}/> : null,
|
||||
icon ? <FontIcon className={style.icon} value={icon}/> : null,
|
||||
label ? label : this.props.children
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
@import "./config";
|
||||
|
||||
%button {
|
||||
@include typo-button();
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: $button-height;
|
||||
|
@ -24,7 +25,6 @@
|
|||
border: 0;
|
||||
}
|
||||
> span:not(.tooltip) {
|
||||
@include typo-button();
|
||||
display: inline-block;
|
||||
line-height: $button-height;
|
||||
vertical-align: middle;
|
||||
|
@ -41,7 +41,7 @@
|
|||
pointer-events: none;
|
||||
}
|
||||
[data-react-toolbox="ripple"] {
|
||||
overflow: hidden;
|
||||
@include rounded-overflow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,10 +97,8 @@
|
|||
}
|
||||
.icon {
|
||||
font-size: 120%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.icon {
|
||||
line-height: $button-height;
|
||||
vertical-align: middle;
|
||||
}
|
||||
[data-react-toolbox="ripple"] {
|
||||
border-radius: 50%;
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
@import "./base";
|
||||
@import "~normalize.css";
|
||||
|
||||
$import-normalize: true !default;
|
||||
$import-font: true !default;
|
||||
$import-flex-attributes: false !default;
|
||||
|
||||
@if $import-normalize == true {
|
||||
@import "~normalize.css";
|
||||
}
|
||||
|
||||
@if $import-font == true {
|
||||
@import url($font-roboto-url);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import prefixer from '../utils/prefixer';
|
||||
import style from './style';
|
||||
|
||||
class Ripple extends React.Component {
|
||||
|
@ -25,32 +26,41 @@ class Ripple extends React.Component {
|
|||
width: null
|
||||
};
|
||||
|
||||
handleEnd = (touch = false) => {
|
||||
document.removeEventListener(touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
handleEnd = () => {
|
||||
document.removeEventListener(this.touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
this.setState({active: false});
|
||||
};
|
||||
|
||||
start = ({ pageX, pageY }, touch = false) => {
|
||||
document.addEventListener(touch ? 'touchend' : 'mouseup', this.handleEnd.bind(this, touch));
|
||||
start = ({pageX, pageY}, touch = false) => {
|
||||
this.touch = touch;
|
||||
document.addEventListener(this.touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
const {top, left, width} = this._getDescriptor(pageX, pageY);
|
||||
this.setState({active: false, restarting: true, width: 0}, () => {
|
||||
this.setState({active: false, restarting: true, top, left, width}, () => {
|
||||
this.refs.ripple.offsetWidth; //eslint-disable-line no-unused-expressions
|
||||
this.setState({active: true, restarting: false, top, left, width});
|
||||
this.setState({active: true, restarting: false});
|
||||
});
|
||||
};
|
||||
|
||||
_getDescriptor (pageX, pageY) {
|
||||
const { left, top, height, width } = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
||||
const {left, top, height, width} = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
||||
return {
|
||||
left: this.props.centered ? width / 2 : pageX - left + window.scrollX,
|
||||
top: this.props.centered ? height / 2 : pageY - top + window.scrollY,
|
||||
left: this.props.centered ? 0 : pageX - left - width / 2 + window.scrollX,
|
||||
top: this.props.centered ? 0 : pageY - top - height / 2 + window.scrollY,
|
||||
width: width * this.props.spread
|
||||
};
|
||||
}
|
||||
|
||||
render () {
|
||||
const { left, top, width } = this.state;
|
||||
const rippleStyle = {left, top, width, height: width};
|
||||
const scale = this.state.restarting ? 0 : 1;
|
||||
let rippleStyle = {width, height: width};
|
||||
|
||||
if (!this.props.loading) {
|
||||
rippleStyle = prefixer({
|
||||
transform: `translate3d(${-width / 2 + left}px, ${-width / 2 + top}px, 0) scale(${scale})`
|
||||
}, rippleStyle);
|
||||
}
|
||||
|
||||
let className = style[this.props.loading ? 'loading' : 'normal'];
|
||||
if (this.state.active) className += ` ${style.active}`;
|
||||
if (this.state.restarting) className += ` ${style.restarting}`;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
%ripple {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: $z-index-high;
|
||||
pointer-events: none;
|
||||
background-color: currentColor;
|
||||
|
@ -23,31 +25,23 @@
|
|||
.normal {
|
||||
@extend %ripple;
|
||||
transition-duration: $ripple-duration;
|
||||
|
||||
&.restarting {
|
||||
transform: translate3d(-50%, -50%, 0) scale(0);
|
||||
opacity: $ripple-final-opacity;
|
||||
transition-property: none;
|
||||
opacity: $ripple-final-opacity;
|
||||
}
|
||||
|
||||
&.active {
|
||||
transform: translate3d(-50%, -50%, 0) scale(1);
|
||||
transition-property: transform;
|
||||
opacity: $ripple-final-opacity;
|
||||
transition-property: transform;
|
||||
}
|
||||
|
||||
&:not(.active):not(.restarting) {
|
||||
transform: translate3d(-50%, -50%, 0) scale(1);
|
||||
transition-property: opacity, transform;
|
||||
opacity: 0;
|
||||
transition-property: opacity, transform;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
@extend %ripple;
|
||||
@include ripple-loading(ripple, $ripple-size, $ripple-size);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: $ripple-size;
|
||||
height: $ripple-size;
|
||||
opacity: $ripple-final-opacity;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
line-height: $font-size-small;
|
||||
color: $tooltip-color;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
background: $tooltip-background;
|
||||
border-radius: $tooltip-border-radius;
|
||||
transform: scale(0);
|
||||
|
|
|
@ -25,8 +25,8 @@ function addPrefixesTo (style, property, value) {
|
|||
return style;
|
||||
}
|
||||
|
||||
function prefixer (style) {
|
||||
const _style = {};
|
||||
function prefixer (style, defaultValue = {}) {
|
||||
const _style = defaultValue;
|
||||
for (const property in style) {
|
||||
_style[property] = style[property];
|
||||
if (properties[property]) {
|
||||
|
|
Loading…
Reference in New Issue