972 lines
29 KiB
PHP
972 lines
29 KiB
PHP
<?php
|
|
if (!empty($_GET['q'])) {
|
|
switch ($_GET['q']) {
|
|
case 'info':
|
|
phpinfo();
|
|
exit;
|
|
break;
|
|
}
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="id">
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>WebGIS Portal — Kota Pontianak</title>
|
|
<meta name="description" content="Portal Sistem Informasi Geografis (WebGIS) Kota Pontianak — Pusat akses semua project WebGIS yang dibangun untuk pengelolaan data spasial wilayah." />
|
|
<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=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
|
|
|
|
<style>
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
:root {
|
|
--bg: #060b14;
|
|
--bg-2: #0c1424;
|
|
--bg-card: rgba(255, 255, 255, 0.04);
|
|
--bg-card-h: rgba(255, 255, 255, 0.08);
|
|
--border: rgba(255, 255, 255, 0.08);
|
|
--border-h: rgba(255, 255, 255, 0.18);
|
|
--text-1: #f0f6ff;
|
|
--text-2: #8b9ab8;
|
|
--text-3: #4a5568;
|
|
--accent-1: #3b82f6;
|
|
--accent-2: #8b5cf6;
|
|
--accent-3: #06b6d4;
|
|
--green: #10b981;
|
|
--orange: #f59e0b;
|
|
--pink: #ec4899;
|
|
--radius: 16px;
|
|
--radius-sm: 10px;
|
|
--shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
|
|
--shadow-lg: 0 20px 80px rgba(0, 0, 0, 0.7);
|
|
}
|
|
|
|
html {
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Inter', sans-serif;
|
|
background: var(--bg);
|
|
color: var(--text-1);
|
|
min-height: 100vh;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
/* ── CANVAS BG ─────────────────────────────────────── */
|
|
#bg-canvas {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.grid-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 0;
|
|
pointer-events: none;
|
|
background-image:
|
|
linear-gradient(rgba(59, 130, 246, 0.03) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(59, 130, 246, 0.03) 1px, transparent 1px);
|
|
background-size: 60px 60px;
|
|
}
|
|
|
|
/* ── WRAPPER ───────────────────────────────────────── */
|
|
.wrapper {
|
|
position: relative;
|
|
z-index: 1;
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
padding: 0 24px;
|
|
}
|
|
|
|
/* ── NAVBAR ────────────────────────────────────────── */
|
|
nav {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
padding: 0 24px;
|
|
background: rgba(6, 11, 20, 0.85);
|
|
backdrop-filter: blur(20px);
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.nav-inner {
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
height: 64px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.nav-brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
font-weight: 700;
|
|
font-size: 1.05rem;
|
|
color: var(--text-1);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.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: 1rem;
|
|
flex-shrink: 0;
|
|
box-shadow: 0 0 20px rgba(59, 130, 246, 0.4);
|
|
}
|
|
|
|
.nav-links {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.nav-links a {
|
|
padding: 7px 14px;
|
|
border-radius: var(--radius-sm);
|
|
font-size: 0.82rem;
|
|
font-weight: 500;
|
|
color: var(--text-2);
|
|
text-decoration: none;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.nav-links a:hover {
|
|
color: var(--text-1);
|
|
background: var(--bg-card);
|
|
}
|
|
|
|
.nav-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 5px 12px;
|
|
background: rgba(59, 130, 246, 0.12);
|
|
border: 1px solid rgba(59, 130, 246, 0.25);
|
|
border-radius: 20px;
|
|
font-size: 0.73rem;
|
|
font-weight: 600;
|
|
color: var(--accent-1);
|
|
}
|
|
|
|
.dot-live {
|
|
width: 7px;
|
|
height: 7px;
|
|
background: var(--green);
|
|
border-radius: 50%;
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
|
|
0%,
|
|
100% {
|
|
opacity: 1;
|
|
transform: scale(1)
|
|
}
|
|
|
|
50% {
|
|
opacity: .5;
|
|
transform: scale(.7)
|
|
}
|
|
}
|
|
|
|
/* ── HERO ──────────────────────────────────────────── */
|
|
.hero {
|
|
padding: 100px 0 70px;
|
|
text-align: center;
|
|
}
|
|
|
|
.hero-eyebrow {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 16px;
|
|
border-radius: 20px;
|
|
background: rgba(139, 92, 246, 0.12);
|
|
border: 1px solid rgba(139, 92, 246, 0.25);
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
color: var(--accent-2);
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
margin-bottom: 24px;
|
|
animation: fadeUp 0.6s ease both;
|
|
}
|
|
|
|
.hero-title {
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
font-size: clamp(2.2rem, 5vw, 3.8rem);
|
|
font-weight: 800;
|
|
line-height: 1.1;
|
|
letter-spacing: -0.02em;
|
|
margin-bottom: 20px;
|
|
animation: fadeUp 0.6s ease 0.1s both;
|
|
}
|
|
|
|
.hero-title .gradient-text {
|
|
background: linear-gradient(135deg, var(--accent-1) 0%, var(--accent-2) 50%, var(--pink) 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
|
|
.hero-sub {
|
|
font-size: 1.05rem;
|
|
color: var(--text-2);
|
|
line-height: 1.7;
|
|
max-width: 560px;
|
|
margin: 0 auto 40px;
|
|
animation: fadeUp 0.6s ease 0.2s both;
|
|
}
|
|
|
|
.hero-stats {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 40px;
|
|
margin-top: 50px;
|
|
padding-top: 40px;
|
|
border-top: 1px solid var(--border);
|
|
animation: fadeUp 0.6s ease 0.35s both;
|
|
}
|
|
|
|
.hero-stat {
|
|
text-align: center;
|
|
}
|
|
|
|
.hero-stat-num {
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
font-size: 2rem;
|
|
font-weight: 700;
|
|
background: linear-gradient(135deg, var(--accent-1), var(--accent-3));
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
|
|
.hero-stat-label {
|
|
font-size: 0.75rem;
|
|
color: var(--text-3);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
margin-top: 4px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
@keyframes fadeUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* ── SECTION HEADER ────────────────────────────────── */
|
|
.section-header {
|
|
margin-bottom: 36px;
|
|
animation: fadeUp 0.6s ease 0.3s both;
|
|
}
|
|
|
|
.section-label {
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
color: var(--accent-1);
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.section-label::before {
|
|
content: '';
|
|
width: 20px;
|
|
height: 2px;
|
|
background: var(--accent-1);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.section-title {
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
font-size: 1.8rem;
|
|
font-weight: 700;
|
|
color: var(--text-1);
|
|
}
|
|
|
|
/* ── PROJECT CARDS ─────────────────────────────────── */
|
|
.projects-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 28px;
|
|
margin-bottom: 80px;
|
|
}
|
|
|
|
.project-card {
|
|
position: relative;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
padding: 30px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
transition: all 0.3s ease;
|
|
overflow: hidden;
|
|
animation: fadeUp 0.6s ease both;
|
|
}
|
|
|
|
.project-card::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(135deg, var(--card-color-1, rgba(59, 130, 246, 0.07)), var(--card-color-2, rgba(139, 92, 246, 0.04)));
|
|
opacity: 0;
|
|
transition: opacity 0.3s;
|
|
border-radius: inherit;
|
|
}
|
|
|
|
.project-card:hover {
|
|
border-color: var(--border-h);
|
|
transform: translateY(-6px);
|
|
box-shadow: var(--shadow-lg);
|
|
background: var(--bg-card-h);
|
|
}
|
|
|
|
.project-card:hover::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* accent glow line on top */
|
|
.project-card::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 2px;
|
|
background: var(--card-accent, linear-gradient(90deg, var(--accent-1), var(--accent-2)));
|
|
transform: scaleX(0);
|
|
transform-origin: left;
|
|
transition: transform 0.4s ease;
|
|
}
|
|
|
|
.project-card:hover::after {
|
|
transform: scaleX(1);
|
|
}
|
|
|
|
.card-icon-wrap {
|
|
width: 58px;
|
|
height: 58px;
|
|
border-radius: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.5rem;
|
|
margin-bottom: 22px;
|
|
flex-shrink: 0;
|
|
position: relative;
|
|
}
|
|
|
|
.card-icon-wrap::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: -1px;
|
|
border-radius: 17px;
|
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
}
|
|
|
|
.card-number {
|
|
position: absolute;
|
|
top: 20px;
|
|
right: 24px;
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
font-size: 3.5rem;
|
|
font-weight: 800;
|
|
color: rgba(255, 255, 255, 0.04);
|
|
line-height: 1;
|
|
user-select: none;
|
|
}
|
|
|
|
.card-tag-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.tag {
|
|
padding: 3px 10px;
|
|
border-radius: 20px;
|
|
font-size: 0.65rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
.card-title {
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
font-size: 1.25rem;
|
|
font-weight: 700;
|
|
color: var(--text-1);
|
|
margin-bottom: 10px;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.card-desc {
|
|
font-size: 0.84rem;
|
|
color: var(--text-2);
|
|
line-height: 1.7;
|
|
margin-bottom: 24px;
|
|
flex: 1;
|
|
}
|
|
|
|
.card-features {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 7px;
|
|
margin-bottom: 26px;
|
|
padding: 14px;
|
|
background: rgba(255, 255, 255, 0.03);
|
|
border-radius: var(--radius-sm);
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.card-feature {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 0.77rem;
|
|
color: var(--text-2);
|
|
}
|
|
|
|
.card-feature i {
|
|
width: 14px;
|
|
text-align: center;
|
|
font-size: 0.72rem;
|
|
}
|
|
|
|
.card-footer {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: auto;
|
|
}
|
|
|
|
.card-url {
|
|
font-size: 0.71rem;
|
|
color: var(--text-3);
|
|
font-family: 'Courier New', monospace;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.btn-open {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 20px;
|
|
border-radius: var(--radius-sm);
|
|
font-size: 0.82rem;
|
|
font-weight: 600;
|
|
color: #fff;
|
|
text-decoration: none;
|
|
transition: all 0.2s;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-family: inherit;
|
|
position: relative;
|
|
z-index: 10;
|
|
}
|
|
|
|
.btn-open:hover {
|
|
filter: brightness(1.15);
|
|
transform: translateX(3px);
|
|
}
|
|
|
|
.btn-open i {
|
|
font-size: 0.72rem;
|
|
transition: transform 0.2s;
|
|
}
|
|
|
|
.btn-open:hover i {
|
|
transform: translateX(4px);
|
|
}
|
|
|
|
/* ── CARD THEMES ───────────────────────────────────── */
|
|
.card-blue {
|
|
--card-color-1: rgba(59, 130, 246, 0.1);
|
|
--card-color-2: rgba(6, 182, 212, 0.05);
|
|
--card-accent: linear-gradient(90deg, #3b82f6, #06b6d4);
|
|
}
|
|
|
|
.card-purple {
|
|
--card-color-1: rgba(139, 92, 246, 0.1);
|
|
--card-color-2: rgba(236, 72, 153, 0.05);
|
|
--card-accent: linear-gradient(90deg, #8b5cf6, #ec4899);
|
|
}
|
|
|
|
/* ── TECH STACK ────────────────────────────────────── */
|
|
.tech-section {
|
|
padding: 50px 0;
|
|
border-top: 1px solid var(--border);
|
|
margin-bottom: 60px;
|
|
}
|
|
|
|
.tech-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.tech-chip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 8px 16px;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
font-size: 0.78rem;
|
|
font-weight: 500;
|
|
color: var(--text-2);
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.tech-chip:hover {
|
|
border-color: var(--border-h);
|
|
color: var(--text-1);
|
|
background: var(--bg-card-h);
|
|
}
|
|
|
|
.tech-chip i {
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
/* ── FOOTER ────────────────────────────────────────── */
|
|
footer {
|
|
border-top: 1px solid var(--border);
|
|
padding: 32px 24px;
|
|
}
|
|
|
|
.footer-inner {
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
}
|
|
|
|
.footer-brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 0.83rem;
|
|
font-weight: 600;
|
|
color: var(--text-2);
|
|
}
|
|
|
|
.footer-info {
|
|
font-size: 0.73rem;
|
|
color: var(--text-3);
|
|
}
|
|
|
|
.footer-info span {
|
|
color: var(--text-2);
|
|
}
|
|
|
|
/* ── SCROLL BAR ────────────────────────────────────── */
|
|
.scroll-indicator {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
height: 3px;
|
|
background: linear-gradient(90deg, var(--accent-1), var(--accent-2), var(--pink));
|
|
z-index: 9999;
|
|
transition: width 0.1s;
|
|
width: 0%;
|
|
}
|
|
|
|
/* ── RESPONSIVE ────────────────────────────────────── */
|
|
@media(max-width: 720px) {
|
|
.hero {
|
|
padding: 70px 0 50px;
|
|
}
|
|
|
|
.hero-stats {
|
|
gap: 24px;
|
|
}
|
|
|
|
.projects-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.nav-links {
|
|
display: none;
|
|
}
|
|
|
|
.footer-inner {
|
|
flex-direction: column;
|
|
text-align: center;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="scroll-indicator" id="scroll-bar"></div>
|
|
<canvas id="bg-canvas"></canvas>
|
|
<div class="grid-overlay"></div>
|
|
|
|
<!-- ── NAV ────────────────────────────────────────────── -->
|
|
<nav>
|
|
<div class="nav-inner">
|
|
<a class="nav-brand" href="#">
|
|
<div class="nav-logo"><i class="fas fa-globe" style="color:#fff"></i></div>
|
|
WebGIS Portal
|
|
</a>
|
|
<div class="nav-links">
|
|
<a href="#projects">Projects</a>
|
|
<a href="#stack">Tech Stack</a>
|
|
<a href="/?q=info" target="_blank">PHP Info</a>
|
|
</div>
|
|
<div class="nav-badge">
|
|
<span class="dot-live"></span>
|
|
2 Projects Online
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- ── HERO ───────────────────────────────────────────── -->
|
|
<section class="hero">
|
|
<div class="wrapper">
|
|
<div class="hero-eyebrow">
|
|
<i class="fas fa-map-location-dot"></i>
|
|
Sistem Informasi Geografis
|
|
</div>
|
|
<h1 class="hero-title">
|
|
Portal <span class="gradient-text">WebGIS</span><br />Kota Pontianak
|
|
</h1>
|
|
<p class="hero-sub">
|
|
Pusat akses seluruh project Sistem Informasi Geografis berbasis web untuk pengelolaan data spasial wilayah Kota Pontianak.
|
|
</p>
|
|
<div class="hero-stats">
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">2</div>
|
|
<div class="hero-stat-label">Project Aktif</div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">6+</div>
|
|
<div class="hero-stat-label">Layer Data</div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">PHP</div>
|
|
<div class="hero-stat-label"><?php echo PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION; ?></div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hero-stat-num">GIS</div>
|
|
<div class="hero-stat-label">LeafletJS</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── PROJECTS ────────────────────────────────────────── -->
|
|
<section id="projects">
|
|
<div class="wrapper">
|
|
<div class="section-header">
|
|
<div class="section-label">Daftar Project</div>
|
|
<h2 class="section-title">Semua WebGIS Project</h2>
|
|
</div>
|
|
|
|
<div class="projects-grid">
|
|
|
|
<!-- ══ CARD 1: WebGIS Layer ══════════════════════════ -->
|
|
<div class="project-card card-blue" style="animation-delay:0.1s">
|
|
<span class="card-number">01</span>
|
|
<div class="card-icon-wrap" style="background:linear-gradient(135deg,rgba(59,130,246,0.2),rgba(6,182,212,0.2))">
|
|
<i class="fas fa-layer-group" style="color:#3b82f6"></i>
|
|
</div>
|
|
|
|
<div class="card-tag-row">
|
|
<span class="tag" style="background:rgba(59,130,246,0.15);color:#60a5fa;border:1px solid rgba(59,130,246,0.3)">
|
|
<i class="fas fa-road"></i> Jalan
|
|
</span>
|
|
<span class="tag" style="background:rgba(139,92,246,0.15);color:#a78bfa;border:1px solid rgba(139,92,246,0.3)">
|
|
<i class="fas fa-draw-polygon"></i> Parsil
|
|
</span>
|
|
<span class="tag" style="background:rgba(16,185,129,0.15);color:#34d399;border:1px solid rgba(16,185,129,0.3)">
|
|
<i class="fas fa-gas-pump"></i> SPBU
|
|
</span>
|
|
</div>
|
|
|
|
<h3 class="card-title">WebGIS Layer — Jalan, Parsil & SPBU</h3>
|
|
<p class="card-desc">
|
|
Sistem informasi geografis untuk manajemen data jalan (nasional, provinsi, kabupaten), parsil tanah beserta status kepemilikan, dan sebaran SPBU di Kota Pontianak.
|
|
</p>
|
|
|
|
<div class="card-features">
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#3b82f6"></i>
|
|
<span>Gambar polyline & polygon langsung di peta</span>
|
|
</div>
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#3b82f6"></i>
|
|
<span>CRUD data jalan, parsil tanah & SPBU</span>
|
|
</div>
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#3b82f6"></i>
|
|
<span>Kalkulasi panjang & luas otomatis (LeafletJS)</span>
|
|
</div>
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#3b82f6"></i>
|
|
<span>Layer switcher: Street & Satellite view</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
<div class="card-url">
|
|
<i class="fas fa-link"></i>
|
|
/Web GIS Layer/
|
|
</div>
|
|
<a href="./Web%20GIS%20Layer/index.html"
|
|
class="btn-open"
|
|
style="background:linear-gradient(135deg,#3b82f6,#06b6d4)"
|
|
onclick="window.location.href=this.href; return false;">
|
|
Buka Project <i class="fas fa-arrow-right"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ══ CARD 2: WebGIS Poverty Mapping ════════════════ -->
|
|
<div class="project-card card-purple" style="animation-delay:0.2s">
|
|
<span class="card-number">02</span>
|
|
<div class="card-icon-wrap" style="background:linear-gradient(135deg,rgba(139,92,246,0.2),rgba(236,72,153,0.2))">
|
|
<i class="fas fa-house-chimney-crack" style="color:#a855f7"></i>
|
|
</div>
|
|
|
|
<div class="card-tag-row">
|
|
<span class="tag" style="background:rgba(139,92,246,0.15);color:#a78bfa;border:1px solid rgba(139,92,246,0.3)">
|
|
<i class="fas fa-users"></i> Kemiskinan
|
|
</span>
|
|
<span class="tag" style="background:rgba(236,72,153,0.15);color:#f472b6;border:1px solid rgba(236,72,153,0.3)">
|
|
<i class="fas fa-mosque"></i> Rumah Ibadah
|
|
</span>
|
|
<span class="tag" style="background:rgba(245,158,11,0.15);color:#fbbf24;border:1px solid rgba(245,158,11,0.3)">
|
|
<i class="fas fa-hand-holding-heart"></i> Bantuan
|
|
</span>
|
|
</div>
|
|
|
|
<h3 class="card-title">WebGIS Poverty Mapping & Rumah Ibadah</h3>
|
|
<p class="card-desc">
|
|
Pemetaan keluarga miskin, histori penyaluran bantuan sosial, dan lokasi rumah ibadah berbasis peta interaktif. Dilengkapi dashboard analitik dan laporan spasial.
|
|
</p>
|
|
|
|
<div class="card-features">
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#a855f7"></i>
|
|
<span>Pemetaan & manajemen data keluarga miskin</span>
|
|
</div>
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#a855f7"></i>
|
|
<span>Histori & tracking bantuan sosial</span>
|
|
</div>
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#a855f7"></i>
|
|
<span>Lokasi rumah ibadah (masjid, gereja, dll.)</span>
|
|
</div>
|
|
<div class="card-feature">
|
|
<i class="fas fa-check-circle" style="color:#a855f7"></i>
|
|
<span>Dashboard statistik & laporan lengkap</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
<div class="card-url">
|
|
<i class="fas fa-link"></i>
|
|
/Web GIS Rumah Ibadah/
|
|
</div>
|
|
<a href="./Web%20GIS%20Rumah%20Ibadah/index.html"
|
|
class="btn-open"
|
|
style="background:linear-gradient(135deg,#8b5cf6,#ec4899)"
|
|
onclick="window.location.href=this.href; return false;">
|
|
Buka Project <i class="fas fa-arrow-right"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- /.projects-grid -->
|
|
|
|
<!-- ── TECH STACK ──────────────────────────────────── -->
|
|
<section id="stack" class="tech-section">
|
|
<div class="section-label">Teknologi</div>
|
|
<h2 class="section-title" style="margin-bottom:0">Tech Stack yang Digunakan</h2>
|
|
<div class="tech-grid">
|
|
<div class="tech-chip"><i class="fab fa-html5" style="color:#e34f26"></i> HTML5 & CSS3</div>
|
|
<div class="tech-chip"><i class="fab fa-js" style="color:#f7df1e"></i> JavaScript</div>
|
|
<div class="tech-chip"><i class="fab fa-php" style="color:#777bb4"></i> PHP <?php echo phpversion(); ?></div>
|
|
<div class="tech-chip"><i class="fas fa-database" style="color:#4479a1"></i> MySQL / MariaDB</div>
|
|
<div class="tech-chip"><i class="fas fa-map" style="color:#3b82f6"></i> Leaflet.js 1.9.4</div>
|
|
<div class="tech-chip"><i class="fas fa-pencil-ruler" style="color:#06b6d4"></i> Leaflet.Draw</div>
|
|
<div class="tech-chip"><i class="fas fa-ruler" style="color:#10b981"></i> Leaflet.GeometryUtil</div>
|
|
<div class="tech-chip"><i class="fas fa-globe" style="color:#f59e0b"></i> OpenStreetMap</div>
|
|
<div class="tech-chip"><i class="fas fa-satellite" style="color:#8b5cf6"></i> Esri Satellite</div>
|
|
<div class="tech-chip"><i class="fab fa-font-awesome" style="color:#528dd7"></i> Font Awesome 6</div>
|
|
<div class="tech-chip"><i class="fas fa-server" style="color:#ec4899"></i> Laragon</div>
|
|
<div class="tech-chip"><i class="fas fa-code-branch" style="color:#22d3ee"></i> GeoJSON Format</div>
|
|
</div>
|
|
</section>
|
|
|
|
</div><!-- /.wrapper -->
|
|
</section>
|
|
|
|
<!-- ── FOOTER ──────────────────────────────────────────── -->
|
|
<footer>
|
|
<div class="footer-inner">
|
|
<div class="footer-brand">
|
|
<div class="nav-logo" style="width:28px;height:28px;font-size:.8rem">
|
|
<i class="fas fa-globe" style="color:#fff"></i>
|
|
</div>
|
|
WebGIS Portal — Kota Pontianak
|
|
<div class="footer-info">
|
|
Dibangun dengan <span style="color:#ec4899">♥</span> menggunakan LeafletJS & PHP
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
/* ── ANIMATED PARTICLE CANVAS ─────────────────────────── */
|
|
(function() {
|
|
const canvas = document.getElementById('bg-canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
let W, H, particles = [];
|
|
|
|
function resize() {
|
|
W = canvas.width = window.innerWidth;
|
|
H = canvas.height = window.innerHeight;
|
|
}
|
|
resize();
|
|
window.addEventListener('resize', resize);
|
|
|
|
class Particle {
|
|
constructor() {
|
|
this.reset();
|
|
}
|
|
reset() {
|
|
this.x = Math.random() * W;
|
|
this.y = Math.random() * H;
|
|
this.r = Math.random() * 1.5 + 0.3;
|
|
this.vx = (Math.random() - 0.5) * 0.25;
|
|
this.vy = (Math.random() - 0.5) * 0.25;
|
|
this.a = Math.random() * 0.5 + 0.1;
|
|
const p = ['59,130,246', '139,92,246', '6,182,212', '16,185,129'];
|
|
this.color = p[Math.floor(Math.random() * p.length)];
|
|
}
|
|
update() {
|
|
this.x += this.vx;
|
|
this.y += this.vy;
|
|
if (this.x < 0 || this.x > W || this.y < 0 || this.y > H) this.reset();
|
|
}
|
|
draw() {
|
|
ctx.beginPath();
|
|
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
|
|
ctx.fillStyle = `rgba(${this.color},${this.a})`;
|
|
ctx.fill();
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < 120; i++) particles.push(new Particle());
|
|
|
|
function drawLines() {
|
|
for (let i = 0; i < particles.length; i++)
|
|
for (let j = i + 1; j < particles.length; j++) {
|
|
const dx = particles[i].x - particles[j].x,
|
|
dy = particles[i].y - particles[j].y;
|
|
const d = Math.sqrt(dx * dx + dy * dy);
|
|
if (d < 100) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(particles[i].x, particles[i].y);
|
|
ctx.lineTo(particles[j].x, particles[j].y);
|
|
ctx.strokeStyle = `rgba(59,130,246,${0.06*(1-d/100)})`;
|
|
ctx.lineWidth = 0.5;
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
}
|
|
|
|
function animate() {
|
|
ctx.clearRect(0, 0, W, H);
|
|
particles.forEach(p => {
|
|
p.update();
|
|
p.draw();
|
|
});
|
|
drawLines();
|
|
requestAnimationFrame(animate);
|
|
}
|
|
animate();
|
|
})();
|
|
|
|
/* ── SCROLL PROGRESS ──────────────────────────────────── */
|
|
window.addEventListener('scroll', () => {
|
|
const st = document.documentElement.scrollTop;
|
|
const sh = document.documentElement.scrollHeight - document.documentElement.clientHeight;
|
|
document.getElementById('scroll-bar').style.width = (st / sh * 100) + '%';
|
|
});
|
|
|
|
/* ── CARD TILT ────────────────────────────────────────── */
|
|
document.querySelectorAll('.project-card').forEach(card => {
|
|
card.addEventListener('mousemove', e => {
|
|
const r = card.getBoundingClientRect();
|
|
const x = ((e.clientX - r.left) / r.width - 0.5) * 8;
|
|
const y = ((e.clientY - r.top) / r.height - 0.5) * 8;
|
|
card.style.transform = `translateY(-6px) rotateX(${-y}deg) rotateY(${x}deg)`;
|
|
});
|
|
card.addEventListener('mouseleave', () => {
|
|
card.style.transform = '';
|
|
});
|
|
});
|
|
|
|
/* ── INTERSECTION OBSERVER ────────────────────────────── */
|
|
const obs = new IntersectionObserver(entries => {
|
|
entries.forEach(e => {
|
|
if (e.isIntersecting) e.target.style.animationPlayState = 'running';
|
|
});
|
|
}, {
|
|
threshold: 0.1
|
|
});
|
|
document.querySelectorAll('.project-card,.tech-chip').forEach(el => {
|
|
el.style.animationPlayState = 'paused';
|
|
obs.observe(el);
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|