Published
Edited
Dec 30, 2021
Fork of 河流图
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof chart_river = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.on("mouseover", reset);

// const regionSystem = RegionCatalog('cesus_1');

let currentWord = '';
let value = "ALL";

svg
.append("g")
.selectAll("path")
.data(series) //画河流所用数据
.join("path")
.on("mouseover", over)
.on("mouseout", out)
.on("mousemove", move)
// .style("fill", ({ key }) => d3.scaleOrdinal(keys,d3.schemeTableau10)) //设置河流的颜色(还没搞好
.style("fill", (d) => { return colorScale(d.key); }) //设置颜色
.attr("opacity", .7) //初始透明度
.attr("stroke", 'black')
.attr("stroke-width", .2)
.attr("d", area)
.on("click", function(event,d) {
// const node = svg.node();
// console.log(d);
// if(d == NaN){node.value = value = "ALL";}
d3.select(this) //选中鼠标操作触发的事件对应的当前元素对象
.transition()
.attr("opacity", .9)//设置不透明度为0.9
const node = svg.node();
// console.log(d);
//获得对应key
node.value = value = truncatedseries[d].key;
node.dispatchEvent(new CustomEvent("input"));
});

//画x轴
svg.append("g").call(xAxis);

//画长线
const bigLine = svg
.append("line")
.attr("stroke", "black")
.attr("opacity", .8)
.attr("stroke-dasharray", 3, 4)
.attr("pointer-events", "none");

//画短线
const line = svg
.append("line")
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("pointer-events", "none");

const textArea = svg.append("g").attr("pointer-events", "none");
const stateLabel = textArea
.append("text")
.attr("font-size", 16)
.attr("text-anchor", "middle");
const caseLabel = textArea
.append("text")
.attr("font-size", 16)
.attr("text-anchor", "middle");

function over(d) {
d3.select(this).attr("opacity", 1);
currentWord = d.key;
d3.event.stopPropagation(); //停止传播???
}

function out(d) {
d3.select(this).attr("opacity", .7);
}

function move(d) {
const dateStamp =
x.invert(d3.event.offsetX).getTime() >
x.invert(d3.event.offsetX).setHours(12, 0, 0, 0)
? x.invert(d3.event.offsetX).setHours(24, 0, 0, 0)
: x.invert(d3.event.offsetX).setHours(0, 0, 0, 0);
const index = d.findIndex(t => t.data.Date.getTime() == dateStamp);
const selectedData = d[index];
// const node = svg.node();
// node.value = value = "ALL";
// node.dispatchEvent(new CustomEvent("input"));
const min = d3.min(series, d => d[index][0]);
const max = d3.max(series, d => d[index][1]);
line
.attr("x1", x(dateStamp))
.attr("x2", x(dateStamp))
.attr("y1", y(selectedData[0]))
.attr("y2", y(selectedData[1]));
bigLine
.attr("x1", x(dateStamp))
.attr("x2", x(dateStamp))
.attr("y1", y(min))
.attr("y2", y(max));
stateLabel
.attr("x", d3.max([d3.min([x(dateStamp), width - 120]), 120]))
.attr("y", d3.max([y(max) - 40, 20]))
.text(currentWord + ' ' + new Date(dateStamp).toLocaleDateString());
const stateMetric = selectedData.data[currentWord];
const nationalMetric = d3.sum(keys, k => selectedData.data[k]);
const percentage = Math.round((stateMetric / nationalMetric) * 100);
caseLabel
.attr("x", d3.max([d3.min([x(dateStamp), width - 120]), 120]))
.attr("y", d3.max([y(max) - 20, 40]))
.text(
` 数量:${Math.round(
stateMetric
)} 占比:${percentage}%`
);
d3.event.stopPropagation();
}

function reset() {
line
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", 0)
.attr("y2", 0);
bigLine
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", 0)
.attr("y2", 0);
stateLabel.text("");
caseLabel.text("");
}

