gridloc / src /components /MapPreview.tsx
lassanmonster's picture
GridLoc: Bengaluru parking congestion digital twin
db3dbe1
Raw
History Blame Contribute Delete
3.44 kB
/**
* A simplified, mostly-static preview of the dark Bengaluru map used in the
* landing hero. Pure SVG - no map SDK, no network - so it renders instantly
* and stays calm. A few glowing hexagons hint at the live "risk zones".
*/
type Hex = {
cx: number
cy: number
r: number
color: string
delay: number
}
// Classification palette: calm graphite, check bronze, patrol amber-ember.
const HEXES: Array<Hex> = [
{ cx: 168, cy: 150, r: 26, color: '#D98E04', delay: 0 },
{ cx: 232, cy: 120, r: 20, color: '#8A6D3B', delay: 0.8 },
{ cx: 120, cy: 210, r: 18, color: '#2A2D34', delay: 1.6 },
{ cx: 250, cy: 205, r: 16, color: '#2A2D34', delay: 2.2 },
{ cx: 198, cy: 240, r: 14, color: '#8A6D3B', delay: 1.2 },
]
function hexPoints(cx: number, cy: number, r: number): string {
const pts: Array<string> = []
for (let i = 0; i < 6; i++) {
const a = (Math.PI / 180) * (60 * i - 30)
pts.push(`${cx + r * Math.cos(a)},${cy + r * Math.sin(a)}`)
}
return pts.join(' ')
}
// A few hand-drawn "road" polylines to suggest a road network.
const ROADS = [
'M40,90 L150,140 L210,120 L320,170',
'M70,260 L160,200 L240,230 L300,210',
'M120,40 L150,140 L140,220 L170,300',
'M250,50 L232,120 L250,205 L260,290',
'M30,170 L120,180 L210,160 L330,120',
]
export function MapPreview() {
return (
<div className="relative h-full w-full overflow-hidden rounded-xl border border-cyan/20 bg-[#0b1018] shadow-[0_0_40px_-12px_rgba(63,208,230,0.35)]">
{/* faint grid */}
<div className="tron-grid absolute inset-0 opacity-60" />
<svg
viewBox="0 0 360 320"
className="absolute inset-0 h-full w-full"
preserveAspectRatio="xMidYMid slice"
>
<defs>
{HEXES.map((h, i) => (
<radialGradient id={`glow-${i}`} key={i}>
<stop offset="0%" stopColor={h.color} stopOpacity="0.55" />
<stop offset="100%" stopColor={h.color} stopOpacity="0" />
</radialGradient>
))}
</defs>
{/* water blob */}
<path
d="M280,250 q30,-20 50,10 q10,30 -20,40 q-40,5 -40,-25 z"
fill="#10202a"
stroke="#1d3340"
strokeWidth="1"
/>
{/* roads */}
<g
fill="none"
stroke="#2a3850"
strokeWidth="1.5"
strokeLinecap="round"
>
{ROADS.map((d, i) => (
<path key={i} d={d} />
))}
</g>
{/* glow halos */}
{HEXES.map((h, i) => (
<circle
key={`halo-${i}`}
cx={h.cx}
cy={h.cy}
r={h.r * 2.2}
fill={`url(#glow-${i})`}
/>
))}
{/* hexagons */}
{HEXES.map((h, i) => (
<polygon
key={`hex-${i}`}
className="hex-pulse"
style={{ animationDelay: `${h.delay}s` }}
points={hexPoints(h.cx, h.cy, h.r)}
fill={h.color}
fillOpacity={0.22}
stroke={h.color}
strokeOpacity={0.9}
strokeWidth={1.5}
/>
))}
</svg>
{/* corner label */}
<div className="absolute bottom-3 left-3 font-mono text-[10px] uppercase tracking-widest text-cyan/70">
Bengaluru · live preview
</div>
<div className="pointer-events-none absolute inset-0 rounded-xl ring-1 ring-inset ring-cyan/10" />
</div>
)
}