mirror of
https://github.com/d3/d3.git
synced 2025-12-08 19:46:24 +00:00
55 lines
1.5 KiB
Vue
55 lines
1.5 KiB
Vue
<script setup>
|
|
|
|
import * as d3 from "d3";
|
|
import * as topojson from "topojson-client";
|
|
import deferRender from "./deferRender.js";
|
|
|
|
</script>
|
|
<script>
|
|
|
|
const outline = {type: "Sphere"};
|
|
const graticule = d3.geoGraticule10();
|
|
|
|
let landPromises = {};
|
|
let disconnect;
|
|
|
|
async function render(node, {projection, landPromise}) {
|
|
const land = await landPromise;
|
|
const path = d3.geoPath(projection);
|
|
const svg = d3.select(node);
|
|
svg.selectAll("[name='outline']").attr("d", path(outline));
|
|
svg.selectAll("[name='graticule']").attr("d", path(graticule));
|
|
svg.selectAll("[name='feature']").attr("d", path(land));
|
|
}
|
|
|
|
export default {
|
|
props: {
|
|
projection: {type: Function},
|
|
resolution: {type: String, default: "110m"},
|
|
width: {type: Number, default: 688},
|
|
height: {type: Number, default: 400},
|
|
},
|
|
mounted() {
|
|
this.landPromise = landPromises[this.resolution] ??= d3
|
|
.json(`https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/land-${this.resolution}.json`)
|
|
.then((world) => topojson.feature(world, world.objects.land));
|
|
disconnect = deferRender(this.$el, async () => render(this.$el, this));
|
|
},
|
|
updated() {
|
|
render(this.$el, this);
|
|
},
|
|
unmounted() {
|
|
if (disconnect) disconnect();
|
|
}
|
|
}
|
|
|
|
</script>
|
|
<template>
|
|
<svg :width="width" :height="height">
|
|
<path name="outline" fill="var(--vp-c-bg-alt)" />
|
|
<path name="graticule" stroke="currentColor" stroke-opacity="0.2" fill="none" />
|
|
<path name="feature" fill="currentColor" />
|
|
<path name="outline" stroke="currentColor" fill="none" />
|
|
</svg>
|
|
</template>
|