触摸涟漪效果是现代UI设计中常见的交互反馈,可以通过JavaScript和CSS实现。下面我将介绍几种实现方法。
<button class="ripple-button">点击我</button>
<style>
.ripple-button {
position: relative;
overflow: hidden;
padding: 12px 24px;
border: none;
background-color: #6200ee;
color: white;
cursor: pointer;
border-radius: 4px;
}
.ripple-button:after {
content: "";
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
background-image: radial-gradient(circle, #fff 10%, transparent 10.01%);
background-repeat: no-repeat;
background-position: 50%;
transform: scale(10, 10);
opacity: 0;
transition: transform .5s, opacity 1s;
}
.ripple-button:active:after {
transform: scale(0, 0);
opacity: .3;
transition: 0s;
}
</style>
限制:这种方法只能在按钮激活时显示效果,无法精确定位触摸点。
<button class="ripple-btn">点击我</button>
<style>
.ripple-btn {
position: relative;
overflow: hidden;
padding: 12px 24px;
border: none;
background-color: #6200ee;
color: white;
cursor: pointer;
border-radius: 4px;
}
.ripple {
position: absolute;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.7);
transform: scale(0);
animation: ripple 600ms linear;
pointer-events: none;
}
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
</style>
<script>
document.querySelectorAll('.ripple-btn').forEach(button => {
button.addEventListener('click', function(e) {
// 获取点击位置相对于按钮的位置
const rect = button.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 创建涟漪元素
const ripple = document.createElement('span');
ripple.classList.add('ripple');
ripple.style.left = `${x}px`;
ripple.style.top = `${y}px`;
// 添加到按钮中
this.appendChild(ripple);
// 动画结束后移除元素
setTimeout(() => {
ripple.remove();
}, 600);
});
});
</script>
<button class="ripple-btn-advanced">高级涟漪效果</button>
<style>
.ripple-btn-advanced {
position: relative;
overflow: hidden;
padding: 12px 24px;
border: none;
background-color: #6200ee;
color: white;
cursor: pointer;
border-radius: 4px;
--ripple-x: 0;
--ripple-y: 0;
}
.ripple-btn-advanced::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(
circle at var(--ripple-x) var(--ripple-y),
rgba(255, 255, 255, 0.8) 0%,
rgba(255, 255, 255, 0) 70%
);
transform: scale(0);
opacity: 0;
pointer-events: none;
}
.ripple-btn-advanced.animate::after {
animation: ripple-animation 0.6s ease-out;
}
@keyframes ripple-animation {
0% {
transform: scale(0);
opacity: 1;
}
100% {
transform: scale(1);
opacity: 0;
}
}
</style>
<script>
document.querySelectorAll('.ripple-btn-advanced').forEach(button => {
button.addEventListener('click', function(e) {
const rect = button.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 设置CSS变量
this.style.setProperty('--ripple-x', `${x}px`);
this.style.setProperty('--ripple-y', `${y}px`);
// 添加动画类
this.classList.add('animate');
// 动画结束后移除类
setTimeout(() => {
this.classList.remove('animate');
}, 600);
});
});
</script>
class RippleEffect {
constructor(element, options = {}) {
this.element = element;
this.options = {
color: 'rgba(255, 255, 255, 0.7)',
duration: 600,
...options
};
this.init();
}
init() {
this.element.style.position = 'relative';
this.element.style.overflow = 'hidden';
this.element.addEventListener('click', this.createRipple.bind(this));
}
createRipple(e) {
const rect = this.element.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const diameter = Math.max(rect.width, rect.height);
const ripple = document.createElement('span');
ripple.style.position = 'absolute';
ripple.style.width = ripple.style.height = `${diameter}px`;
ripple.style.left = `${x - diameter / 2}px`;
ripple.style.top = `${y - diameter / 2}px`;
ripple.style.borderRadius = '50%';
ripple.style.backgroundColor = this.options.color;
ripple.style.transform = 'scale(0)';
ripple.style.transition = `transform ${this.options.duration}ms ease-out, opacity ${this.options.duration}ms ease-out`;
ripple.style.pointerEvents = 'none';
this.element.appendChild(ripple);
setTimeout(() => {
ripple.style.transform = 'scale(2)';
ripple.style.opacity = '0';
}, 10);
setTimeout(() => {
ripple.remove();
}, this.options.duration);
}
}
// 使用示例
document.querySelectorAll('[data-ripple]').forEach(el => {
new RippleEffect(el, {
color: 'rgba(255, 255, 255, 0.5)',
duration: 800
});
});
click
和touch
事件以上方法可以根据项目需求选择使用,方法二和方法三是最常用的实现方式。