https://observablehq.com/@d3/tidy-tree
Dentro.vue
<!--
<template><div><dentro></dentro></div></template>
<script>
import Dentro from "@/views/Dentro.vue";
export default {components: {Dentro}};
</script>
-->
<template>
<div>
<h1>Dentro</h1>
<div id="arc" class="svgborder" />
<div id="den" class="svgborder" />
<h1>End</h1>
</div>
</template>
<script>
import * as d3 from "d3";
import flareJson from "@/assets/dentro.json";
export default {
name: "Dentro",
data() {
return {
gdp: [
{ country: "USA", value: 20.5 },
{ country: "China", value: 13.4 },
{ country: "Germany", value: 4.0 },
{ country: "Japan", value: 4.9 },
{ country: "France", value: 2.8 }
]
};
},
mounted() {
this.generateArc("#arc", this.gdp);
this.generateDen("#den");
},
methods: {
generateDen(id) {
const width = 1280;
const data = flareJson;
const temp = d3.hierarchy(data);
temp.dx = 10;
temp.dy = width / (temp.height + 1);
const root = d3.tree().nodeSize([temp.dx, temp.dy])(temp);
let x0 = Infinity;
let x1 = -x0;
root.each(d => {
if (d.x > x1) x1 = d.x;
if (d.x < x0) x0 = d.x;
});
const svg = d3
.select(id)
.append("svg")
.attr("viewBox", [0, 0, width, x1 - x0 + root.dx * 2]);
const g = svg
.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("transform", `translate(${root.dy / 3},${root.dx - x0})`);
const link = g
.append("g")
.attr("fill", "none")
.attr("stroke", "#555")
.attr("stroke-opacity", 0.4)
.attr("stroke-width", 1.5)
.selectAll("path")
.data(root.links())
.join("path")
.attr(
"d",
d3
.linkHorizontal()
.x(d => d.y)
.y(d => d.x)
);
console.log(link);
const node = g
.append("g")
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.y},${d.x})`);
node
.append("circle")
.attr("fill", d => (d.children ? "#555" : "#999"))
.attr("r", 2.5);
node
.append("text")
.attr("dy", "0.31em")
.attr("x", d => (d.children ? -6 : 6))
.attr("text-anchor", d => (d.children ? "end" : "start"))
.text(d => d.data.name)
.clone(true)
.lower()
.attr("stroke", "white");
const chart = svg.node();
console.log(chart);
},
generateArc(id, gdp) {
const w = 500;
const h = 500;
const svg = d3
.select(id)
.append("svg")
.attr("width", w)
.attr("height", h);
const sortedGDP = gdp.sort((a, b) => (a.value > b.value ? 1 : -1));
const color = d3.scaleOrdinal(d3.schemeDark2);
const max_gdp = d3.max(sortedGDP, o => o.value);
const angleScale = d3
.scaleLinear()
.domain([0, max_gdp])
.range([0, 1.5 * Math.PI]);
const arc = d3
.arc()
.innerRadius((d, i) => (i + 1) * 25)
.outerRadius((d, i) => (i + 2) * 25)
.startAngle(angleScale(0))
.endAngle(d => angleScale(d.value));
const g = svg.append("g");
g.selectAll("path")
.data(sortedGDP)
.enter()
.append("path")
.attr("d", arc)
.attr("fill", (d, i) => color(i))
.attr("stroke", "#FFF")
.attr("stroke-width", "1px")
.on("mouseenter", function() {
d3.select(this)
.transition()
.duration(200)
.attr("opacity", 0.5);
})
.on("mouseout", function() {
d3.select(this)
.transition()
.duration(200)
.attr("opacity", 1);
});
g.selectAll("text")
.data(gdp)
.enter()
.append("text")
.text(d => `${d.country} - ${d.value} Trillion`)
.attr("x", -150)
.attr("dy", -8)
.attr("y", (d, i) => -(i + 1) * 25);
g.attr("transform", "translate(200,300)");
}
}
};
</script>
<style scope>
.svgborder svg {
border: 2px solid;
}
</style>
Middle
End
沒有留言:
張貼留言