mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 06:29:30 -07:00
1 line
2.8 KiB
JSON
1 line
2.8 KiB
JSON
{"name":"Magnet","title":"Magnet","description":"Elements magnetically ease toward the cursor then settle back with spring physics.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <div\n ref=\"magnetRef\"\n :class=\"wrapperClassName\"\n :style=\"{ position: 'relative', display: 'inline-block' }\"\n v-bind=\"$attrs\"\n >\n <div\n :class=\"innerClassName\"\n :style=\"{\n transform: `translate3d(${position.x}px, ${position.y}px, 0)`,\n transition: transitionStyle,\n willChange: 'transform'\n }\"\n >\n <slot />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted, watch, useTemplateRef } from 'vue';\n\ninterface Props {\n padding?: number;\n disabled?: boolean;\n magnetStrength?: number;\n activeTransition?: string;\n inactiveTransition?: string;\n wrapperClassName?: string;\n innerClassName?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n padding: 100,\n disabled: false,\n magnetStrength: 2,\n activeTransition: 'transform 0.3s ease-out',\n inactiveTransition: 'transform 0.5s ease-in-out',\n wrapperClassName: '',\n innerClassName: ''\n});\n\ndefineOptions({\n inheritAttrs: false\n});\n\nconst magnetRef = useTemplateRef<HTMLDivElement>('magnetRef');\nconst isActive = ref(false);\nconst position = ref({ x: 0, y: 0 });\n\nconst transitionStyle = computed(() => (isActive.value ? props.activeTransition : props.inactiveTransition));\n\nconst handleMouseMove = (e: MouseEvent) => {\n if (!magnetRef.value || props.disabled) return;\n\n const { left, top, width, height } = magnetRef.value.getBoundingClientRect();\n const centerX = left + width / 2;\n const centerY = top + height / 2;\n\n const distX = Math.abs(centerX - e.clientX);\n const distY = Math.abs(centerY - e.clientY);\n\n if (distX < width / 2 + props.padding && distY < height / 2 + props.padding) {\n isActive.value = true;\n const offsetX = (e.clientX - centerX) / props.magnetStrength;\n const offsetY = (e.clientY - centerY) / props.magnetStrength;\n position.value = { x: offsetX, y: offsetY };\n } else {\n isActive.value = false;\n position.value = { x: 0, y: 0 };\n }\n};\n\nonMounted(() => {\n window.addEventListener('mousemove', handleMouseMove);\n});\n\nonUnmounted(() => {\n window.removeEventListener('mousemove', handleMouseMove);\n});\n\nwatch(\n () => props.disabled,\n newDisabled => {\n if (newDisabled) {\n position.value = { x: 0, y: 0 };\n isActive.value = false;\n }\n }\n);\n</script>\n","path":"Magnet/Magnet.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["Animations"]} |