移动目录
This commit is contained in:
175
mdui_patched/components/ripple/index.js
Normal file
175
mdui_patched/components/ripple/index.js
Normal file
@@ -0,0 +1,175 @@
|
||||
import { __decorate } from "tslib";
|
||||
import { html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { createRef, ref } from 'lit/directives/ref.js';
|
||||
import { $ } from '@mdui/jq/$.js';
|
||||
import '@mdui/jq/methods/addClass.js';
|
||||
import '@mdui/jq/methods/children.js';
|
||||
import '@mdui/jq/methods/css.js';
|
||||
import '@mdui/jq/methods/data.js';
|
||||
import '@mdui/jq/methods/each.js';
|
||||
import '@mdui/jq/methods/filter.js';
|
||||
import '@mdui/jq/methods/innerHeight.js';
|
||||
import '@mdui/jq/methods/innerWidth.js';
|
||||
import '@mdui/jq/methods/offset.js';
|
||||
import '@mdui/jq/methods/on.js';
|
||||
import '@mdui/jq/methods/prependTo.js';
|
||||
import '@mdui/jq/methods/remove.js';
|
||||
import { MduiElement } from '@mdui/shared/base/mdui-element.js';
|
||||
import { booleanConverter } from '@mdui/shared/helpers/decorator.js';
|
||||
import { componentStyle } from '@mdui/shared/lit-styles/component-style.js';
|
||||
import { style } from './style.js';
|
||||
/**
|
||||
* 处理点击时的涟漪动画;及添加 hover、focused、dragged 的背景色
|
||||
* 背景色通过在 .surface 元素上添加对应的 class 实现
|
||||
* 阴影在 ripple-mixin 中处理,通过在 :host 元素上添加 attribute 供 CSS 选择器添加样式
|
||||
*/
|
||||
let Ripple = class Ripple extends MduiElement {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
/**
|
||||
* 是否禁用涟漪动画
|
||||
*/
|
||||
this.noRipple = false;
|
||||
this.hover = false;
|
||||
this.focused = false;
|
||||
this.dragged = false;
|
||||
this.surfaceRef = createRef();
|
||||
}
|
||||
startPress(event) {
|
||||
if (this.noRipple) {
|
||||
return;
|
||||
}
|
||||
const $surface = $(this.surfaceRef.value);
|
||||
const surfaceHeight = $surface.innerHeight();
|
||||
const surfaceWidth = $surface.innerWidth();
|
||||
// 点击位置坐标
|
||||
let touchStartX;
|
||||
let touchStartY;
|
||||
if (!event) {
|
||||
// 未传入事件对象,涟漪从中间扩散
|
||||
touchStartX = surfaceWidth / 2;
|
||||
touchStartY = surfaceHeight / 2;
|
||||
}
|
||||
else {
|
||||
// 传入了事件对象,涟漪从点击位置扩散
|
||||
const touchPosition = typeof TouchEvent !== 'undefined' &&
|
||||
event instanceof TouchEvent &&
|
||||
event.touches.length
|
||||
? event.touches[0]
|
||||
: event;
|
||||
const offset = $surface.offset();
|
||||
// 点击位置不在 surface 内,不执行
|
||||
if (touchPosition.pageX < offset.left ||
|
||||
touchPosition.pageX > offset.left + surfaceWidth ||
|
||||
touchPosition.pageY < offset.top ||
|
||||
touchPosition.pageY > offset.top + surfaceHeight) {
|
||||
return;
|
||||
}
|
||||
touchStartX = touchPosition.pageX - offset.left;
|
||||
touchStartY = touchPosition.pageY - offset.top;
|
||||
}
|
||||
// 涟漪直径
|
||||
const diameter = Math.max(Math.pow(Math.pow(surfaceHeight, 2) + Math.pow(surfaceWidth, 2), 0.5), 48);
|
||||
// 涟漪扩散动画
|
||||
const translateX = `${-touchStartX + surfaceWidth / 2}px`;
|
||||
const translateY = `${-touchStartY + surfaceHeight / 2}px`;
|
||||
const translate = `translate3d(${translateX}, ${translateY}, 0) scale(1)`;
|
||||
// 涟漪 DOM 元素
|
||||
$('<div class="wave"></div>')
|
||||
.css({
|
||||
width: diameter,
|
||||
height: diameter,
|
||||
marginTop: -diameter / 2,
|
||||
marginLeft: -diameter / 2,
|
||||
left: touchStartX,
|
||||
top: touchStartY,
|
||||
})
|
||||
.each((_, wave) => {
|
||||
wave.style.setProperty('--mdui-comp-ripple-transition-x', translateX);
|
||||
wave.style.setProperty('--mdui-comp-ripple-transition-y', translateY);
|
||||
})
|
||||
.prependTo(this.surfaceRef.value)
|
||||
.each((_, wave) => wave.clientLeft) // 重绘
|
||||
.css('transform', translate)
|
||||
.on('animationend', function (e) {
|
||||
const event = e;
|
||||
if (event.animationName === 'mdui-comp-ripple-radius-in') {
|
||||
$(this).data('filled', true); // 扩散动画完成后,添加标记
|
||||
}
|
||||
});
|
||||
}
|
||||
endPress() {
|
||||
const $waves = $(this.surfaceRef.value)
|
||||
.children()
|
||||
.filter((_, wave) => !$(wave).data('removing'))
|
||||
.data('removing', true);
|
||||
const hideAndRemove = ($waves) => {
|
||||
$waves
|
||||
.addClass('out')
|
||||
.each((_, wave) => wave.clientLeft) // 重绘
|
||||
.on('animationend', function () {
|
||||
$(this).remove();
|
||||
});
|
||||
};
|
||||
// 扩散动画未完成,先完成扩散,再隐藏并移除
|
||||
$waves
|
||||
.filter((_, wave) => !$(wave).data('filled'))
|
||||
.on('animationend', function (e) {
|
||||
const event = e;
|
||||
if (event.animationName === 'mdui-comp-ripple-radius-in') {
|
||||
hideAndRemove($(this));
|
||||
}
|
||||
});
|
||||
// 扩散动画已完成,直接隐藏并移除
|
||||
hideAndRemove($waves.filter((_, wave) => !!$(wave).data('filled')));
|
||||
}
|
||||
startHover() {
|
||||
this.hover = true;
|
||||
}
|
||||
endHover() {
|
||||
this.hover = false;
|
||||
}
|
||||
startFocus() {
|
||||
this.focused = true;
|
||||
}
|
||||
endFocus() {
|
||||
this.focused = false;
|
||||
}
|
||||
startDrag() {
|
||||
this.dragged = true;
|
||||
}
|
||||
endDrag() {
|
||||
this.dragged = false;
|
||||
}
|
||||
render() {
|
||||
return html `<div ${ref(this.surfaceRef)} class="surface ${classMap({
|
||||
hover: this.hover,
|
||||
focused: this.focused,
|
||||
dragged: this.dragged,
|
||||
})}"></div>`;
|
||||
}
|
||||
};
|
||||
Ripple.styles = [componentStyle, style];
|
||||
__decorate([
|
||||
property({
|
||||
type: Boolean,
|
||||
reflect: true,
|
||||
converter: booleanConverter,
|
||||
attribute: 'no-ripple',
|
||||
})
|
||||
], Ripple.prototype, "noRipple", void 0);
|
||||
__decorate([
|
||||
state()
|
||||
], Ripple.prototype, "hover", void 0);
|
||||
__decorate([
|
||||
state()
|
||||
], Ripple.prototype, "focused", void 0);
|
||||
__decorate([
|
||||
state()
|
||||
], Ripple.prototype, "dragged", void 0);
|
||||
Ripple = __decorate([
|
||||
customElement('mdui-ripple')
|
||||
], Ripple);
|
||||
export { Ripple };
|
||||
Reference in New Issue
Block a user