mirror of
https://gitee.com/blackfox/geekai.git
synced 2025-12-07 01:08:24 +08:00
102 lines
2.1 KiB
Vue
102 lines
2.1 KiB
Vue
<template>
|
|
<button
|
|
class="ripple-button"
|
|
@mousedown="startRipples"
|
|
@mouseup="stopRipples"
|
|
@mouseleave="stopRipples"
|
|
>
|
|
<slot></slot>
|
|
<span
|
|
v-for="ripple in ripples"
|
|
:key="ripple.id"
|
|
class="ripple"
|
|
:style="getRippleStyle(ripple)"
|
|
></span>
|
|
</button>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue';
|
|
|
|
const ripples = ref([]);
|
|
let rippleCount = 0;
|
|
let animationId;
|
|
|
|
const startRipples = (event) => {
|
|
const button = event.currentTarget;
|
|
const rect = button.getBoundingClientRect();
|
|
const size = Math.max(rect.width, rect.height);
|
|
// const x = event.clientX - rect.left;
|
|
// const y = event.clientY - rect.top;
|
|
const x = rect.right - rect.left - size/2;
|
|
const y = rect.bottom - rect.top - size/2;
|
|
|
|
const createRipple = () => {
|
|
ripples.value.push({
|
|
id: rippleCount++,
|
|
x,
|
|
y,
|
|
size: 0,
|
|
opacity: 0.5
|
|
});
|
|
|
|
if (ripples.value.length > 3) {
|
|
ripples.value.shift();
|
|
}
|
|
};
|
|
|
|
const animate = () => {
|
|
ripples.value.forEach(ripple => {
|
|
ripple.size += 2;
|
|
ripple.opacity -= 0.01;
|
|
});
|
|
|
|
ripples.value = ripples.value.filter(ripple => ripple.opacity > 0);
|
|
|
|
if (ripples.value.length < 3) {
|
|
createRipple();
|
|
}
|
|
|
|
animationId = requestAnimationFrame(animate);
|
|
};
|
|
|
|
createRipple();
|
|
animate();
|
|
};
|
|
|
|
const stopRipples = () => {
|
|
cancelAnimationFrame(animationId);
|
|
ripples.value = [];
|
|
};
|
|
|
|
const getRippleStyle = (ripple) => ({
|
|
left: `${ripple.x}px`,
|
|
top: `${ripple.y}px`,
|
|
width: `${ripple.size}px`,
|
|
height: `${ripple.size}px`,
|
|
opacity: ripple.opacity
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="stylus">
|
|
.ripple-button {
|
|
position: relative;
|
|
overflow: hidden;
|
|
border: none;
|
|
background none;
|
|
color: white;
|
|
cursor: pointer;
|
|
border-radius: 50%;
|
|
outline: none;
|
|
margin 0
|
|
padding 0
|
|
}
|
|
|
|
.ripple {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
background-color: rgba(255, 255, 255, 0.7);
|
|
transform: translate(-50%, -50%);
|
|
pointer-events: none;
|
|
}
|
|
</style> |