Published
Edited
Oct 22, 2021
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mutable stage = {
var stage = (app.stage = new PIXI.Container());
invalidation.then(() => {
stage.destroy();
});

stage.addChild(map);
stage.interactive = true;
var centerOffsetX = width / 2 - map.width / 2;
var centerOffsetY = 20;
map.position.x = centerOffsetX;
map.position.y = centerOffsetY;

////////////
/// ZOOM ///
////////////

var zoom = d3
.zoom()
.scaleExtent([1, 30])
.on('start', function() {
mutable zooming = true;
})
.on('zoom', function() {
var e = d3.event.transform;
map.scale.x = map.scale.y = e.k;
map.position.x = e.x + centerOffsetX * e.k;
map.position.y = e.y + centerOffsetY * e.k;
})
.on('end', function() {
mutable zooming = false;
});
d3.select(app.view).call(zoom);

return stage;
}
Insert cell
map = {
var map = new PIXI.Container();

// Create containers for 3 maps https://pixijs.download/dev/docs/PIXI.Container.html
var map_container1 = new PIXI.Container();
var map_container2 = new PIXI.Container();
var map_container3 = new PIXI.Container();

map_container2.position.x = map_width; //offset
map_container3.position.x = map_width * 2; //offset

// Set up interactive areas for tooltip
map_container1.interactive = true;
map_container1.hitArea = new PIXI.Rectangle(0, 0, map_width, map_height);
map_container2.interactive = true;
map_container2.hitArea = new PIXI.Rectangle(0, 0, map_width, map_height);
map_container3.interactive = true;
map_container3.hitArea = new PIXI.Rectangle(0, 0, map_width, map_height);

////////////////
// Draw paths //
////////////////

var graphics = new PIXI.Graphics();
var graphics2 = new PIXI.Graphics();
var graphics3 = new PIXI.Graphics();

let path1 = d3.geoPath(projection, graphics);
let path2 = d3.geoPath(projection, graphics2);
let path3 = d3.geoPath(projection, graphics3);

graphics.beginFill(0x66CCFF, 0.15);
path1(data);
graphics.endFill();

graphics2.beginFill(0x66CCFF, 0.15);
path2(data);
graphics2.endFill();
graphics2.blendMode = PIXI.BLEND_MODES.MULTIPLY; // apply multiply blendmode to map 2

graphics3.beginFill(0x66CCFF, 0.15);
path3(data);
graphics3.endFill();

////////////
// Shader //
////////////

// Create a texture for the colour scale (from canvas image 'color_ramp')
// A texture stores the information that represents an image
let color_ramp_texture = PIXI.Texture.fromCanvas(color_ramp);

// Assign the uniforms data to pass to the shader
const uniformsData = {
u_color_ramp: {
type: 'sampler2D',
value: color_ramp_texture
}
};

let shader = new PIXI.Filter('', fragment_shader, uniformsData);
map_container1.filters = [shader]; // apply the shader

map.addChild(map_container1);
map_container1.addChild(graphics);
map.addChild(map_container2);
map_container2.addChild(graphics2);
map.addChild(map_container3);
map_container3.addChild(graphics3);

/////////////
// TOOLTIP //
/////////////

var mouseIn_1 = false,
mouseIn_2 = false,
mouseIn_3 = false;

map_container1.on('mouseover', () => (mouseIn_1 = true));
map_container1.on('mouseout', () => (mouseIn_1 = false));
map_container1.on('mousemove', onHover1);

map_container2.on('mouseover', () => (mouseIn_2 = true));
map_container2.on('mouseout', () => (mouseIn_2 = false));
map_container2.on('mousemove', onHover2);

map_container3.on('mouseover', () => (mouseIn_3 = true));
map_container3.on('mouseout', () => (mouseIn_3 = false));
map_container3.on('mousemove', onHover3);

function onHover1(event) {
if (mouseIn_1) getOverlaps(event);
}

function onHover2(event) {
if (mouseIn_2) getOverlaps(event, map_width);
}

function onHover3(event) {
if (mouseIn_3) getOverlaps(event, map_width * 2);
}

function getOverlaps(event, offset = 0) {
let hoverx = event.data.global.x,
hovery = event.data.global.y;

// get hoverx and hovery relative to the PIXI container zoom
let hoverx_relative = (hoverx - map.position.x) / map.scale.x - offset,
hovery_relative = (hovery - map.position.y) / map.scale.y;

// map from x y back to lat lng
let [hover_lng, hover_lat] = projection.invert([
hoverx_relative,
hovery_relative
]);
// use polygon lookup https://github.com/pelias/polygon-lookup to get the point-in-polygon intersections
let hover_data = lookup.search(hover_lng, hover_lat, -1);

// number of overlaps
mutable clickedSheet = hover_data.features.length;
}

return map;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Create SVG element for tooltip
mutable svg = html`<svg id="tooltip_svg" width=${width} height=700 style="position: fixed; pointer-events:none;"><g id="tooltip" style="display:block;"></g></svg>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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