Skip to content

Commit

Permalink
feat(ripple): add ripple component
Browse files Browse the repository at this point in the history
  • Loading branch information
lingbopro committed Dec 8, 2024
1 parent fe4ba69 commit 87889b7
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 0 deletions.
1 change: 1 addition & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default {
// component names
// add component name here when adding new component
'page',
'ripple',
],
],
},
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './page';
export * from './ripple';
1 change: 1 addition & 0 deletions src/components/ripple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ripple/ripple';
33 changes: 33 additions & 0 deletions src/components/ripple/ripple.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
:host {
display: inline-block;
position: relative;
--mm-ripple-color: currentColor;
}
.container,
.container::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: hidden;
}
.container::before {
content: '';
background-color: var(--mm-ripple-color);
opacity: 0;
transition: opacity 0.1s ease-in-out;
}
.container.hover::before {
opacity: 0.2;
}
.ripple {
position: absolute;
opacity: 0.24;
border-radius: 50%;
background-color: var(--mm-ripple-color);
}
.ripple-template {
display: none;
}
4 changes: 4 additions & 0 deletions src/components/ripple/ripple.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<slot></slot>
<div class="container">
<div class="ripple-template"></div>
</div>
106 changes: 106 additions & 0 deletions src/components/ripple/ripple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { useElement } from '../../core/element';
import template from './ripple.html';
import style from './ripple.css';

const name = 'mm-ripple';
const props = {};

export class Ripple extends useElement({
template,
style,
props,
setup(shadowRoot) {
const containerEl = shadowRoot.querySelector('.container') as HTMLDivElement;
const rippleTemplateEl = shadowRoot.querySelector('.ripple-template') as HTMLDivElement;

// 获取文字颜色
const computedTextColor = getComputedStyle(this).color;
const textColor = computedTextColor.replace(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/g, '$1, $2, $3');
containerEl.style.setProperty('--mm-internal-text-color', textColor);

/** 波纹点击开始 */
const rippleTouchStart = (event: MouseEvent, node?: HTMLElement) => {
if (!node) {
node = this;
}
// 计算位置
const { offsetWidth, offsetHeight } = node;
const { left, top } = node.getBoundingClientRect();
const { clientX, clientY } = event;
const realX = clientX - left;
const realY = clientY - top;
const halfHeight = offsetHeight / 2;
const halfWidth = offsetWidth / 2;
const edgeW = (Math.abs(halfHeight - realY) + halfHeight) * 2;
const edgeH = (Math.abs(halfWidth - realX) + halfWidth) * 2;
const size = Math.sqrt(edgeW * edgeW + edgeH * edgeH);

// 添加元素
const rippleEl = rippleTemplateEl.cloneNode() as HTMLDivElement;
rippleEl.classList.replace('ripple-template', 'ripple');
containerEl.appendChild(rippleEl);
// 动画关键帧
const standardKeyframesProp = {
opacity: 0.24,
width: `${size}px`,
height: `${size}px`,
left: `${realX}px`,
top: `${realY}px`,
};
const keyframes = [
{
...standardKeyframesProp,
transform: `translate(-50%, -50%) scale(0)`,
},
{
...standardKeyframesProp,
transform: `translate(-50%, -50%) scale(1)`,
},
];
// 应用动画
const animation = rippleEl.animate(keyframes, {
duration: 800,
fill: 'forwards',
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
});

// 点击结束处理方法
const touchEnd = () => {
// 淡出动画
const fadeOutAnimation = rippleEl.animate([{ opacity: 0.24 }, { opacity: 0 }], {
duration: 400,
fill: 'forwards',
});
// 移除元素
fadeOutAnimation.addEventListener('finish', () => {
rippleEl.remove();
});
};
return { rippleEl, touchEnd };
};

// 鼠标悬停处理函数
const onMouseOver = () => {
containerEl.classList.add('hover');
};
const onMouseLeave = () => {
containerEl.classList.remove('hover');
};
// 点击开始事件
const onPointerDown = (event: MouseEvent) => {
const { touchEnd } = rippleTouchStart(event);
document.addEventListener('pointerup', touchEnd, { once: true });
};

/** 添加监听器 */
const addListeners = (node: HTMLElement) => {
node.addEventListener('mouseover', onMouseOver);
node.addEventListener('mouseleave', onMouseLeave);
node.addEventListener('pointerdown', onPointerDown);
};
addListeners(this);
return {};
},
}) {}

Ripple.define(name);

0 comments on commit 87889b7

Please sign in to comment.