Published
Edited
Aug 31, 2020
1 fork
2 stars
Insert cell
md`# World Map under a Dot Plot

### Step 1: Create a dot plot

### Step 2: Create a map

### Step 3: linkVertical to the points together`
Insert cell
md `# Plot Universe Stuff`
Insert cell
margin = ({top:20, right:30, bottom: 20, left: 30})
Insert cell
height = 150 + margin.top
Insert cell
width = 1000
Insert cell
mapPoints = {
// how does DOM.svg differ from d3.create("svg")
const svg = d3.select(DOM.svg(width, width/1.6 + height));

// STEP 1: make the dot plot
const dots = svg.append("g");
dots.selectAll('circle')
.data(dataset)
.join("circle")
.attr("r", 10)
.attr("cx", d => xScale(d.chapter))
.attr("cy", d => height - margin.bottom - (d.groupId * 22))
.attr("fill", d => colorScale(colorAccessor(d)))
dots.append("g")
.style("color", "black")
.call(xAxis)
// APPEND TEXT? IF WE WANT?
.append("text")
.attr("x", margin.left + 15)
.attr("y", margin.bottom + 5)
.attr("fill", "black")
.html("Chapter")
// STEP 2 ADD THE MAP

// now we use the "range" we specified and project it onto our "domain"
const path = d3.geoPath()
.projection(projection);
// create a second group for the map
const map = svg.append("g");

// bind the map to our svg given the above
map.selectAll("path")
.data(topojson.feature(world, world.objects.countries).features)
.enter()
.append("path")
.attr("d", path)
.style('fill', 'white')
.style('stroke', 'black')
// add circles to the points on the map
map
.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
// map the circles onto the projection
// just not projecting correctly
.attr("transform", function(d) {
return "translate(" + projection([
d.long,
d.lat
]) + ")";
});
// STEP 3 ADD PATHS
svg.selectAll("paths")
.data(linksWithTypes)
.enter()
.append("path")
.attr('d', d => d.node)
.attr('stroke', d => colorScale(d.type))
.attr('fill', 'none');
return svg.node();
}
Insert cell
md `# Scales for dot plot`
Insert cell
xScale = d3.scaleLinear()
.domain(d3.extent(dataset, d => d.chapter))
.range([margin.left + 80, width - margin.right - margin.left ])
Insert cell
xAxisTicks = xScale.ticks()
.filter(tick => Number.isInteger(tick));
Insert cell
xAxis = g => g
.attr("transform", `translate(0, ${height - margin.bottom + 20})`)
.style("font-size", "1.4em")
.call(d3.axisBottom(xScale)
.tickValues(xAxisTicks)
.tickFormat(d3.format('d')))
Insert cell
md `# Color Scale`
Insert cell
colorAccessor = d => d.type
Insert cell
colorScale = d3.scaleOrdinal()
.domain(d3.extent(dataset, d => d.type))
.range(["#00AED5", "#F29904", "#017101"]);
Insert cell
md `# Data
Raw data, adding sequence per chapter, and turning lat long and dot plot into nodes we can use for lines`
Insert cell
world = d3.json('https://gist.githubusercontent.com/olemi/d4fb825df71c2939405e0017e360cd73/raw/d6f9f0e9e8bd33183454250bd8b808953869edd2/world-110m2.json')
Insert cell
// create a sequential group of numbers for each chapter
function getIds(data) {
const counterMap = new Map();
let res = data.map((val) => {
const previousGroupId = counterMap.get(val.chapter);
let groupId;
if (previousGroupId === undefined) {
groupId = 1;
} else {
groupId = previousGroupId + 1;
}
counterMap.set(val.chapter, groupId);
return {
chapter: val.chapter,
type: val.type,
groupId: groupId,
long: val.long,
lat: val.lat,
};
});
return res
}
Insert cell
dataset = getIds([
{chapter: 1, type: "a", lat: 26.8206, long: 30.8025},
{chapter: 1, type: "b", lat: 37.0902 , long: -95.7129},
{chapter: 1, type: "b", lat: 15.8700, long: 100.9925},
{chapter: 1, type: "a", lat: 4.8604, long: 58.9302},
{chapter: 1, type: "a", lat: 0.0236, long: 37.9062},
{chapter: 1, type: "c", lat: 18.1096, long: 77.2975},
{chapter: 2, type: "c", lat: 6.4281, long: 9.4295},
{chapter: 2, type: "a", lat: 26.8206, long: 30.8025},
{chapter: 2, type: "a", lat: 37.0902 , long: -95.7129},
{chapter: 3, type: "a", lat: 15.8700, long: 100.9925},
{chapter: 3, type: "a", lat: 4.8604, long: 58.9302},
{chapter: 4, type: "b", lat: 0.0236, long: 37.9062},
{chapter: 4, type: "b", lat: 18.1096, long: 77.2975},
{chapter: 4, type: "a", lat: 6.4281, long: 9.4295},
{chapter: 4, type: "a", lat: 26.8206, long: 30.8025},
{chapter: 4, type: "b", lat:37.0902 , long: -95.7129},
{chapter: 4, type: "c", lat: 15.8700, long: 100.9925},
{chapter: 5, type: "c", lat: 4.8604, long: 58.9302},
{chapter: 5, type: "a", lat: 0.0236, long: 37.9062},
{chapter: 5, type: "b", lat: 18.1096, long: 77.2975},
{chapter: 5, type: "b", lat: 6.4281, long: 9.4295},
{chapter: 5, type: "a", lat: 26.8206, long: 30.8025},
{chapter: 6, type: "a", lat:37.0902 , long: -95.7129},
{chapter: 6, type: "c", lat: 15.8700, long: 100.9925}
])
Insert cell
md `# Map Projection and lines`
Insert cell
projection = d3.geoEqualEarth()
.center([30, 100])
.scale(200)
.rotate([0,0]);
Insert cell
Insert cell
Insert cell
linksWithTypes = makeLinks()
Insert cell
Insert cell
d3 = require('d3@5')
Insert cell
topojson = require('topojson')
Insert cell
Insert cell
// zoom and pan -- dont need but will keep code
/*
const zoom = d3.zoom()
.on("zoom", () => {
g.attr("transform", d3.event.transform);
g.selectAll("circle")
.attr("d", path.projection(projection));
g.selectAll("path")
.attr("d", path.projection(projection));

});
svg.call(zoom)
*/
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more