index.vue 2.56 KB
<script setup lang="ts">
import { nextTick, onMounted, ref } from 'vue'

// Import CSS Leaflet
import 'leaflet/dist/leaflet.css'

// Refs untuk elemen peta dan instance Leaflet
const mapContainer = ref<HTMLElement | null>(null)
let map = null

// Pusatkan peta ke Universitas Indonesia
const center = [-6.3668871, 106.8284798]
const zoom = 15
const tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'

// List Fakultas di UI
const faculties = [
  { name: 'Gedung Rektorat', coords: [-6.3668871, 106.8284798], description: 'Pusat administrasi utama Universitas Indonesia.' },
  { name: 'Gedung Balairung', coords: [-6.3680973, 106.829668], description: 'Gedung serbaguna yang sering digunakan untuk acara wisuda dan kegiatan akademik besar.' },
  { name: 'Gedung Balai Sidang', coords: [-6.369758, 106.8284664], description: 'Tempat penyelenggaraan seminar, konferensi, dan acara akademik lainnya di UI.' },
  { name: 'Masjid Ukhuwah Islamiyah (MUI)', coords: [-6.3658022, 106.8310627], description: 'Masjid utama Universitas Indonesia yang menjadi pusat kegiatan keagamaan.' },
  { name: 'Ruang Rapat Terapung', coords: [-6.365815, 106.830285], description: 'Ruang pertemuan unik di atas danau UI, sering digunakan untuk diskusi dan rapat penting.' },
]

// Inisialisasi peta saat komponen dipasang
onMounted(async () => {
  await nextTick()
  if (typeof window === 'undefined' || !mapContainer.value)
    return

  const L = await import('leaflet') // Import dynamically

  map = L.map(mapContainer.value).setView(center, zoom)

  L.tileLayer(tileUrl, {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 18,
    minZoom: 12,
    subdomains: ['a', 'b', 'c'],
  }).addTo(map)

  // Fix missing marker icons
  const markerIcon = new L.Icon({
    iconUrl: new URL('leaflet/dist/images/marker-icon.png', import.meta.url).href,
    shadowUrl: new URL('leaflet/dist/images/marker-shadow.png', import.meta.url).href,
    iconSize: [25, 41],
    iconAnchor: [12, 41],
    popupAnchor: [1, -34],
    shadowSize: [41, 41],
  })

  faculties.forEach(faculty => {
    L.marker(faculty.coords, { icon: markerIcon })
      .addTo(map)
      .bindPopup(`<h3>${faculty.name}</h3><p>${faculty.description}</p>`)
  })
})
</script>

<template>
  <ClientOnly>
    <div class="map-container">
      <div
        ref="mapContainer"
        class="map"
      />
    </div>
  </ClientOnly>
</template>

<style scoped>
.map-container {
  block-size: 500px;
  inline-size: 100%;
}

.map {
  block-size: 100%;
  inline-size: 100%;
  min-block-size: 400px;
}
</style>