"use client"; import { motion, useScroll, useTransform, useInView } from "framer-motion"; import { useRef, useState } from "react"; import Image from "next/image"; import { SectionHeader } from "@/components/shared/SectionHeader"; /* * Coordinates are percentages (0–100) relative to the map image (2720×1568). * Each point was placed by identifying the geographic feature on the * istanbul_map.png silhouette: * * Karaköy — European shore just south of the Golden Horn mouth * Moda İskelesi — tip of the Kadıköy/Moda peninsula (Asian side) * Moda (coffee) — slightly inland on the Moda neighbourhood streets * Fenerbahçe — the prominent cape/park jutting south into the Marmara * Caddebostan — along the Asian Marmara coast, east of Fenerbahçe * Bağdat Caddesi— runs parallel to the coast, slightly inland * Suadiye — further east along the Marmara coast */ const waypoints = [ { id: "karakoy", name: "Karaköy Ferry Terminal", description: "Your journey begins here. Board the ferry with Turkish tea in hand.", icon: "🚢", x: 27, y: 34, side: "europe", }, { id: "moda", name: "Moda İskelesi", description: "Step onto a 1917 pier that now houses a library and café over the sea.", icon: "📚", x: 42, y: 56, side: "asia", }, { id: "coffee", name: "Moda Coffee District", description: "Third-wave coffee tasting in Istanbul's coolest neighbourhood.", icon: "☕", x: 48, y: 53, side: "asia", }, { id: "fenerbahce", name: "Fenerbahçe Park", description: "Mediterranean-style marina with yachts, pine trees, and sea air.", icon: "🌳", x: 44, y: 67, side: "asia", }, { id: "caddebostan", name: "Caddebostan Seafront", description: "The promenade where Istanbulites gather at sunset. Street food heaven.", icon: "🌅", x: 53, y: 78, side: "asia", }, { id: "bagdat", name: "Bağdat Caddesi", description: "Istanbul's Champs-Élysées. 6km of designer boutiques and patisseries.", icon: "🛍️", x: 64, y: 60, side: "asia", }, { id: "suadiye", name: "Suadiye", description: "Sunset dinner with the European skyline painted in gold. The grand finale.", icon: "🍷", x: 63, y: 86, side: "asia", }, ]; /* ------------------------------------------------------------------ */ /* SVG path that connects the waypoints via a smooth Bézier curve. */ /* The path crosses the Bosphorus water from Karaköy to Moda, then */ /* follows the Asian coastline south-east to Suadiye. */ /* ------------------------------------------------------------------ */ const ROUTE_PATH = [ "M 27 34", // Karaköy "C 32 42, 38 52, 42 56", // ferry crossing → Moda İskelesi "C 44 55, 46 54, 48 53", // walk to Moda coffee district "C 47 57, 45 63, 44 67", // south to Fenerbahçe "C 46 72, 50 76, 53 78", // east to Caddebostan "C 57 76, 62 66, 64 60", // inland to Bağdat Caddesi "C 64 68, 63 78, 63 86", // back to coast at Suadiye ].join(" "); function WaypointPin({ waypoint, index, isActive, onClick, }: { waypoint: (typeof waypoints)[0]; index: number; isActive: boolean; onClick: () => void; }) { const ref = useRef(null); const isInView = useInView(ref, { once: true }); return ( {/* Pulse ring behind pin */} {/* Pin circle */} {waypoint.icon} {/* Step number label */} {index + 1} ); } export function InteractiveMap() { const sectionRef = useRef(null); const [activeWaypoint, setActiveWaypoint] = useState(null); const { scrollYProgress } = useScroll({ target: sectionRef, offset: ["start end", "end start"], }); const pathLength = useTransform(scrollYProgress, [0.15, 0.55], [0, 1]); return ( {/* ---- Map Container ---- */} setActiveWaypoint(null)} > {/* Map background image — the container inherits the image's intrinsic aspect ratio so pins stay aligned at every size. */} {/* Animated route path overlay */} {/* Shadow/glow underneath */} {/* Main dashed route line */} {/* Waypoint pins */} {waypoints.map((wp, i) => ( { setActiveWaypoint(activeWaypoint === wp.id ? null : wp.id); }} /> ))} {/* Side labels */} Europe Asia {/* Mobile: scrollable stop list below the map */} {waypoints.map((wp, i) => ( setActiveWaypoint(activeWaypoint === wp.id ? null : wp.id) } > {i + 1} {wp.icon} {wp.name} {wp.description} ))} ); }
{wp.name}
{wp.description}