xiaohongshu
xiaohongshu
d3-geo
Use when creating maps, working with geographic projections, or processing GeoJSON data. Invoke for world maps, choropleth maps, projection types, geo path generators, spherical geometry, or geographic feature manipulation.
Full skill instructions
Expert knowledge of D3's geographic projections and map rendering. Covers map projections, GeoJSON processing, geographic path generators, spherical geometry, and cartographic features.
Invoke this skill when:
Location: /Users/zach/Documents/cc-skills/docs/d3/
Coverage (266 files):
Core Geography (91 files):
Projections (151 files):
Polygon Operations (24 files):
Question: "How do I create a simple world map?"
Response:
import * as d3 from 'd3';
// Load GeoJSON data
const worldData = await d3.json('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json');
// Convert TopoJSON to GeoJSON
const countries = topojson.feature(worldData, worldData.objects.countries);
// Create projection
const projection = d3.geoNaturalEarth1()
.scale(200)
.translate([400, 300]); // Center of SVG
// Create path generator
const path = d3.geoPath()
.projection(projection);
// Create SVG
const svg = d3.create('svg')
.attr('width', 800)
.attr('height', 600);
// Draw countries
svg.selectAll('path')
.data(countries.features)
.join('path')
.attr('d', path)
.attr('fill', '#ccc')
.attr('stroke', '#fff')
.attr('stroke-width', 0.5);
// Add graticule (grid lines)
const graticule = d3.geoGraticule();
svg.append('path')
.datum(graticule())
.attr('d', path)
.attr('fill', 'none')
.attr('stroke', '#ddd')
.attr('stroke-width', 0.5);
// Add sphere outline
svg.append('path')
.datum({ type: 'Sphere' })
.attr('d', path)
.attr('fill', 'none')
.attr('stroke', '#000')
.attr('stroke-width', 1.5);
Auto-fit projection to data:
const projection = d3.geoNaturalEarth1()
.fitSize([800, 600], countries);
References:
docs/d3/geo/path.mddocs/d3/geo-projection/Question: "How do I create a choropleth map with state-level data?"
Response:
import * as d3 from 'd3';
// Load US states TopoJSON
const us = await d3.json('https://cdn.jsdelivr.net/npm/us-atlas@3/states-10m.json');
const states = topojson.feature(us, us.objects.states);
// Sample data (state ID -> value)
const data = new Map([
['01', 45], // Alabama
['06', 82], // California
['36', 68], // New York
// ... more states
]);
// Create projection optimized for US
const projection = d3.geoAlbersUsa()
.scale(1000)
.translate([400, 300]);
const path = d3.geoPath()
.projection(projection);
// Create color scale
const colorScale = d3.scaleSequential()
.domain([0, 100])
.interpolator(d3.interpolateBlues);
// Create SVG
const svg = d3.create('svg')
.attr('width', 800)
.attr('height', 600);
// Draw states
svg.selectAll('path')
.data(states.features)
.join('path')
.attr('d', path)
.attr('fill', d => {
const value = data.get(d.id);
return value ? colorScale(value) : '#ccc';
})
.attr('stroke', '#fff')
.attr('stroke-width', 0.5)
.on('mouseenter', function(event, d) {
d3.select(this)
.attr('stroke', '#000')
.attr('stroke-width', 2);
// Show tooltip
const value = data.get(d.id);
console.log(`${d.properties.name}: ${value}`);
})
.on('mouseleave', function() {
d3.select(this)
.attr('stroke', '#fff')
.attr('stroke-width', 0.5);
});
// Add legend
const legendWidth = 300;
const legendHeight = 10;
const legend = svg.append('g')
.attr('transform', 'translate(250, 550)');
// Create gradient for legend
const defs = svg.append('defs');
const gradient = defs.append('linearGradient')
.attr('id', 'legend-gradient');
gradient.selectAll('stop')
.data(d3.range(0, 1.1, 0.1))
.join('stop')
.attr('offset', d => `${d * 100}%`)
.attr('stop-color', d => colorScale(d * 100));
legend.append('rect')
.attr('width', legendWidth)
.attr('height', legendHeight)
.style('fill', 'url(#legend-gradient)');
// Add legend axis
const legendScale = d3.scaleLinear()
.domain([0, 100])
.range([0, legendWidth]);
const legendAxis = d3.axisBottom(legendScale)
.ticks(5);
legend.append('g')
.attr('transform', `translate(0, ${legendHeight})`)
.call(legendAxis);
Albers USA Projection:
References:
docs/d3/geo-projection/albers-usa.mdQuestion: "How do I create a draggable globe?"
Response:
import * as d3 from 'd3';
// Load world data
const world = await d3.json('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json');
const countries = topojson.feature(world, world.objects.countries);
// Create orthographic projection (globe)
const projection = d3.geoOrthographic()
.scale(250)
.translate([400, 300])
.rotate([0, 0]); // [longitude, latitude, roll]
const path = d3.geoPath()
.projection(projection);
// Create SVG
const svg = d3.create('svg')
.attr('width', 800)
.attr('height', 600);
// Add ocean (sphere background)
svg.append('path')
.datum({ type: 'Sphere' })
.attr('class', 'ocean')
.attr('d', path)
.attr('fill', '#a8d5ff');
// Add countries
const countriesGroup = svg.append('g')
.selectAll('path')
.data(countries.features)
.join('path')
.attr('d', path)
.attr('fill', '#bbb')
.attr('stroke', '#fff')
.attr('stroke-width', 0.5);
// Add graticule
const graticule = d3.geoGraticule();
svg.append('path')
.datum(graticule())
.attr('d', path)
.attr('fill', 'none')
.attr('stroke', '#ccc')
.attr('stroke-width', 0.5)
.attr('opacity', 0.5);
// Add drag behavior
const drag = d3.drag()
.on('start', function(event) {
// Store starting rotation
this._rotation = projection.rotate();
this._coords = [event.x, event.y];
})
.on('drag', function(event) {
const rotation = this._rotation;
const coords = this._coords;
// Calculate rotation delta
const dx = event.x - coords[0];
const dy = event.y - coords[1];
// Update projection rotation
projection.rotate([
rotation[0] + dx * 0.5,
rotation[1] - dy * 0.5,
]);
// Re-render
svg.selectAll('path').attr('d', path);
});
svg.call(drag);
// Add zoom behavior
const zoom = d3.zoom()
.scaleExtent([0.5, 5])
.on('zoom', (event) => {
projection.scale(250 * event.transform.k);
svg.selectAll('path').attr('d', path);
});
svg.call(zoom);
Other 3D Projections:
geoOrthographic() - Globe viewgeoStereographic() - Perspective from pointgeoGnomonic() - Great circles as straight linesReferences:
docs/d3/geo-projection/orthographic.mdQuestion: "How do I calculate distances and areas on a sphere?"
Response:
import * as d3 from 'd3';
// Define coordinates [longitude, latitude]
const newYork = [-74.006, 40.7128];
const london = [-0.1278, 51.5074];
const tokyo = [139.6917, 35.6895];
// Calculate great circle distance (in radians)
const distanceRadians = d3.geoDistance(newYork, london);
console.log('Distance (radians):', distanceRadians);
// Convert to kilometers (Earth radius = 6371 km)
const distanceKm = distanceRadians * 6371;
console.log('Distance (km):', distanceKm.toFixed(0)); // ~5,570 km
// Calculate area of polygon (in steradians)
const polygon = {
type: 'Polygon',
coordinates: [[
[-74, 40],
[-73, 40],
[-73, 41],
[-74, 41],
[-74, 40],
]],
};
const areaSteradians = d3.geoArea(polygon);
console.log('Area (steradians):', areaSteradians);
// Convert to square kilometers (Earth surface area = 510M km²)
const areaKm2 = areaSteradians * (6371 * 6371);
console.log('Area (km²):', areaKm2.toFixed(0));
// Calculate path length
const lineString = {
type: 'LineString',
coordinates: [newYork, london],
};
const lengthRadians = d3.geoLength(lineString);
const lengthKm = lengthRadians * 6371;
console.log('Path length (km):', lengthKm.toFixed(0));
// Calculate centroid
const centroid = d3.geoCentroid(polygon);
console.log('Centroid [lon, lat]:', centroid);
// Check if point is inside polygon
const point = [-73.5, 40.5];
const contains = d3.geoContains(polygon, point);
console.log('Contains point:', contains); // true or false
// Interpolate along great circle
const interpolate = d3.geoInterpolate(newYork, london);
console.log('25% along:', interpolate(0.25));
console.log('50% along:', interpolate(0.5));
console.log('75% along:', interpolate(0.75));
// Calculate bounds
const bounds = d3.geoBounds(polygon);
console.log('Bounds [[west, south], [east, north]]:', bounds);
Spherical vs. Planar:
d3.geo* for geographic coordinates (lat/lon)d3.polygon* for projected/screen coordinatesReferences:
docs/d3/geo/distance.mddocs/d3/geo/area.mddocs/d3/geo/centroid.mdQuestion: "How do I configure projection for a specific region?"
Response:
import * as d3 from 'd3';
// Load region data (e.g., Europe)
const europe = await d3.json('europe.geojson');
// Method 1: Manual configuration
const projection1 = d3.geoMercator()
.center([10, 50]) // Center on [lon, lat]
.scale(500)
.translate([400, 300]); // SVG center
// Method 2: Fit to bounds (recommended)
const projection2 = d3.geoMercator()
.fitSize([800, 600], europe);
// Method 3: Fit with padding
const projection3 = d3.geoMercator()
.fitExtent([[20, 20], [780, 580]], europe); // [[x0, y0], [x1, y1]]
// Method 4: Fit width, maintain aspect ratio
const projection4 = d3.geoMercator()
.fitWidth(800, europe);
// Method 5: Fit height, maintain aspect ratio
const projection5 = d3.geoMercator()
.fitHeight(600, europe);
// Projection with rotation
const projection6 = d3.geoMercator()
.rotate([-10, 0, 0]) // [yaw, pitch, roll]
.fitSize([800, 600], europe);
// Set clipping
const projection7 = d3.geoMercator()
.clipAngle(90) // Clip to hemisphere
.fitSize([800, 600], europe);
// Set precision (adaptive sampling)
const projection8 = d3.geoMercator()
.precision(0.1) // Lower = more points, higher quality
.fitSize([800, 600], europe);
// Get projection functions
const path = d3.geoPath(projection2);
// Project coordinate to screen
const [x, y] = projection2([10, 50]); // [lon, lat] -> [x, y]
// Invert screen to coordinate
const [lon, lat] = projection2.invert([400, 300]); // [x, y] -> [lon, lat]
// Check if coordinate is visible
const visible = projection2([10, 50]); // null if clipped
Common Projections:
geoMercator() - Web maps (preserves angles)geoAlbers() - US/Europe maps (preserves area)geoEquirectangular() - Simple lat/lon mappinggeoConicEqualArea() - Regional mapsgeoNaturalEarth1() - World maps (compromise)References:
docs/d3/geo/projection.mddocs/d3/geo-projection/function zoomToFeature(feature) {
const [[x0, y0], [x1, y1]] = path.bounds(feature);
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity
.translate(width / 2, height / 2)
.scale(Math.min(8, 0.9 / Math.max(
(x1 - x0) / width,
(y1 - y0) / height
)))
.translate(-(x0 + x1) / 2, -(y0 + y1) / 2)
);
}
const neighbors = topojson.neighbors(us.objects.states.geometries);
svg.selectAll('path')
.on('mouseenter', function(event, d, i) {
svg.selectAll('path')
.filter((_, j) => neighbors[i].includes(j))
.attr('fill', 'orange');
});
svg.selectAll('text')
.data(countries.features)
.join('text')
.attr('transform', d => {
const [x, y] = path.centroid(d);
return `translate(${x}, ${y})`;
})
.attr('text-anchor', 'middle')
.text(d => d.properties.name);
# Find projection docs
grep -r "projection\|geoMercator\|geoAlbers" /Users/zach/Documents/cc-skills/docs/d3/geo-projection/
# Find path generator docs
grep -r "geoPath\|path.area\|path.bounds" /Users/zach/Documents/cc-skills/docs/d3/geo/
# Find spherical math docs
grep -r "geoDistance\|geoArea\|geoCentroid" /Users/zach/Documents/cc-skills/docs/d3/geo/
# Find clipping docs
grep -r "clip\|rotate" /Users/zach/Documents/cc-skills/docs/d3/geo/
# List projection types
ls /Users/zach/Documents/cc-skills/docs/d3/geo-projection/
Map not centered: Use .fitSize() instead of manual scale/translate
projection.fitSize([width, height], geoJSON)Countries upside down: Y coordinates in wrong direction
Dateline artifacts: Features crossing 180° longitude
Performance issues: Too many vertices
Projection returns null: Coordinate outside clip bounds
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience