869 lines
38 KiB
HTML
869 lines
38 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>WebGIS Pontianak — Portfolio Proyek</title>
|
|
<meta name="description" content="Kumpulan proyek WebGIS Kota Pontianak — Kepadatan Penduduk, SPBU, dan Distribusi Bantuan Sosial.">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
<style>
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
:root {
|
|
--bg-primary: #f8fafc;
|
|
--bg-card: #ffffff;
|
|
--bg-card-hover: #ffffff;
|
|
--border: #e2e8f0;
|
|
--border-hover: #cbd5e1;
|
|
--text: #0f172a;
|
|
--text-muted: #475569;
|
|
--text-dim: #64748b;
|
|
--accent-1: #0891b2;
|
|
--accent-2: #7c3aed;
|
|
--accent-3: #d97706;
|
|
--accent-4: #059669;
|
|
--font: 'Inter', -apple-system, system-ui, sans-serif;
|
|
--mono: 'DM Mono', monospace;
|
|
}
|
|
|
|
html { scroll-behavior: smooth; }
|
|
|
|
body {
|
|
font-family: var(--font);
|
|
background: var(--bg-primary);
|
|
color: var(--text);
|
|
min-height: 100vh;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
/* =========================================
|
|
AMBIENT BACKGROUND
|
|
========================================= */
|
|
.bg-ambient {
|
|
position: fixed; inset: 0; z-index: 0; pointer-events: none;
|
|
overflow: hidden;
|
|
}
|
|
.bg-orb {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
filter: blur(120px);
|
|
opacity: 0.08;
|
|
animation: orbFloat 20s ease-in-out infinite;
|
|
}
|
|
.bg-orb:nth-child(1) {
|
|
width: 600px; height: 600px;
|
|
background: var(--accent-1);
|
|
top: -10%; left: -10%;
|
|
animation-delay: 0s;
|
|
}
|
|
.bg-orb:nth-child(2) {
|
|
width: 500px; height: 500px;
|
|
background: var(--accent-2);
|
|
bottom: -10%; right: -5%;
|
|
animation-delay: -7s;
|
|
}
|
|
.bg-orb:nth-child(3) {
|
|
width: 400px; height: 400px;
|
|
background: var(--accent-3);
|
|
top: 40%; left: 50%;
|
|
animation-delay: -14s;
|
|
}
|
|
@keyframes orbFloat {
|
|
0%, 100% { transform: translate(0, 0) scale(1); }
|
|
33% { transform: translate(30px, -40px) scale(1.05); }
|
|
66% { transform: translate(-20px, 30px) scale(0.95); }
|
|
}
|
|
|
|
/* Grid pattern overlay */
|
|
.bg-grid {
|
|
position: fixed; inset: 0; z-index: 0; pointer-events: none;
|
|
background-image:
|
|
linear-gradient(rgba(15, 23, 42, 0.03) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(15, 23, 42, 0.03) 1px, transparent 1px);
|
|
background-size: 60px 60px;
|
|
}
|
|
|
|
/* =========================================
|
|
NAVBAR
|
|
========================================= */
|
|
.navbar {
|
|
position: fixed; top: 0; left: 0; right: 0;
|
|
z-index: 100;
|
|
padding: 16px 40px;
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
background: rgba(248, 250, 252, 0.8);
|
|
backdrop-filter: blur(20px) saturate(1.4);
|
|
border-bottom: 1px solid var(--border);
|
|
transition: all 0.3s;
|
|
}
|
|
.navbar.scrolled {
|
|
padding: 12px 40px;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
box-shadow: 0 4px 20px rgba(15, 23, 42, 0.03);
|
|
}
|
|
.nav-brand {
|
|
display: flex; align-items: center; gap: 12px;
|
|
}
|
|
.nav-logo {
|
|
width: 36px; height: 36px;
|
|
background: linear-gradient(135deg, var(--accent-1), var(--accent-2));
|
|
border-radius: 10px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 18px;
|
|
box-shadow: 0 4px 20px rgba(6, 182, 212, 0.3);
|
|
}
|
|
.nav-title {
|
|
font-size: 16px; font-weight: 700;
|
|
letter-spacing: -0.3px;
|
|
}
|
|
.nav-title span {
|
|
background: linear-gradient(135deg, var(--accent-1), var(--accent-2));
|
|
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
.nav-links {
|
|
display: flex; gap: 8px;
|
|
}
|
|
.nav-link {
|
|
padding: 8px 16px;
|
|
font-size: 13px; font-weight: 500;
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
border-radius: 8px;
|
|
transition: all 0.2s;
|
|
}
|
|
.nav-link:hover {
|
|
color: var(--text);
|
|
background: rgba(15, 23, 42, 0.05);
|
|
}
|
|
|
|
/* =========================================
|
|
HERO SECTION
|
|
========================================= */
|
|
.hero {
|
|
position: relative; z-index: 1;
|
|
display: flex; flex-direction: column;
|
|
align-items: center; justify-content: center;
|
|
text-align: center;
|
|
padding: 160px 40px 80px;
|
|
min-height: 70vh;
|
|
}
|
|
.hero-badge {
|
|
display: inline-flex; align-items: center; gap: 8px;
|
|
padding: 6px 16px 6px 8px;
|
|
background: rgba(139, 92, 246, 0.12);
|
|
border: 1px solid rgba(139, 92, 246, 0.2);
|
|
border-radius: 100px;
|
|
font-size: 12px; font-weight: 600; color: var(--accent-2);
|
|
margin-bottom: 24px;
|
|
animation: fadeInUp 0.6s ease;
|
|
}
|
|
.hero-badge-dot {
|
|
width: 8px; height: 8px;
|
|
background: var(--accent-2);
|
|
border-radius: 50%;
|
|
animation: pulse 2s ease-in-out infinite;
|
|
}
|
|
@keyframes pulse {
|
|
0%,100% { opacity: 1; transform: scale(1); }
|
|
50% { opacity: 0.5; transform: scale(1.3); }
|
|
}
|
|
|
|
.hero h1 {
|
|
font-size: clamp(36px, 6vw, 64px);
|
|
font-weight: 800;
|
|
line-height: 1.1;
|
|
letter-spacing: -1.5px;
|
|
margin-bottom: 20px;
|
|
animation: fadeInUp 0.6s ease 0.1s both;
|
|
}
|
|
.hero h1 .gradient-text {
|
|
background: linear-gradient(135deg, var(--accent-1) 0%, var(--accent-2) 50%, var(--accent-3) 100%);
|
|
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
.hero-desc {
|
|
font-size: 17px; color: var(--text-muted);
|
|
max-width: 560px; line-height: 1.7;
|
|
margin-bottom: 36px;
|
|
animation: fadeInUp 0.6s ease 0.2s both;
|
|
}
|
|
.hero-stats {
|
|
display: flex; gap: 40px;
|
|
animation: fadeInUp 0.6s ease 0.3s both;
|
|
}
|
|
.hero-stat {
|
|
text-align: center;
|
|
}
|
|
.hero-stat-num {
|
|
font-size: 28px; font-weight: 800;
|
|
font-family: var(--mono);
|
|
background: linear-gradient(135deg, var(--accent-1), var(--accent-4));
|
|
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
.hero-stat-label {
|
|
font-size: 11px; font-weight: 600;
|
|
color: var(--text-dim);
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
@keyframes fadeInUp {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
/* =========================================
|
|
PROJECTS SECTION
|
|
========================================= */
|
|
.projects {
|
|
position: relative; z-index: 1;
|
|
padding: 40px 40px 100px;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
.section-label {
|
|
display: flex; align-items: center; gap: 10px;
|
|
font-size: 11px; font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 2px;
|
|
color: var(--accent-1);
|
|
margin-bottom: 12px;
|
|
}
|
|
.section-label::before {
|
|
content: '';
|
|
width: 24px; height: 2px;
|
|
background: var(--accent-1);
|
|
border-radius: 2px;
|
|
}
|
|
.section-title {
|
|
font-size: 32px; font-weight: 800;
|
|
letter-spacing: -0.8px;
|
|
margin-bottom: 48px;
|
|
}
|
|
|
|
.project-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
|
|
gap: 24px;
|
|
}
|
|
|
|
/* =========================================
|
|
PROJECT CARD
|
|
========================================= */
|
|
.project-card {
|
|
position: relative;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 20px;
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
|
text-decoration: none;
|
|
color: inherit;
|
|
display: flex; flex-direction: column;
|
|
box-shadow: 0 4px 20px rgba(15, 23, 42, 0.02);
|
|
}
|
|
.project-card:hover {
|
|
transform: translateY(-6px);
|
|
background: var(--bg-card-hover);
|
|
border-color: var(--border-hover);
|
|
box-shadow:
|
|
0 20px 45px rgba(15, 23, 42, 0.06),
|
|
0 0 0 1px rgba(15, 23, 42, 0.03);
|
|
}
|
|
.project-card:hover .card-icon-glow {
|
|
opacity: 0.25;
|
|
}
|
|
.project-card:hover .card-arrow {
|
|
transform: translate(3px, -3px);
|
|
opacity: 1;
|
|
}
|
|
.project-card:hover .card-preview {
|
|
transform: scale(1.03);
|
|
}
|
|
|
|
/* Card top: preview area */
|
|
.card-preview-wrap {
|
|
position: relative;
|
|
height: 200px;
|
|
overflow: hidden;
|
|
background: linear-gradient(135deg, rgba(15, 23, 42, 0.02), rgba(15, 23, 42, 0.04));
|
|
}
|
|
.card-preview {
|
|
width: 100%; height: 100%;
|
|
display: flex; align-items: center; justify-content: center;
|
|
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
.card-icon-glow {
|
|
position: absolute;
|
|
width: 200px; height: 200px;
|
|
border-radius: 50%;
|
|
filter: blur(60px);
|
|
opacity: 0.12;
|
|
transition: opacity 0.4s;
|
|
top: 50%; left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
/* SVG icons */
|
|
.card-icon-svg {
|
|
position: relative; z-index: 1;
|
|
width: 100px; height: 100px;
|
|
}
|
|
|
|
/* Card number badge */
|
|
.card-number {
|
|
position: absolute; top: 16px; left: 16px;
|
|
font-family: var(--mono);
|
|
font-size: 11px; font-weight: 600;
|
|
color: var(--text-dim);
|
|
padding: 4px 10px;
|
|
background: rgba(15, 23, 42, 0.04);
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
}
|
|
|
|
/* Card arrow */
|
|
.card-arrow {
|
|
position: absolute; top: 16px; right: 16px;
|
|
width: 32px; height: 32px;
|
|
background: rgba(15, 23, 42, 0.04);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
opacity: 0.5;
|
|
transition: all 0.3s;
|
|
}
|
|
.card-arrow svg {
|
|
width: 14px; height: 14px;
|
|
stroke: var(--text-muted);
|
|
fill: none;
|
|
stroke-width: 2;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
}
|
|
|
|
/* Card body */
|
|
.card-body {
|
|
padding: 24px 24px 28px;
|
|
flex: 1;
|
|
display: flex; flex-direction: column;
|
|
}
|
|
.card-tag {
|
|
display: inline-flex;
|
|
align-self: flex-start;
|
|
padding: 3px 10px;
|
|
font-size: 10px; font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.8px;
|
|
border-radius: 6px;
|
|
margin-bottom: 12px;
|
|
}
|
|
.card-tag.choropleth {
|
|
background: rgba(245, 158, 11, 0.12);
|
|
color: var(--accent-3);
|
|
border: 1px solid rgba(245, 158, 11, 0.2);
|
|
}
|
|
.card-tag.crud {
|
|
background: rgba(6, 182, 212, 0.12);
|
|
color: var(--accent-1);
|
|
border: 1px solid rgba(6, 182, 212, 0.2);
|
|
}
|
|
.card-tag.fullstack {
|
|
background: rgba(16, 185, 129, 0.12);
|
|
color: var(--accent-4);
|
|
border: 1px solid rgba(16, 185, 129, 0.2);
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 20px; font-weight: 700;
|
|
letter-spacing: -0.3px;
|
|
margin-bottom: 8px;
|
|
line-height: 1.3;
|
|
}
|
|
.card-desc {
|
|
font-size: 13px; color: var(--text-muted);
|
|
line-height: 1.7;
|
|
flex: 1;
|
|
}
|
|
|
|
/* Card tech tags */
|
|
.card-techs {
|
|
display: flex; flex-wrap: wrap; gap: 6px;
|
|
margin-top: 16px; padding-top: 16px;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
.card-tech {
|
|
padding: 3px 8px;
|
|
font-size: 10px; font-weight: 600;
|
|
color: var(--text-muted);
|
|
background: rgba(15, 23, 42, 0.03);
|
|
border: 1px solid var(--border);
|
|
border-radius: 5px;
|
|
font-family: var(--mono);
|
|
}
|
|
|
|
/* =========================================
|
|
FOOTER
|
|
========================================= */
|
|
.footer {
|
|
position: relative; z-index: 1;
|
|
text-align: center;
|
|
padding: 40px;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
.footer-text {
|
|
font-size: 12px; color: var(--text-dim);
|
|
}
|
|
.footer-text a {
|
|
color: var(--accent-1);
|
|
text-decoration: none;
|
|
}
|
|
|
|
/* =========================================
|
|
RESPONSIVE
|
|
========================================= */
|
|
@media (max-width: 768px) {
|
|
.navbar { padding: 12px 20px; }
|
|
.nav-links { display: none; }
|
|
.hero { padding: 120px 20px 60px; }
|
|
.hero-stats { gap: 24px; }
|
|
.projects { padding: 20px 20px 60px; }
|
|
.project-grid { grid-template-columns: 1fr; }
|
|
.card-preview-wrap { height: 160px; }
|
|
}
|
|
|
|
/* =========================================
|
|
SCROLL ANIMATIONS
|
|
========================================= */
|
|
.reveal {
|
|
opacity: 0;
|
|
transform: translateY(30px);
|
|
transition: all 0.7s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
.reveal.visible {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Ambient Background -->
|
|
<div class="bg-ambient">
|
|
<div class="bg-orb"></div>
|
|
<div class="bg-orb"></div>
|
|
<div class="bg-orb"></div>
|
|
</div>
|
|
<div class="bg-grid"></div>
|
|
|
|
<!-- Navbar -->
|
|
<nav class="navbar" id="navbar">
|
|
<div class="nav-brand">
|
|
<div class="nav-logo">🌍</div>
|
|
<div class="nav-title"><span>WebGIS</span> Pontianak</div>
|
|
</div>
|
|
<div class="nav-links">
|
|
<a href="#projects" class="nav-link">Proyek</a>
|
|
<a href="https://github.com" class="nav-link" target="_blank">GitHub</a>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Hero -->
|
|
<section class="hero">
|
|
<div class="hero-badge">
|
|
<div class="hero-badge-dot"></div>
|
|
Sistem Informasi Geografis Berbasis Web
|
|
</div>
|
|
<h1>
|
|
Eksplorasi <span class="gradient-text">WebGIS</span><br>
|
|
Kota Pontianak
|
|
</h1>
|
|
<p class="hero-desc">
|
|
Kumpulan proyek WebGIS interaktif yang mencakup analisis kepadatan penduduk,
|
|
pemetaan SPBU, hingga distribusi bantuan sosial berbasis peta digital.
|
|
</p>
|
|
<div class="hero-stats">
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">3</div>
|
|
<div class="hero-stat-label">Proyek</div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">Leaflet</div>
|
|
<div class="hero-stat-label">Map Engine</div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">PHP</div>
|
|
<div class="hero-stat-label">Backend</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Projects -->
|
|
<section class="projects" id="projects">
|
|
<div class="section-label">Portfolio</div>
|
|
<h2 class="section-title">Proyek yang Telah Dibuat</h2>
|
|
|
|
<div class="project-grid">
|
|
|
|
<!-- Card 1: WebGIS SPBU -->
|
|
<a href="http://localhost/webgis/03/index.html" class="project-card reveal" id="card-03">
|
|
<div class="card-preview-wrap">
|
|
<div class="card-icon-glow" style="background: var(--accent-1);"></div>
|
|
<div class="card-number">03</div>
|
|
<div class="card-arrow">
|
|
<svg viewBox="0 0 24 24"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg>
|
|
</div>
|
|
<div class="card-preview">
|
|
<!-- SPBU / Gas Station Icon -->
|
|
<svg class="card-icon-svg" viewBox="0 0 120 120" fill="none">
|
|
<!-- Gas pump body -->
|
|
<rect x="25" y="35" width="40" height="55" rx="6" fill="#06b6d4" opacity="0.8"/>
|
|
<rect x="30" y="42" width="30" height="20" rx="3" fill="#0e7490" opacity="0.6"/>
|
|
<!-- Display -->
|
|
<rect x="33" y="45" width="24" height="14" rx="2" fill="#164e63"/>
|
|
<text x="38" y="55" font-family="monospace" font-size="8" fill="#22d3ee">24H</text>
|
|
<!-- Nozzle -->
|
|
<path d="M65 45 L75 40 L78 50 L80 75" stroke="#06b6d4" stroke-width="3" fill="none" stroke-linecap="round"/>
|
|
<circle cx="80" cy="78" r="4" fill="#06b6d4" opacity="0.7"/>
|
|
<!-- Base -->
|
|
<rect x="20" y="88" width="50" height="6" rx="3" fill="#06b6d4" opacity="0.3"/>
|
|
<!-- Map pin markers -->
|
|
<circle cx="95" cy="35" r="6" fill="#10b981" opacity="0.8"/>
|
|
<circle cx="95" cy="35" r="2.5" fill="white"/>
|
|
<circle cx="100" cy="55" r="5" fill="#ef4444" opacity="0.8"/>
|
|
<circle cx="100" cy="55" r="2" fill="white"/>
|
|
<!-- Lines / roads -->
|
|
<path d="M85 45 L105 45" stroke="#334155" stroke-width="2" stroke-dasharray="4 3" opacity="0.4"/>
|
|
<path d="M88 65 L108 65" stroke="#334155" stroke-width="2" stroke-dasharray="4 3" opacity="0.4"/>
|
|
<!-- Polygon hint -->
|
|
<path d="M88 75 L105 72 L108 85 L90 88 Z" fill="#8b5cf6" opacity="0.15" stroke="#8b5cf6" stroke-width="1"/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="card-tag crud">CRUD + Draw Tools</div>
|
|
<div class="card-title">WebGIS SPBU Kota Pontianak</div>
|
|
<div class="card-desc">
|
|
Sistem pemetaan SPBU interaktif dengan fitur CRUD lengkap — tambah, edit, hapus
|
|
titik SPBU. Dilengkapi draw tools untuk menggambar jalan (polyline) dan kavling (polygon)
|
|
langsung di peta, serta filter status operasional 24 jam.
|
|
</div>
|
|
<div class="card-techs">
|
|
<span class="card-tech">Leaflet.js</span>
|
|
<span class="card-tech">Leaflet Draw</span>
|
|
<span class="card-tech">PHP + MySQL</span>
|
|
<span class="card-tech">CRUD</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Card 2: Kepadatan Penduduk -->
|
|
<a href="http://localhost/webgis/02/index.html" class="project-card reveal" id="card-02" style="animation-delay: 0.1s">
|
|
<div class="card-preview-wrap">
|
|
<div class="card-icon-glow" style="background: var(--accent-3);"></div>
|
|
<div class="card-number">02</div>
|
|
<div class="card-arrow">
|
|
<svg viewBox="0 0 24 24"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg>
|
|
</div>
|
|
<div class="card-preview">
|
|
<!-- Choropleth Map Icon -->
|
|
<svg class="card-icon-svg" viewBox="0 0 120 120" fill="none">
|
|
<!-- Map regions -->
|
|
<path d="M20 30 L55 20 L60 50 L35 60 Z" fill="#f59e0b" opacity="0.8" rx="4"/>
|
|
<path d="M55 20 L95 25 L90 55 L60 50 Z" fill="#d97706" opacity="0.7" rx="4"/>
|
|
<path d="M35 60 L60 50 L65 85 L25 90 Z" fill="#fbbf24" opacity="0.6" rx="4"/>
|
|
<path d="M60 50 L90 55 L95 80 L65 85 Z" fill="#b45309" opacity="0.9" rx="4"/>
|
|
<!-- Map outline glow -->
|
|
<path d="M20 30 L55 20 L95 25 L90 55 L95 80 L65 85 L25 90 L35 60 Z"
|
|
stroke="#f59e0b" stroke-width="1.5" fill="none" opacity="0.4"/>
|
|
<!-- People dots -->
|
|
<circle cx="45" cy="40" r="3" fill="white" opacity="0.7"/>
|
|
<circle cx="75" cy="38" r="4" fill="white" opacity="0.8"/>
|
|
<circle cx="50" cy="68" r="2.5" fill="white" opacity="0.6"/>
|
|
<circle cx="78" cy="65" r="5" fill="white" opacity="0.9"/>
|
|
<!-- Legend bar -->
|
|
<rect x="30" y="98" width="60" height="6" rx="3" fill="url(#grad-heat)" opacity="0.7"/>
|
|
<defs>
|
|
<linearGradient id="grad-heat" x1="0" y1="0" x2="1" y2="0">
|
|
<stop offset="0%" stop-color="#fef3c7"/>
|
|
<stop offset="50%" stop-color="#f59e0b"/>
|
|
<stop offset="100%" stop-color="#7c2d12"/>
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="card-tag choropleth">Choropleth Map</div>
|
|
<div class="card-title">Kepadatan Penduduk Kota Pontianak</div>
|
|
<div class="card-desc">
|
|
Visualisasi peta tematik kepadatan penduduk per kelurahan di Kota Pontianak
|
|
menggunakan teknik choropleth dengan gradasi warna berdasarkan jumlah jiwa.
|
|
Dilengkapi hover interaktif dan legenda dinamis.
|
|
</div>
|
|
<div class="card-techs">
|
|
<span class="card-tech">Leaflet.js</span>
|
|
<span class="card-tech">GeoJSON</span>
|
|
<span class="card-tech">Choropleth</span>
|
|
<span class="card-tech">Interactive</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Card 3: BantSOSial GIS -->
|
|
<a href="http://localhost/webgis/04/index.html" class="project-card reveal" id="card-04" style="animation-delay: 0.2s">
|
|
<div class="card-preview-wrap">
|
|
<div class="card-icon-glow" style="background: var(--accent-4);"></div>
|
|
<div class="card-number">04</div>
|
|
<div class="card-arrow">
|
|
<svg viewBox="0 0 24 24"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg>
|
|
</div>
|
|
<div class="card-preview">
|
|
<!-- Social Aid / Distribution Icon -->
|
|
<svg class="card-icon-svg" viewBox="0 0 120 120" fill="none">
|
|
<!-- Central mosque/worship icon -->
|
|
<path d="M60 25 Q60 15 60 15 Q65 20 65 25" fill="#10b981" opacity="0.8"/>
|
|
<rect x="45" y="25" width="30" height="35" rx="4" fill="#10b981" opacity="0.7"/>
|
|
<path d="M40 60 L80 60 L80 65 L40 65 Z" fill="#10b981" opacity="0.5"/>
|
|
<!-- Dome -->
|
|
<ellipse cx="60" cy="28" rx="12" ry="8" fill="#059669" opacity="0.6"/>
|
|
<!-- Radius circle -->
|
|
<circle cx="60" cy="50" r="35" fill="none" stroke="#10b981" stroke-width="1.5"
|
|
stroke-dasharray="6 4" opacity="0.35"/>
|
|
<!-- Houses around -->
|
|
<rect x="20" y="40" width="10" height="10" rx="2" fill="#ef4444" opacity="0.7"/>
|
|
<rect x="90" y="45" width="10" height="10" rx="2" fill="#f59e0b" opacity="0.7"/>
|
|
<rect x="30" y="75" width="10" height="10" rx="2" fill="#22c55e" opacity="0.7"/>
|
|
<rect x="80" y="70" width="10" height="10" rx="2" fill="#ef4444" opacity="0.7"/>
|
|
<rect x="55" y="80" width="10" height="10" rx="2" fill="#f59e0b" opacity="0.7"/>
|
|
<!-- Connection lines -->
|
|
<line x1="25" y1="45" x2="45" y2="45" stroke="#ef4444" stroke-width="0.8" opacity="0.4" stroke-dasharray="3 2"/>
|
|
<line x1="80" y1="50" x2="95" y2="50" stroke="#f59e0b" stroke-width="0.8" opacity="0.4" stroke-dasharray="3 2"/>
|
|
<!-- Legend dots -->
|
|
<circle cx="25" cy="100" r="4" fill="#ef4444" opacity="0.7"/>
|
|
<circle cx="50" cy="100" r="4" fill="#f59e0b" opacity="0.7"/>
|
|
<circle cx="75" cy="100" r="4" fill="#22c55e" opacity="0.7"/>
|
|
<text x="32" y="103" font-size="7" fill="#64748b" font-family="sans-serif">Belum</text>
|
|
<text x="57" y="103" font-size="7" fill="#64748b" font-family="sans-serif">Sudah</text>
|
|
<text x="82" y="103" font-size="7" fill="#64748b" font-family="sans-serif">Luar</text>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="card-tag fullstack">Full-Stack WebGIS</div>
|
|
<div class="card-title">Distribusi Bantuan Sosial Pontianak</div>
|
|
<div class="card-desc">
|
|
Aplikasi WebGIS lengkap untuk memetakan distribusi bantuan sosial berbasis rumah ibadah.
|
|
Fitur meliputi role system (Admin, Surveyer, Viewer), radius jangkauan,
|
|
input data keluarga miskin, status bantuan, dan sistem pelaporan masyarakat.
|
|
</div>
|
|
<div class="card-techs">
|
|
<span class="card-tech">Leaflet.js</span>
|
|
<span class="card-tech">PHP + MySQL</span>
|
|
<span class="card-tech">Role System</span>
|
|
<span class="card-tech">Pelaporan</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
<div class="card-arrow">
|
|
<svg viewBox="0 0 24 24"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg>
|
|
</div>
|
|
<div class="card-preview">
|
|
<!-- Choropleth Map Icon -->
|
|
<svg class="card-icon-svg" viewBox="0 0 120 120" fill="none">
|
|
<!-- Map regions -->
|
|
<path d="M20 30 L55 20 L60 50 L35 60 Z" fill="#f59e0b" opacity="0.8" rx="4"/>
|
|
<path d="M55 20 L95 25 L90 55 L60 50 Z" fill="#d97706" opacity="0.7" rx="4"/>
|
|
<path d="M35 60 L60 50 L65 85 L25 90 Z" fill="#fbbf24" opacity="0.6" rx="4"/>
|
|
<path d="M60 50 L90 55 L95 80 L65 85 Z" fill="#b45309" opacity="0.9" rx="4"/>
|
|
<!-- Map outline glow -->
|
|
<path d="M20 30 L55 20 L95 25 L90 55 L95 80 L65 85 L25 90 L35 60 Z"
|
|
stroke="#f59e0b" stroke-width="1.5" fill="none" opacity="0.4"/>
|
|
<!-- People dots -->
|
|
<circle cx="45" cy="40" r="3" fill="white" opacity="0.7"/>
|
|
<circle cx="75" cy="38" r="4" fill="white" opacity="0.8"/>
|
|
<circle cx="50" cy="68" r="2.5" fill="white" opacity="0.6"/>
|
|
<circle cx="78" cy="65" r="5" fill="white" opacity="0.9"/>
|
|
<!-- Legend bar -->
|
|
<rect x="30" y="98" width="60" height="6" rx="3" fill="url(#grad-heat)" opacity="0.7"/>
|
|
<defs>
|
|
<linearGradient id="grad-heat" x1="0" y1="0" x2="1" y2="0">
|
|
<stop offset="0%" stop-color="#fef3c7"/>
|
|
<stop offset="50%" stop-color="#f59e0b"/>
|
|
<stop offset="100%" stop-color="#7c2d12"/>
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="card-tag choropleth">Choropleth Map</div>
|
|
<div class="card-title">Kepadatan Penduduk Kota Pontianak</div>
|
|
<div class="card-desc">
|
|
Visualisasi peta tematik kepadatan penduduk per kelurahan di Kota Pontianak
|
|
menggunakan teknik choropleth dengan gradasi warna berdasarkan jumlah jiwa.
|
|
Dilengkapi hover interaktif dan legenda dinamis.
|
|
</div>
|
|
<div class="card-techs">
|
|
<span class="card-tech">Leaflet.js</span>
|
|
<span class="card-tech">GeoJSON</span>
|
|
<span class="card-tech">Choropleth</span>
|
|
<span class="card-tech">Interactive</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
|
|
|
|
<div class="card-preview-wrap">
|
|
<div class="card-icon-glow" style="background: var(--accent-1);"></div>
|
|
<div class="card-number">03</div>
|
|
<div class="card-arrow">
|
|
<svg viewBox="0 0 24 24"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg>
|
|
</div>
|
|
<div class="card-preview">
|
|
<!-- SPBU / Gas Station Icon -->
|
|
<svg class="card-icon-svg" viewBox="0 0 120 120" fill="none">
|
|
<!-- Gas pump body -->
|
|
<rect x="25" y="35" width="40" height="55" rx="6" fill="#06b6d4" opacity="0.8"/>
|
|
<rect x="30" y="42" width="30" height="20" rx="3" fill="#0e7490" opacity="0.6"/>
|
|
<!-- Display -->
|
|
<rect x="33" y="45" width="24" height="14" rx="2" fill="#164e63"/>
|
|
<text x="38" y="55" font-family="monospace" font-size="8" fill="#22d3ee">24H</text>
|
|
<!-- Nozzle -->
|
|
<path d="M65 45 L75 40 L78 50 L80 75" stroke="#06b6d4" stroke-width="3" fill="none" stroke-linecap="round"/>
|
|
<circle cx="80" cy="78" r="4" fill="#06b6d4" opacity="0.7"/>
|
|
<!-- Base -->
|
|
<rect x="20" y="88" width="50" height="6" rx="3" fill="#06b6d4" opacity="0.3"/>
|
|
<!-- Map pin markers -->
|
|
<circle cx="95" cy="35" r="6" fill="#10b981" opacity="0.8"/>
|
|
<circle cx="95" cy="35" r="2.5" fill="white"/>
|
|
<circle cx="100" cy="55" r="5" fill="#ef4444" opacity="0.8"/>
|
|
<circle cx="100" cy="55" r="2" fill="white"/>
|
|
<!-- Lines / roads -->
|
|
<path d="M85 45 L105 45" stroke="#334155" stroke-width="2" stroke-dasharray="4 3" opacity="0.4"/>
|
|
<path d="M88 65 L108 65" stroke="#334155" stroke-width="2" stroke-dasharray="4 3" opacity="0.4"/>
|
|
<!-- Polygon hint -->
|
|
<path d="M88 75 L105 72 L108 85 L90 88 Z" fill="#8b5cf6" opacity="0.15" stroke="#8b5cf6" stroke-width="1" opacity="0.3"/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="card-tag crud">CRUD + Draw Tools</div>
|
|
<div class="card-title">WebGIS SPBU Kota Pontianak</div>
|
|
<div class="card-desc">
|
|
Sistem pemetaan SPBU interaktif dengan fitur CRUD lengkap — tambah, edit, hapus
|
|
titik SPBU. Dilengkapi draw tools untuk menggambar jalan (polyline) dan kavling (polygon)
|
|
langsung di peta, serta filter status operasional 24 jam.
|
|
</div>
|
|
<div class="card-techs">
|
|
<span class="card-tech">Leaflet.js</span>
|
|
<span class="card-tech">Leaflet Draw</span>
|
|
<span class="card-tech">PHP + MySQL</span>
|
|
<span class="card-tech">CRUD</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Card 3: BantSOSial GIS -->
|
|
<a href="http://localhost/webgis/04/index.html" class="project-card reveal" id="card-04" style="animation-delay: 0.2s">
|
|
<div class="card-preview-wrap">
|
|
<div class="card-icon-glow" style="background: var(--accent-4);"></div>
|
|
<div class="card-number">04</div>
|
|
<div class="card-arrow">
|
|
<svg viewBox="0 0 24 24"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg>
|
|
</div>
|
|
<div class="card-preview">
|
|
<!-- Social Aid / Distribution Icon -->
|
|
<svg class="card-icon-svg" viewBox="0 0 120 120" fill="none">
|
|
<!-- Central mosque/worship icon -->
|
|
<path d="M60 25 Q60 15 60 15 Q65 20 65 25" fill="#10b981" opacity="0.8"/>
|
|
<rect x="45" y="25" width="30" height="35" rx="4" fill="#10b981" opacity="0.7"/>
|
|
<path d="M40 60 L80 60 L80 65 L40 65 Z" fill="#10b981" opacity="0.5"/>
|
|
<!-- Dome -->
|
|
<ellipse cx="60" cy="28" rx="12" ry="8" fill="#059669" opacity="0.6"/>
|
|
<!-- Radius circle -->
|
|
<circle cx="60" cy="50" r="35" fill="none" stroke="#10b981" stroke-width="1.5"
|
|
stroke-dasharray="6 4" opacity="0.35"/>
|
|
<!-- Houses around -->
|
|
<rect x="20" y="40" width="10" height="10" rx="2" fill="#ef4444" opacity="0.7"/>
|
|
<rect x="90" y="45" width="10" height="10" rx="2" fill="#f59e0b" opacity="0.7"/>
|
|
<rect x="30" y="75" width="10" height="10" rx="2" fill="#22c55e" opacity="0.7"/>
|
|
<rect x="80" y="70" width="10" height="10" rx="2" fill="#ef4444" opacity="0.7"/>
|
|
<rect x="55" y="80" width="10" height="10" rx="2" fill="#f59e0b" opacity="0.7"/>
|
|
<!-- Connection lines -->
|
|
<line x1="25" y1="45" x2="45" y2="45" stroke="#ef4444" stroke-width="0.8" opacity="0.4" stroke-dasharray="3 2"/>
|
|
<line x1="80" y1="50" x2="95" y2="50" stroke="#f59e0b" stroke-width="0.8" opacity="0.4" stroke-dasharray="3 2"/>
|
|
<!-- Legend dots -->
|
|
<circle cx="25" cy="100" r="4" fill="#ef4444" opacity="0.7"/>
|
|
<circle cx="50" cy="100" r="4" fill="#f59e0b" opacity="0.7"/>
|
|
<circle cx="75" cy="100" r="4" fill="#22c55e" opacity="0.7"/>
|
|
<text x="32" y="103" font-size="7" fill="#64748b" font-family="sans-serif">Belum</text>
|
|
<text x="57" y="103" font-size="7" fill="#64748b" font-family="sans-serif">Sudah</text>
|
|
<text x="82" y="103" font-size="7" fill="#64748b" font-family="sans-serif">Luar</text>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="card-tag fullstack">Full-Stack WebGIS</div>
|
|
<div class="card-title">Distribusi Bantuan Sosial Pontianak</div>
|
|
<div class="card-desc">
|
|
Aplikasi WebGIS lengkap untuk memetakan distribusi bantuan sosial berbasis rumah ibadah.
|
|
Fitur meliputi role system (Admin, Surveyer, Viewer), radius jangkauan,
|
|
input data keluarga miskin, status bantuan, dan sistem pelaporan masyarakat.
|
|
</div>
|
|
<div class="card-techs">
|
|
<span class="card-tech">Leaflet.js</span>
|
|
<span class="card-tech">PHP + MySQL</span>
|
|
<span class="card-tech">Role System</span>
|
|
<span class="card-tech">Pelaporan</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Footer -->
|
|
<footer class="footer">
|
|
<div class="footer-text">
|
|
© 2026 WebGIS Pontianak — Dibuat dengan
|
|
<a href="https://leafletjs.com" target="_blank">Leaflet.js</a> & ❤️
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// Navbar scroll effect
|
|
const navbar = document.getElementById('navbar');
|
|
window.addEventListener('scroll', () => {
|
|
navbar.classList.toggle('scrolled', window.scrollY > 40);
|
|
});
|
|
|
|
// Scroll reveal animation
|
|
const revealEls = document.querySelectorAll('.reveal');
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach((entry, i) => {
|
|
if (entry.isIntersecting) {
|
|
setTimeout(() => {
|
|
entry.target.classList.add('visible');
|
|
}, i * 120);
|
|
revealObserver.unobserve(entry.target);
|
|
}
|
|
});
|
|
}, { threshold: 0.15 });
|
|
|
|
revealEls.forEach(el => revealObserver.observe(el));
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|