Map Animated Pulse
terrae/animated-pulseFreeComponent
Pulsing dot animation for map markers.
Install it
npx shadcn@latest add https://www.terrae.dev/animated-pulse.jsonSource
1"use client"23import { useEffect, useRef } from "react"4import { useMap } from "./hooks"5import type { MapCoordinates } from "./types"67const DEFAULT_SIZE = 1008const DEFAULT_COLOR = "rgba(0, 100, 255, 1)"9const DEFAULT_PULSE_COLOR = "rgba(0, 100, 255, 0.8)"10const DEFAULT_DURATION = 10001112type MapAnimatedPulseProps = {13 id: string14 coordinates: MapCoordinates15 size?: number16 color?: string17 pulseColor?: string18 duration?: number19}2021type PulsingDot = {22 width: number23 height: number24 data: Uint8ClampedArray25 context?: CanvasRenderingContext2D26 onAdd: () => void27 render: () => boolean28}2930const createPulsingDot = (size: number, color: string, pulseColor: string, duration: number): PulsingDot => {31 const dot: PulsingDot = {32 width: size,33 height: size,34 data: new Uint8ClampedArray(size * size * 4),3536 onAdd() {37 const canvas = document.createElement("canvas")38 canvas.width = this.width39 canvas.height = this.height40 this.context = canvas.getContext("2d", { willReadFrequently: true }) || undefined41 },4243 render() {44 if (!this.context) {45 return false46 }4748 const t = (performance.now() % duration) / duration49 const radius = (size / 2) * 0.350 const outerRadius = (size / 2) * 0.7 * t + radius5152 this.context.clearRect(0, 0, this.width, this.height)5354 this.context.beginPath()55 this.context.arc(this.width / 2, this.height / 2, outerRadius, 0, Math.PI * 2)56 this.context.fillStyle = pulseColor57 this.context.globalAlpha = 1 - t58 this.context.fill()5960 this.context.beginPath()61 this.context.arc(this.width / 2, this.height / 2, radius, 0, Math.PI * 2)62 this.context.fillStyle = color63 this.context.globalAlpha = 164 this.context.fill()6566 this.data = this.context.getImageData(0, 0, this.width, this.height).data6768 return true69 },70 }7172 return dot73}7475export const MapAnimatedPulse = ({76 id,77 coordinates,78 size = DEFAULT_SIZE,79 color = DEFAULT_COLOR,80 pulseColor = DEFAULT_PULSE_COLOR,81 duration = DEFAULT_DURATION,82}: MapAnimatedPulseProps) => {83 const { map, isLoaded } = useMap()84 const animationFrameRef = useRef<number | null>(null)85 const sourceId = `${id}-source`86 const layerId = `${id}-layer`8788 useEffect(() => {89 if (!isLoaded || !map) {90 return91 }9293 const pulsingDot = createPulsingDot(size, color, pulseColor, duration)9495 const addImage = () => {96 if (!map.hasImage(id)) {97// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from terrae
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Map Animated Circleanimated-circle | terrae | Components | Free | 1 dep | |
| Map Animated Footprintanimated-footprint | terrae | Components | Free | 2 deps | |
| Map Animated Polygonanimated-polygon | terrae | Components | Free | 1 dep | |
| Map Arc Animatedarc-animated | terrae | Components | Free | 1 dep | |
| Map Blur Areablur-area | terrae | Components | Free | 1 dep | |
| Map Camera Followcamera-follow | terrae | Components | Free | 1 dep | |
| Map Choroplethchoropleth | terrae | Components | Free | 1 dep | |
| Map Circlecircle | terrae | Components | Free | 1 dep |
