# CLAUDE.md - Globe Visualization 6 Development Context ## Project Overview This is **Iteration 6** in a progressive Mapbox GL JS learning series. Each iteration builds upon previous learnings while introducing new techniques from web research. This iteration focuses on **interactive filtering and UI controls** for data exploration. ## Development Assignment **Task**: Create an interactive globe visualization demonstrating advanced filtering techniques learned from Mapbox documentation. **Theme**: Global University Rankings & Research Output - 120 top research universities worldwide - Multi-dimensional data: ranking, publications, citations, funding, Nobel prizes - Interactive filtering by region and research metrics - Real-time statistics dashboard ## Web Research Integration **Source**: Mapbox GL JS Filter Markers Example **URL**: https://docs.mapbox.com/mapbox-gl-js/example/filter-markers/ ### Techniques Extracted from Web Source: #### 1. Core Filtering Method ```javascript // From web source - basic pattern map.setLayoutProperty(layerID, 'visibility', checked ? 'visible' : 'none'); // Enhanced approach learned map.setFilter('layer-id', filterExpression); ``` The web source demonstrated layer visibility toggling. I learned the more sophisticated `setFilter()` approach which filters features within a layer rather than hiding the entire layer. #### 2. Filter Expression Syntax ```javascript // From web source - equality filter ['==', 'icon', symbol] // My applications ['==', 'region', selectedRegion] // Equality ['<=', ['get', 'ranking'], maxRank] // Less than or equal ['>=', ['get', 'publications'], minPubs] // Greater than or equal ['in', ['get', 'region'], ['literal', regions]] // Multiple values ``` #### 3. Checkbox UI Pattern ```javascript // From web source checkbox.addEventListener('change', (e) => { map.setLayoutProperty( layerID, 'visibility', e.target.checked ? 'visible' : 'none' ); }); // My adaptation checkbox.addEventListener('change', () => { updateFilterState(); applyFilters(); }); ``` #### 4. Feature Property Access ```javascript // Learned pattern for accessing feature properties in expressions ['get', 'propertyName'] // Retrieves property value from feature ``` ### My Enhancements Beyond Web Source: 1. **Compound Filter Expressions**: - Used `all` operator to combine multiple filter conditions - Implemented range filtering with `>=` and `<=` - Multi-value filtering with `in` and `literal` 2. **Range Sliders**: - Extended beyond checkboxes to continuous controls - Real-time value display and updates - Multiple independent metric thresholds 3. **Filter Coordination**: - Mutual exclusivity for "All" vs specific regions - State management across 6 filter dimensions - Reset functionality restoring all defaults 4. **Statistics Calculation**: - Query rendered features after filtering - Aggregate calculations (sum, average) - Live dashboard updates 5. **Multi-Layer Filtering**: - Coordinated filters across universities and labels layers - Maintained label visibility rules while respecting filters ## Technical Implementation Details ### Filter Architecture **Filter State Object**: ```javascript let currentFilters = { regions: ['all'], // Selected regions rankingRange: [1, 120], // Min/max ranking minPublications: 0, // Publication threshold minCitations: 0, // Citation threshold minFunding: 0, // Funding threshold minNobelPrizes: 0 // Nobel prize threshold }; ``` **Filter Expression Builder**: ```javascript function applyFilters() { let filterExpression = ['all']; // AND combiner // Region filter (OR within selected) if (!selectedRegions.includes('all')) { filterExpression.push([ 'in', ['get', 'region'], ['literal', selectedRegions] ]); } // Ranking filter filterExpression.push(['<=', ['get', 'ranking'], maxRank]); // Metric thresholds if (minPubs > 0) { filterExpression.push(['>=', ['get', 'publications'], minPubs]); } // Apply to layer map.setFilter('universities-layer', filterExpression); // Update statistics updateStatistics(); } ``` ### UI Control Implementation **Checkbox Filters** (7 regions): ```javascript regions.forEach((region, index) => { const checkbox = createElement('input', { type: 'checkbox', id: `region-${index}`, value: region, checked: region === 'All' }); checkbox.addEventListener('change', () => { // Handle "All" mutual exclusivity if (region === 'All' && checkbox.checked) { uncheckOtherRegions(); } else if (checkbox.checked) { uncheckAll(); } applyFilters(); }); }); ``` **Range Sliders** (5 metrics): ```javascript slider.addEventListener('input', (e) => { const value = parseInt(e.target.value); currentFilters.metric = value; displayElement.textContent = formatValue(value); applyFilters(); // Immediate update }); ``` ### Statistics Dashboard **Query Filtered Features**: ```javascript function updateStatistics() { const features = map.queryRenderedFeatures({ layers: ['universities-layer'] }); const stats = { count: features.length, avgResearch: average(features, 'researchScore'), totalPubs: sum(features, 'publications'), totalCitations: sum(features, 'citations'), totalNobel: sum(features, 'nobelPrizes') }; updateDashboard(stats); } ``` This queries only the currently visible (filtered) features, enabling real-time statistics that update with every filter change. ## Data Structure ### University Data Model ```javascript { type: "Feature", geometry: { type: "Point", coordinates: [longitude, latitude] }, properties: { name: "University Name", country: "Country", region: "Region", ranking: 1-120, // Global position publications: 5500-19800, // Annual papers citations: 122000-456000, // Total citations funding: 400-4200, // Annual funding ($M) nobelPrizes: 0-161, // Total Nobel laureates researchScore: 55-99 // Composite score } } ``` ### Data Coverage **120 Universities Across 6 Regions**: - North America: 27 (USA, Canada) - Europe: 25 (UK, Germany, France, Switzerland, etc.) - Asia-Pacific: 42 (China, Japan, Singapore, Australia, India, etc.) - Middle East: 9 (Israel, Qatar, UAE, Saudi Arabia, Turkey) - Africa: 6 (South Africa, Egypt, Kenya, Nigeria) - Latin America: 11 (Brazil, Argentina, Chile, Mexico, Colombia) **Data Realism**: - Rankings based on major global university rankings - Publications scaled to realistic annual output - Citations reflect cumulative academic impact - Funding approximates actual research budgets - Nobel prizes are historically accurate ### Metric Distributions - **Research Score**: 55-99 (composite excellence measure) - **Publications**: 5,500-19,800 (annual research output) - **Citations**: 122,000-456,000 (total academic citations) - **Funding**: $400M-$4,200M (annual research funding) - **Nobel Prizes**: 0-161 (total affiliated laureates) ## Visual Design System ### Color Scheme - Research Excellence 8-stop gradient from deep red (emerging) to royal blue (exceptional): ```javascript 'circle-color': [ 'interpolate', ['linear'], ['get', 'researchScore'], 55, '#8b0000', // Deep red 65, '#dc143c', // Crimson 75, '#ff6347', // Tomato 80, '#ffa500', // Orange 85, '#ffd700', // Gold 90, '#32cd32', // Lime green 95, '#00bfff', // Deep sky blue 99, '#0066ff' // Royal blue ] ``` ### Size Encoding - Ranking Position Inverse relationship (better rank = larger circle): ```javascript 'circle-radius': [ 'interpolate', ['linear'], ['get', 'ranking'], 1, 18, // Top rank 10, 14, 25, 11, 50, 9, 75, 7, 100, 5, 120, 4 // Lower rank ] ``` ### Stroke Styling Dynamic stroke color matches research score: ```javascript 'circle-stroke-color': [ 'interpolate', ['linear'], ['get', 'researchScore'], 55, '#ff4444', // Red 80, '#ffaa00', // Orange 95, '#00ffff' // Cyan ] ``` ## Globe Configuration ### Atmosphere Settings ```javascript map.setFog({ color: 'rgba(8, 16, 32, 0.95)', // Dark base 'high-color': 'rgba(25, 60, 120, 0.5)', // Blue horizon 'horizon-blend': 0.3, // Blend distance 'space-color': '#000510', // Deep space 'star-intensity': 0.7 // Star brightness }); ``` ### Auto-Rotation ```javascript let userInteracting = false; function rotateGlobe() { if (!userInteracting && !rotationPaused) { const center = map.getCenter(); center.lng += 0.05; // Slow rotation map.setCenter(center); } requestAnimationFrame(rotateGlobe); } ``` Pauses during user interaction, resumes when idle. ## UI/UX Design Patterns ### Glassmorphism Theme ```css .panel { background: rgba(0, 0, 0, 0.9); backdrop-filter: blur(15px); border: 1px solid rgba(255, 255, 255, 0.15); } ``` Creates semi-transparent panels with blur effect for modern aesthetic. ### Responsive Layout **Desktop**: - Controls panel: Right side - Statistics: Bottom left - Legend: Bottom right - Title: Top center **Mobile** (< 768px): - Controls: Bottom overlay (scrollable) - Statistics: Top left (compact) - Legend: Hidden - Title: Reduced size ### Interactive Feedback - Slider values update in real-time - Statistics dashboard refreshes with filters - Hover popups show detailed metrics - Cursor changes on interactive elements - Smooth transitions on all updates ## Performance Considerations ### Efficient Filtering - **No data reloading**: Filters operate on existing source - **Expression-based**: Computed on GPU where possible - **Debounced updates**: Statistics calculated after filter application - **Feature querying**: Only visible features processed ### Optimized Rendering - **Single data source**: All 120 universities in one GeoJSON - **Layer reuse**: Same source for circles and labels - **Conditional labels**: Only top 30 show text - **Stroke width**: Modest 2px to reduce overdraw ### Memory Management - **Static data**: Universities loaded once - **No data duplication**: Filters reference same source - **Minimal DOM**: Controls generated once - **Event delegation**: Where possible ## Validation Checklist - [x] Uses Mapbox GL JS v3.0.1 - [x] Globe projection enabled - [x] Atmosphere effects configured - [x] 120 universities with accurate coordinates - [x] 6 data metrics per university - [x] Region checkbox filters (7 options) - [x] Ranking range slider - [x] 4 metric threshold sliders - [x] Compound filter expressions with `all`, `in`, `>=`, `<=` - [x] Real-time statistics dashboard - [x] Interactive popups with full details - [x] Reset filters functionality - [x] Pause/resume rotation control - [x] Top 30 university labels - [x] 8-stop color gradient for research scores - [x] Inverse size scaling for rankings - [x] Auto-rotation with interaction pause - [x] Responsive design (desktop & mobile) - [x] Web source attribution in README ## Learning Outcomes **Completing this iteration demonstrates understanding of**: 1. **Filter Expressions**: Syntax and composition with Mapbox expressions 2. **Dynamic Filtering**: Real-time layer updates with `setFilter()` 3. **Compound Conditions**: Using `all`, `in`, `>=`, `<=` operators 4. **UI Controls**: Checkboxes and sliders for filter input 5. **Feature Querying**: `queryRenderedFeatures()` for statistics 6. **State Management**: Coordinating multiple filter dimensions 7. **Interactive Exploration**: User-driven data discovery 8. **Real-time Updates**: Synchronizing UI, filters, and statistics 9. **Filter Coordination**: Multiple layers with shared filter logic 10. **Practical Application**: Adapting web examples to complex use cases ## Progressive Learning Demonstrated **Building on Previous Iterations**: - **Iter 1**: Basic globe setup, circle layers - **Iter 2**: Color gradients, visual styling - **Iter 3**: Data-driven expressions - **Iter 4**: Multi-layer composition - **Iter 6**: Interactive filtering & exploration ← **Current** **New Capabilities Added**: - Multi-criteria filtering system - Checkbox and slider UI controls - Compound filter expressions - Real-time statistics calculation - Coordinated filter state management - Reset and rotation control **Synthesis Achievement**: Combines visual techniques (Iter 1-3), layer composition (Iter 4), and interactive controls (Iter 6) into a comprehensive data exploration tool. ## Development Notes ### Filter Expression Best Practices 1. **Use `all` for AND logic**: Combine multiple conditions 2. **Use `in` for OR logic**: Match any of multiple values 3. **Use `literal` for arrays**: Wrap array values in filter expressions 4. **Use `get` for properties**: Access feature properties safely 5. **Order matters**: Put most selective filters first for performance ### Common Pitfalls Avoided - ❌ Reloading data on filter change (inefficient) - ✅ Using `setFilter()` on existing source (efficient) - ❌ Hiding entire layer with visibility (limited flexibility) - ✅ Filtering features within layer (precise control) - ❌ Calculating statistics from raw data (inaccurate) - ✅ Querying rendered features (matches visible state) - ❌ Conflicting filter states (confusing UX) - ✅ Coordinated state management (clear behavior) ### Extension Opportunities **Future enhancements**: - Animated transitions between filter states - Saved filter presets (e.g., "Elite Tier", "High Impact") - Export filtered data to CSV/JSON - Comparison mode (before/after filtering) - URL parameters for shareable filtered views - Multi-map views showing different filter perspectives - 3D extrusions for research output metrics - Connection lines between collaborating institutions ## Files Created 1. **index.html** - Main visualization with complete UI 2. **src/index.js** - Filtering logic and interactivity 3. **src/data/data.js** - 120 universities with 6 metrics each 4. **README.md** - Comprehensive documentation 5. **CLAUDE.md** - This development context file ## Local Development ### Running the Visualization ```bash # Option 1: Python 3 python3 -m http.server 8000 # Option 2: Python 2 python -m SimpleHTTPServer 8000 # Option 3: Node.js npx http-server -p 8000 # Option 4: PHP php -S localhost:8000 ``` Then open: http://localhost:8000 ### Browser Requirements - Modern browser with WebGL support - Recommended: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+ - Minimum screen resolution: 1024x768 ### Testing Checklist - [ ] Globe renders with atmosphere - [ ] 120 universities visible on load - [ ] Region checkboxes filter correctly - [ ] "All" checkbox mutual exclusivity works - [ ] All 5 sliders update filters in real-time - [ ] Statistics dashboard shows correct values - [ ] Hover popups display university details - [ ] Labels appear for top 30 only - [ ] Reset button restores all defaults - [ ] Pause rotation button toggles correctly - [ ] Auto-rotation works and pauses on interaction - [ ] Responsive layout on mobile (< 768px) --- *This iteration successfully demonstrates mastery of Mapbox filtering techniques learned from official documentation, applied to a comprehensive research dataset with sophisticated multi-dimensional exploration capabilities.*