added js
This commit is contained in:
160
script/mapbox.js
Normal file
160
script/mapbox.js
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
// script.js
|
||||||
|
|
||||||
|
// 1️⃣ Your Mapbox access token
|
||||||
|
mapboxgl.accessToken = 'pk.eyJ1IjoiY2FiYmJ5eSIsImEiOiJjbWRpYzY1MGgwYzA5Mm1xM25udDUzbGtpIn0.RX6zv4VI6r2vpj7IWidz0w';
|
||||||
|
|
||||||
|
// 2️⃣ Initialize the map zoomed fully out (globe‑like)
|
||||||
|
const map = new mapboxgl.Map({
|
||||||
|
container: 'map',
|
||||||
|
style: 'mapbox://styles/mapbox/streets-v12',
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 1,
|
||||||
|
attributionControl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3️⃣ Define your companies ([lat, lng], zoom, imageUrl, description)
|
||||||
|
const companies = [
|
||||||
|
{
|
||||||
|
id: 'overview',
|
||||||
|
name: 'Overview',
|
||||||
|
coords: [40.14010599415405, -107.69483342077913],
|
||||||
|
zoom: 3,
|
||||||
|
imageUrl: 'images/wip.jpg',
|
||||||
|
description: `
|
||||||
|
<h2>Overview</h2>
|
||||||
|
<p>Use the controls in the top left corner to jump to a spot!</p>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'tancha',
|
||||||
|
name: 'Tan‑Cha',
|
||||||
|
coords: [37.325382569107695, -122.01149036275054],
|
||||||
|
zoom: 9,
|
||||||
|
imageUrl: 'images/tancha.jpg',
|
||||||
|
description: `
|
||||||
|
<h2>Tan‑Cha</h2>
|
||||||
|
<p>Wip.</p>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'pokehouse',
|
||||||
|
name: 'Poke House',
|
||||||
|
coords: [37.301113384436285, -121.9493462690826],
|
||||||
|
zoom: 9,
|
||||||
|
imageUrl: 'images/wip.jpg',
|
||||||
|
description: `
|
||||||
|
<h2>Poke House</h2>
|
||||||
|
<p>Wip.</p>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'nanobase',
|
||||||
|
name: 'NanoBase',
|
||||||
|
coords: [34.68104506798117, 135.49167196036512],
|
||||||
|
zoom: 9,
|
||||||
|
imageUrl: 'images/work.jpg',
|
||||||
|
description: `
|
||||||
|
<h2>NanoBase</h2>
|
||||||
|
<p>Developed automated payroll processing scripts in Python, reducing errors by 85%.</p>
|
||||||
|
<a href="https://www.nanobase.co.jp/blogs/30">NanoBase Blog</a>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lanner',
|
||||||
|
name: 'Lanner Electronics',
|
||||||
|
coords: [43.69824981965482, -79.62570806485385],
|
||||||
|
zoom: 9,
|
||||||
|
imageUrl: 'images/wip.jpg',
|
||||||
|
description: `
|
||||||
|
<h2>Lanner Electronics</h2>
|
||||||
|
<p>Wip.</p>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 4️⃣ Populate the company list
|
||||||
|
const listEl = document.getElementById('company-list');
|
||||||
|
companies.forEach((company, idx) => {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.textContent = company.name;
|
||||||
|
btn.id = company.id;
|
||||||
|
btn.addEventListener('click', () => selectCompany(idx));
|
||||||
|
listEl.appendChild(btn);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Holder for mapboxgl.Marker instances
|
||||||
|
const markers = [];
|
||||||
|
|
||||||
|
// Reference to the .map-wrapper for our fixed popups
|
||||||
|
const mapWrapper = document.querySelector('.map-wrapper');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a fixed-position popup (does not move with the map)
|
||||||
|
*/
|
||||||
|
function showFixedPopup(company, [lng, lat]) {
|
||||||
|
// Remove any existing fixed popups
|
||||||
|
document.querySelectorAll('.fixed-popup').forEach(el => el.remove());
|
||||||
|
|
||||||
|
// Build the popup element
|
||||||
|
const popupEl = document.createElement('div');
|
||||||
|
popupEl.className = 'fixed-popup';
|
||||||
|
popupEl.innerHTML = `
|
||||||
|
<img
|
||||||
|
loading="lazy"
|
||||||
|
src="${company.imageUrl}"
|
||||||
|
alt="Me at ${company.name}" />
|
||||||
|
<strong>${company.name}</strong>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Attach into the map wrapper (above the map canvas)
|
||||||
|
mapWrapper.appendChild(popupEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles company selection:
|
||||||
|
* - cleans up old markers/popups
|
||||||
|
* - flies the map
|
||||||
|
* - updates the blurb
|
||||||
|
* - adds marker + fixed popup (if not overview)
|
||||||
|
*/
|
||||||
|
function selectCompany(index) {
|
||||||
|
const { coords, zoom, description, id } = companies[index];
|
||||||
|
const [lat, lng] = coords;
|
||||||
|
|
||||||
|
// Remove existing markers
|
||||||
|
markers.forEach(m => m.remove());
|
||||||
|
markers.length = 0;
|
||||||
|
|
||||||
|
// Remove any existing popups
|
||||||
|
document.querySelectorAll('.mapboxgl-popup, .fixed-popup').forEach(el => el.remove());
|
||||||
|
|
||||||
|
// Fly to the new location
|
||||||
|
map.flyTo({
|
||||||
|
center: [lng, lat],
|
||||||
|
zoom,
|
||||||
|
speed: 1.5,
|
||||||
|
essential: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update the description blurb
|
||||||
|
document.getElementById('blurb').innerHTML = description;
|
||||||
|
|
||||||
|
// Highlight the active button
|
||||||
|
document.querySelectorAll('.company-list button')
|
||||||
|
.forEach(b => b.classList.toggle('active', b.id === id));
|
||||||
|
|
||||||
|
// If it's the overview, skip marker + popup
|
||||||
|
if (index === 0) return;
|
||||||
|
|
||||||
|
// Add a marker
|
||||||
|
const marker = new mapboxgl.Marker()
|
||||||
|
.setLngLat([lng, lat])
|
||||||
|
.addTo(map);
|
||||||
|
markers.push(marker);
|
||||||
|
|
||||||
|
// Show our custom fixed popup
|
||||||
|
showFixedPopup(companies[index], [lng, lat]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize on load with the overview
|
||||||
|
selectCompany(0);
|
||||||
59
script/scroll.js
Normal file
59
script/scroll.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// scroll.js
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
// 1) Vertical “zoom‑in/out” on .scroll‑section using IntersectionObserver
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
const sections = document.querySelectorAll('.scroll-section');
|
||||||
|
const io = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
entry.target.classList.toggle('in-view', entry.isIntersecting);
|
||||||
|
});
|
||||||
|
}, { threshold: 0.15 });
|
||||||
|
sections.forEach(sec => io.observe(sec));
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
// 2) Horizontal‑scroll “pin & pan” for the Hobbies section
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
const wrapper = document.getElementById('hobbies');
|
||||||
|
if (!wrapper) return; // no Hobbies section → exit
|
||||||
|
|
||||||
|
// The element that will stay stuck in the viewport:
|
||||||
|
const stickySection = wrapper.querySelector('.horizontal-section');
|
||||||
|
// The inner flex row we translate left/right:
|
||||||
|
const inner = stickySection.querySelector('.horizontal-section__inner');
|
||||||
|
|
||||||
|
// A) Make the section itself “sticky” at the top of the viewport
|
||||||
|
stickySection.style.position = 'sticky';
|
||||||
|
stickySection.style.top = '3rem';
|
||||||
|
stickySection.style.height = '100vh';
|
||||||
|
stickySection.style.overflow = 'hidden';
|
||||||
|
|
||||||
|
// B) Compute how far we need to scroll to reveal all cards
|
||||||
|
let containerW = wrapper.clientWidth; // e.g. 70vw in px
|
||||||
|
let scrollableDist = inner.scrollWidth - containerW; // total horizontal span minus one screen
|
||||||
|
|
||||||
|
// C) Stretch the wrapper’s vertical height so that
|
||||||
|
// scrolling wrapperHeight(px) → moving inner by scrollableDist(px)
|
||||||
|
wrapper.style.height = `${window.innerHeight + scrollableDist}px`;
|
||||||
|
|
||||||
|
// D) On scroll, when within the wrapper’s “pin zone,”
|
||||||
|
// translate the inner row instead of moving vertically
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
const y = window.scrollY;
|
||||||
|
const top = wrapper.offsetTop;
|
||||||
|
const end = top + scrollableDist;
|
||||||
|
|
||||||
|
if (y >= top && y <= end) {
|
||||||
|
// map vertical scroll → horizontal translate
|
||||||
|
inner.style.transform = `translateX(-${y - top}px)`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// E) Recompute on resize
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
containerW = wrapper.clientWidth;
|
||||||
|
scrollableDist = inner.scrollWidth - containerW;
|
||||||
|
wrapper.style.height = `${window.innerHeight + scrollableDist}px`;
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user