return Object.assign(svg.node(), {value});
}
Insert cell
Insert cell
Insert cell
area = d3
.area()
.x((d, i) => x(data[i].Date))
.y0(d => y(d[0]))
.y1(d => y(d[1]))
Insert cell
x = d3
.scaleUtc()
.domain(d3.extent(dates, (d, i) => d))
.range([margin.left, width - margin.right]).nice()
Insert cell
y = d3
.scaleLinear()
.domain([
d3.min(series, d => d3.min(d, d => d[0])),
d3.max(series, d => d3.max(d, d => d[1]))
])
.range([height - margin.bottom, margin.top])
Insert cell
// color = d3.scaleOrdinal().range(d3.schemeSet1)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
rawDates = d3.timeDay.range(new Date(2021, 1, 20), new Date(2021, 12, 18)) //此数据中的总日期范围
Insert cell
//Object.keys(rawData[0]).slice(11)
Insert cell
//rawData = d3.csv(
// "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_US.csv"
// )
Insert cell
rawDeathData = d3.csv(
'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_US.csv'
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = Object.assign(d3.csvParse(await FileAttachment("typenum@4.csv").text(), d3.autoType))
Insert cell
datedata = Object.assign(d3.csvParse(await FileAttachment("typenum-4.csv").text(), d3.autoType)).map(d => {d.Date = new Date(d.Date); return d;})
Insert cell
datedata.columns = data.columns
Insert cell
data.columns.slice(1,data.columns.length)
Insert cell
series = d3.stack()
.keys(data.columns.slice(1,data.columns.length)) //关键词(按关键词堆叠
.order(d3.stackOrderDescending) // 将最大的系列放在底部
.offset(d3.stackOffsetSilhouette) //将流图以零为中心
(datedata)
Insert cell
truncatedseries = {
const data = series.map(d => d.slice(dateRange[0], dateRange[1]));
data.forEach((d, i) => (d.key = series[i].key));
return data;
}
//进度条截出来的数据
Insert cell
Insert cell
colorScale = d3.scaleOrdinal()
.domain(keys)
.range(d3.schemeTableau10); //括号里的是10中分类颜色的数组
//根据各关键词来设置河流颜色,一个关键词一个颜色
Insert cell
Insert cell
-------------------------------------------------------------------------------------------------------------
Insert cell
-------------------------------------------------------------------------------------------------------------
Insert cell
# Use 1 Pie in bubble
Insert cell
Insert cell
newstype
Insert cell
Insert cell
chart1 = {
const svg = d3_1.create("svg")
.attr("font-size", "10pt")
.style("cursor", "default")
.attr("viewBox", [0, 0, width_1, height_1]);
const g = svg.selectAll("g")
.data(bubbles(chartData).leaves())
.join("g")
.attr("opacity", 1)
.attr("transform", d => `translate(${d.x},${d.y})`)
.on("mouseenter", e => {
e.currentTarget.parentElement.appendChild(e.currentTarget);
legend.node().parentElement.appendChild(legend.node());
})
.on("mouseover", (e, d) => {
g.transition().duration(500).attr("opacity", a => a === d ? 1 : 0.3)
g.selectAll(".ctext").transition().duration(500).attr("opacity", 0.5);
showLegend(legend, d);
})
.on("mouseout", () => {
g.transition().duration(500).attr("opacity", 1);
g.selectAll(".ctext").transition().duration(500).attr("opacity", 1);
legend.attr("opacity", 0);
});
g.append("g")
.call(g => g.append("circle").attr("r", d => d.r).attr("fill", d => bubbleColor(d.value)))
.call(g => g.append("g").attr("fill", d => invertedColor(d.value)).call(g => bubbleText(g, true, "ctext")));

g.append("g")
.attr("class", "pie")
.call(g => g.append("g")
.attr("font-weight", "bold")
.attr("transform", d => `translate(0,${d.r + 10})`)
.call(bubbleText)
)
.selectAll("path")
.data(d => d3_1.pie()(d.data.values).map(p => ({pie: p, data: d})))
.join("path")
.attr("d", drawPie)
.attr("fill", (d, i) => pieColor(years[i]));
const legend = svg.append("g").attr("font-weight", "bold").attr("opacity", 1);
return svg.node();
}
Insert cell
bubbles = data => d3_1.pack()
.size([width_1, height_1-50])
.padding(3)(
d3_1.hierarchy({children: data})
.sum(d => d.total)
)
Insert cell
drawPie = d => d3_1.arc()
.innerRadius(0)
.outerRadius(d.data.r)
.startAngle(d.pie.startAngle)
.endAngle(d.pie.endAngle)()
Insert cell
bubbleText = (g, short, className) => {
g.append("text")
.attr("class", className)
.attr("text-anchor", "middle")
.text(d => short ? d.data.code : d.data.state);
g.append("text")
.attr("class", className)
.attr("text-anchor", "middle")
.attr("dy", "1em")
.text(d => short ? d3_1.format(".2s")(d.value) : toCurrency(d.value));
}
Insert cell
showLegend = (legend, d) => {
legend.selectAll("g").remove();
legend
.selectAll("g")
.data(years)
.join("g")
.attr("transform", (d, i) => `translate(0,${15 * i})`)
.call(g => g.append("rect")
.attr("width", 15).attr("height", 12)
.attr("rx", 3).attr("ry", 3)
.attr("fill", y => pieColor(y)))
.call(g => g.append("text")
.attr("dx", 20)
.attr("dy", "0.8em")
.text((y, i) => {
const v = d.data.values[i];
return `${y} ${toCurrency(v)} (${(v / d.value * 100).toFixed(1)}%)`
}));
legend.attr("opacity", 1)
.attr("transform", `translate(${d.x + d.r + 10},${d.y - d.r})`);
}
Insert cell
pieColor = d3_1.scaleOrdinal()
.domain(years)
.range(["#4e79a7","#f28e2c","#e15759","#76b7b2","#59a14f","#edc949","#af7aa1","#ff9da7","#9c755f","#bab0ab"])
Insert cell
bubbleColor = d3_1.scaleSequential(d3_1.interpolateOrRd)
.domain(d3_1.extent(chartData.map(d => d.total)))
Insert cell
invertedColor = d3_1.scaleSequential(d3_1.interpolateCubehelixDefault)
.domain(d3_1.extent(chartData.map(d => d.total)))
Insert cell
toCurrency = (num) => d3_1.format(".2f")(num)
Insert cell
data1 = d3_1.csvParse(await FileAttachment("type_key_words.csv").text(), d3_1.autoType)
Insert cell
final_data={
if(chart_river=="ALL"){
let data2=data1;return data2;}
else{
let data2=data1.filter(d => d.Code==chart_river);return data2}
}
Insert cell
years = data1.columns.slice(2)
Insert cell
chartData = final_data.map(d => {
const values = years.map(y => d[y])
return {
state: d["State"],
code: d["Code"],
values: values,
total: values.reduce((a, b) => a + b)
}
})
Insert cell
width_1 = 1024
Insert cell
height_1 = 600
Insert cell
d3_1 = require("d3@6")
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