| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- const defaultOptions = {
- size: 300,
- color1: 'rgba(128, 119, 255, 0.5)',
- color2: 'rgba(231, 76, 255, 0.5)',
- angle: 148,
- opacity: 0.5,
- blur: 50,
- duration: 0.15
- }
- const createGlowElement = (container, options) => {
- const glow = document.createElement('div')
- const gradient = `conic-gradient(from ${options.angle}deg, ${options.color1} 0%, ${options.color2} 50%, ${options.color1} 100%)`
- glow.style.cssText = `
- position: absolute;
- left: 0;
- top: 0;
- width: ${options.size}px;
- height: ${options.size}px;
- background: ${gradient};
- border-radius: 50%;
- pointer-events: none;
- opacity: 0;
- transition: opacity ${options.duration}s ease;
- will-change: transform;
- filter: blur(${options.blur}px) drop-shadow(0 4px 4px rgba(0,0,0,0.25));
- z-index: 1;
- `
- container.style.position = 'relative'
- container.style.overflow = 'hidden'
- container.appendChild(glow)
- return glow
- }
- const updateGlowPosition = (glow, x, y, options) => {
- glow.style.transform = `translate(${x - options.size / 2}px, ${y - options.size / 2}px)`
- }
- const mouseGlowDirective = {
- mounted(el, binding) {
- const options = { ...defaultOptions, ...binding.value }
- const glow = createGlowElement(el, options)
- let animationFrameId = null
- let isVisible = false
- const handleMouseMove = (e) => {
- if (animationFrameId !== null) {
- cancelAnimationFrame(animationFrameId)
- }
- animationFrameId = requestAnimationFrame(() => {
- const rect = el.getBoundingClientRect()
- const x = e.clientX - rect.left
- const y = e.clientY - rect.top
- updateGlowPosition(glow, x, y, options)
- animationFrameId = null
- })
- }
- const handleMouseEnter = () => {
- if (!isVisible) {
- glow.style.opacity = options.opacity?.toString() || defaultOptions.opacity.toString()
- isVisible = true
- }
- }
- const handleMouseLeave = () => {
- if (isVisible) {
- glow.style.opacity = '0'
- isVisible = false
- }
- }
- el.addEventListener('mousemove', handleMouseMove, { passive: true })
- el.addEventListener('mouseenter', handleMouseEnter, { passive: true })
- el.addEventListener('mouseleave', handleMouseLeave, { passive: true })
- el._mouseGlowDirective = {
- glow,
- handleMouseMove,
- handleMouseEnter,
- handleMouseLeave,
- animationFrameId: () => animationFrameId
- }
- },
- updated(el, binding) {
- const directiveData = el._mouseGlowDirective
- if (directiveData) {
- const options = { ...defaultOptions, ...binding.value }
- const { glow } = directiveData
- const gradient = `conic-gradient(from ${options.angle}deg, ${options.color1} 0%, ${options.color2} 50%, ${options.color1} 100%)`
- glow.style.width = `${options.size}px`
- glow.style.height = `${options.size}px`
- glow.style.background = gradient
- glow.style.filter = `blur(${options.blur}px) drop-shadow(0 4px 4px rgba(0,0,0,0.25))`
- glow.style.transition = `opacity ${options.duration}s ease`
- }
- },
- unmounted(el) {
- const directiveData = el._mouseGlowDirective
- if (directiveData) {
- const { glow, handleMouseMove, handleMouseEnter, handleMouseLeave, animationFrameId } = directiveData
- const frameId = animationFrameId()
- if (frameId !== null) {
- cancelAnimationFrame(frameId)
- }
- el.removeEventListener('mousemove', handleMouseMove)
- el.removeEventListener('mouseenter', handleMouseEnter)
- el.removeEventListener('mouseleave', handleMouseLeave)
- glow.remove()
- delete el._mouseGlowDirective
- }
- }
- }
- export default mouseGlowDirective
|