mapbox+deckgl 类似迁移图( mapbox为主(在线))

效果图:

 

 

<html>
<head>
<title>US County-to-County Migration 类似迁移图</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no'/>

<script src="../lib/mapboxgl/6.4.10.deckgl.min.js"></script>
<script src='../source/v2.6.1/mapbox-gl.js'></script>
<link href='../source/v2.6.1/mapbox-gl.css' rel='stylesheet'/>
<script src="../lib/mapboxgl/d3.v5.min.js"></script>

<style>
body {
width: 100vw;
height: 100vh;
margin: 0;
}
</style>
</head>

<body>
</body>

<script type="text/javascript">
// import test from './chongqing.json'

mapboxgl.accessToken =
'pk.eyJ1IjoiZXRlcm5pdHkteHlmIiwiYSI6ImNqaDFsdXIxdTA1ODgycXJ5czdjNmF0ZTkifQ.zN7e588TqZOQMWfws-K0Yw';

const {MapboxLayer, ArcLayer, ScatterplotLayer} = deck;

const DATA_URL = 'https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/arc/counties.json';
// migrate out
const SOURCE_COLOR = [166, 3, 3];
// migrate in
const TARGET_COLOR = [35, 181, 184];
const RADIUS_SCALE = d3.scaleSqrt().domain([0, 8000]).range([1000, 20000]);
const WIDTH_SCALE = d3.scaleLinear().domain([0, 1000]).range([1, 4]);

const map = new mapboxgl.Map({
container: document.body,
style: 'mapbox://styles/mapbox/light-v9',
center: [-100, 40.7],
// center: [120, 30.7],
// center: [7, 45.7],
zoom: 8
});

let countiesLayer;
let arcsLayer;

map.on('load', () => {
d3.json(DATA_URL).then(loadData);
// d3.json(test).then(loadData);
});

map.on('mousemove', ({point}) => {
if (arcsLayer) {
arcsLayer.setProps({mousePosition: [point.x, point.y]});
}
});

function renderLayers({arcs, counties}) {
countiesLayer = new MapboxLayer({
type: ScatterplotLayer,
id: 'counties',
data: counties,
opacity: 1,
pickable: true,
// onHover: this._onHover,
getRadius: d => RADIUS_SCALE(d.total),
getColor: d => (d.net > 0 ? TARGET_COLOR : SOURCE_COLOR)
});

arcsLayer = new MapboxLayer({
type: ArcBrushingLayer,
id: 'arcs',
data: arcs,
brushRadius: 100000,
getStrokeWidth: d => WIDTH_SCALE(d.value),
opacity: 1,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: SOURCE_COLOR,
getTargetColor: TARGET_COLOR
});

map.addLayer(countiesLayer, 'waterway-label');
map.addLayer(arcsLayer);
}

function loadData(data) {
const arcs = [];
const counties = [];
const pairs = {};

data.features.forEach((county, i) => {
const {flows, centroid: targetCentroid} = county.properties;
const value = {gain: 0, loss: 0};

Object.keys(flows).forEach(toId => {
value[flows[toId] > 0 ? 'gain' : 'loss'] += flows[toId];

const pairKey = i < toId ? `${i}-${toId}` : `${toId}-${i}`;
const sourceCentroid = data.features[toId].properties.centroid;
const gain = Math.sign(flows[toId]);

// eliminate duplicates arcs
if (pairs[pairKey]) {
return;
}

pairs[pairKey] = true;

arcs.push({
target: gain > 0 ? targetCentroid : sourceCentroid,
source: gain > 0 ? sourceCentroid : targetCentroid,
value: Math.abs(flows[toId])
});
});

// add point at arc target
counties.push({
...value,
position: targetCentroid,
net: value.gain + value.loss,
total: value.gain - value.loss,
name: county.properties.name
});
});

// sort counties by radius large -> small
counties.sort((a, b) => Math.abs(b.net) - Math.abs(a.net));

renderLayers({arcs, counties});
}


class ArcBrushingLayer extends ArcLayer {
getShaders() {
// use customized shaders
return Object.assign({}, super.getShaders(), {
inject: {
'vs:#decl': `
uniform vec2 mousePosition;
uniform float brushRadius;
`,
'vs:#main-end': `
float brushRadiusPixels = project_scale(brushRadius);

vec2 sourcePosition = project_position(instancePositions.xy);
bool isSourceInBrush = distance(sourcePosition, mousePosition) <= brushRadiusPixels;

vec2 targetPosition = project_position(instancePositions.zw);
bool isTargetInBrush = distance(targetPosition, mousePosition) <= brushRadiusPixels;

if (!isSourceInBrush && !isTargetInBrush) {
vColor.a = 0.0;
}
`,
'fs:#main-start': `
if (vColor.a == 0.0) discard;
`
}
});
}

draw(opts) {
const {brushRadius = 1e6, mousePosition} = this.props;
// add uniforms
const uniforms = Object.assign({}, opts.uniforms, {
brushRadius: brushRadius,
mousePosition: mousePosition ?
this.projectPosition(this.unproject(mousePosition)).slice(0, 2) : [0, 0]
});
super.draw(Object.assign({}, opts, {uniforms}));
}
}

</script>
</html>
posted @ 2022-10-10 20:43  A影子放風箏  阅读(267)  评论(0)    收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css