Map Rain
terrae/rainFreeComponent
Animated rain effect layer.
Install it
npx shadcn@latest add https://www.terrae.dev/rain.jsonSource
1"use client"23import { useEffect, useRef } from "react"4import { useMap } from "./hooks"56type MapboxExpression = unknown[]78type MapRainProps = {9 density?: number | MapboxExpression10 intensity?: number11 color?: string12 opacity?: number13 vignette?: number | MapboxExpression14 vignetteColor?: string15 direction?: [number, number]16 dropletSize?: [number, number]17 distortionStrength?: number18 centerThinning?: number19}2021export const createZoomInterpolation = (22 value: number,23 minZoom: number = 11,24 maxZoom: number = 1325): MapboxExpression => {26 return ["interpolate", ["linear"], ["zoom"], minZoom, 0.0, maxZoom, value]27}2829const clampValue = (value: number, min: number, max: number): number => {30 return Math.min(Math.max(value, min), max)31}3233const applyRainEffect = (map: mapboxgl.Map, config: Record<string, unknown>): void => {34 ;(map as unknown as { setRain: (config: Record<string, unknown> | null) => void }).setRain(config)35}3637const removeRainEffect = (map: mapboxgl.Map): void => {38 ;(map as unknown as { setRain: (config: Record<string, unknown> | null) => void }).setRain(null)39}4041const hasRainSupport = (map: mapboxgl.Map): boolean => {42 return typeof (map as unknown as Record<string, unknown>).setRain === "function"43}4445const DEFAULT_DIRECTION: [number, number] = [0, 80]46const DEFAULT_DROPLET_SIZE: [number, number] = [2.6, 18.2]4748export const MapRain = ({49 density = 0.5,50 intensity = 1,51 color = "#a8adbc",52 opacity = 0.7,53 vignette = 1,54 vignetteColor = "#464646",55 direction = DEFAULT_DIRECTION,56 dropletSize = DEFAULT_DROPLET_SIZE,57 distortionStrength = 0.7,58 centerThinning = 0,59}: MapRainProps) => {60 const { map, isLoaded } = useMap()61 const initializedRef = useRef(false)6263 useEffect(() => {64 if (!isLoaded || !map || initializedRef.current) {65 return66 }6768 if (!hasRainSupport(map)) {69 console.warn("Rain effect requires Mapbox GL JS v3.9 or higher. This feature is not available in MapLibre GL.")70 return71 }7273 try {74 const clampedDensity = typeof density === "number" ? clampValue(density, 0, 1) : density75 const clampedVignette = typeof vignette === "number" ? clampValue(vignette, 0, 1) : vignette7677 applyRainEffect(map, {78 density: clampedDensity,79 intensity: clampValue(intensity, 0, 1),80 color,81 opacity: clampValue(opacity, 0, 1),82 vignette: clampedVignette,83 "vignette-color": vignetteColor,84 direction,85 "droplet-size": dropletSize,86// … 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 Animated Pulseanimated-pulse | 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 |
