Map Circle
terrae/circleFreeComponent
Draggable geographic circle with customizable fill and stroke.
Install it
npx shadcn@latest add https://www.terrae.dev/circle.jsonSource
1"use client"23import type mapboxgl from "mapbox-gl"45import { useEffect, useId, useRef } from "react"6import { useMap } from "./hooks"7import type { MapCoordinates, MapPath } from "./types"89type MapCircleProps = {10 center: MapCoordinates11 radius: number12 fillColor?: string13 fillOpacity?: number14 strokeColor?: string15 strokeWidth?: number16 strokeOpacity?: number17 dashArray?: [number, number]18 segments?: number19 draggable?: boolean20 cursor?: string21 onDragStart?: (center: MapCoordinates) => void22 onDrag?: (center: MapCoordinates) => void23 onDragEnd?: (center: MapCoordinates) => void24}2526const DEFAULT_FILL_COLOR = "#3b82f6"27const DEFAULT_FILL_OPACITY = 028const DEFAULT_STROKE_COLOR = "#3b82f6"29const DEFAULT_STROKE_WIDTH = 230const DEFAULT_STROKE_OPACITY = 131const DEFAULT_SEGMENTS = 6432const EARTH_RADIUS_METERS = 6371008.83334const generateCircleCoordinates = (center: MapCoordinates, radiusMeters: number, segments: number): MapPath => {35 const [lng, lat] = center36 const coordinates: MapPath = []3738 const latRadians = (lat * Math.PI) / 18039 const lngRadians = (lng * Math.PI) / 18040 const angularDistance = radiusMeters / EARTH_RADIUS_METERS4142 for (let i = 0; i <= segments; i++) {43 const bearing = (2 * Math.PI * i) / segments4445 const pointLat = Math.asin(46 Math.sin(latRadians) * Math.cos(angularDistance) +47 Math.cos(latRadians) * Math.sin(angularDistance) * Math.cos(bearing)48 )4950 const pointLng =51 lngRadians +52 Math.atan2(53 Math.sin(bearing) * Math.sin(angularDistance) * Math.cos(latRadians),54 Math.cos(angularDistance) - Math.sin(latRadians) * Math.sin(pointLat)55 )5657 coordinates.push([(pointLng * 180) / Math.PI, (pointLat * 180) / Math.PI])58 }5960 return coordinates61}6263export const MapCircle = ({64 center,65 radius,66 fillColor = DEFAULT_FILL_COLOR,67 fillOpacity = DEFAULT_FILL_OPACITY,68 strokeColor = DEFAULT_STROKE_COLOR,69 strokeWidth = DEFAULT_STROKE_WIDTH,70 strokeOpacity = DEFAULT_STROKE_OPACITY,71 dashArray,72 segments = DEFAULT_SEGMENTS,73 draggable = false,74 cursor,75 onDragStart,76 onDrag,77 onDragEnd,78}: MapCircleProps) => {79 const { map, isLoaded } = useMap()80 const id = useId()81 const sourceId = `circle-source-${id}`82 const fillLayerId = `circle-fill-layer-${id}`83 const strokeLayerId = `circle-stroke-layer-${id}`84 const initializedRef = useRef(false)85 const isDraggingRef = useRef(false)8687 const centerRef = useRef(center)88 const radiusRef = useRef(radius)89// … 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 |
