javascript - 如何使用 D3V6 缩放我的流图?
问题描述
更新: 缩放流图问题已解决。谢谢你,安德鲁!但是流图的缩放与 X 和 Y 轴的缩放不一致。
原帖在这里:
我是 StackOverflow 和 javascript 社区的新手。我正在尝试缩放我使用 javascript 和 D3 的流图,并按照本教程进行操作:https ://www.d3-graph-gallery.com/graph/interactivity_zoom.html#axisZoom 。
我的代码可以在这里查看:https ://github.com/Feisnowflakes/zoomtest222/tree/main/streamgraph-test
但是,目前,我可以缩放 X aXis 和 Y aXis,但我的流图不能缩放。我在控制台中没有看到任何错误,所以我现在卡住了。任何人都可以查看我的代码并帮助我弄清楚为什么我的流图无法缩放吗?
太感谢了!
(function () {
// first, load the dataset from a CSV file
d3.csv("https://raw.githubusercontent.com/Feisnowflakes/zoomtest222/main/streamgraph-test/Los_Angeles_International_Airport_-_Passenger_Traffic_By_Terminal.csv")
.then(data => {
// log csv in browser console
console.log(data);
var advanceVisData = {};
var airport = new Set();
data.forEach(d => {
airport.add(d['Terminal']);
var period = new Date(d['ReportPeriod']);
if (period in advanceVisData) {
if (d['Terminal'] in advanceVisData[period]) {
advanceVisData[period][d['Terminal']] += Number(d['Passenger_Count']);
}
else {
advanceVisData[period][d['Terminal']] = Number(d['Passenger_Count']);
}
}
else {
advanceVisData[period] = {};
advanceVisData[period][d['Terminal']] = Number(d['Passenger_Count']);
}
});
console.log(airport);
console.log(advanceVisData);
// reformat the advanceVisData for d3.stack()
var formattedData = [];
Object.keys(advanceVisData).forEach(d => {
var item = {};
item['year'] = d;
airport.forEach(terminal => {
if (terminal in advanceVisData[d]) {
item[terminal] = advanceVisData[d][terminal];
} else {
item[terminal] = 0;
}
});
formattedData.push(item);
});
console.log(formattedData);
/*********************************
* Visualization codes start here
* ********************************/
var width = 1200;
var height = 400;
var margin = { left: 60, right: 20, top: 20, bottom: 60 };
//set the dimensions and margins of the graph
// append the svg object to the body of the page
var svg = d3.select('#container')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// List of groups = header of the csv files
var keys = Array.from(airport);
//stack the data?
var stackedData = d3.stack()
//.offset(d3.stackOffsetSilhouette)
.keys(keys)
(formattedData);
console.log(stackedData);
var max_val = 0;
var min_val = 0;
stackedData.forEach(terminal => {
terminal.forEach(year => {
if (year[0] < min_val) min_val = year[0];
if (year[1] < min_val) min_val = year[1];
if (year[0] > max_val) max_val = year[0];
if (year[1] > max_val) max_val = year[1];
})
});
//console.log(max_val, min_val);
// Add X axis
var x = d3.scaleTime()
.domain(d3.extent(formattedData, function (d) {
return new Date(d.year);
}))
.range([0, width]);
var xAxis = svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(20));
// Add Y axis
var y = d3.scaleLinear()
.domain([min_val, max_val])
.range([height, 0]);
var yAxis = svg.append("g")
.call(d3.axisLeft(y));
// color palette
var color = d3.scaleOrdinal()
.domain(keys)
.range(['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#f781bf', "#87sbf", "#ff981bf","#d6a3b6", '#b3afb0', '#ddd8c2']);
// create a tooltip
var Tooltip = svg
.append("text")
.attr("x", 0)
.attr("y", 0)
.style("opacity", 0)
.style("font-size", 17)
// Show the areas
var stream = svg.append("g")
stream
.selectAll(".myStreamArea")
.data(stackedData)
.enter()
.append("path")
.attr("class", "myStreamArea")
.style("fill", function (d) {
return color(d.key);
})
.style("opacity", 1)
.attr("d", d3.area()
.x(function (d) {
return x(new Date(d.data.year));
})
.y0(function (d) {
return y(d[0]);
})
.y1(function (d) {
return y(d[1]);
})
);
// Set the zoom and Pan features: how much you can zoom, on which part, and what to do when there is a zoom
var zoom = d3.zoom()
.scaleExtent([.5, 20]) // This control how much you can unzoom (x0.5) and zoom (x20)
.extent([[0, 0], [width, height]])
.on("zoom", updateChart);
// This add an invisible rect on top of the chart area. This rect can recover pointer events: necessary to understand when the user zoom
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.call(zoom);
// now the user can zoom and it will trigger the function called updateChart
// A function that updates the chart when the user zoom and thus new boundaries are available
function updateChart() {
// recover the new scale
var transform = d3.zoomTransform(this);
var newX = transform.rescaleX(x);
var newY = transform.rescaleY(y);
// var newX = d3.event.transform.rescaleX(x);
// var newY = d3.event.transform.rescaleY(y);
// update axes with these new boundaries
xAxis.call(d3.axisBottom(newX))
yAxis.call(d3.axisLeft(newY))
stream
.selectAll(".myStreamArea")
.attr("d", d3.area()
.x(function (d) {
return newX(new Date(d.data.year));
})
.y0(function (d) {
return newY(d[0]);
})
.y1(function (d) {
return newY(d[1]);
}));
}
})
})();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Zoomable streamgraph</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
#tooltip {
min-width: 100px;
min-height: 50px;
background-color: white;
}
</style>
</head>
<body>
<div id="container"> <div id="tooltip"></div></div>
<script src="main.js"></script>
</body>
</html>
解决方案
推荐阅读
- python - 在 Django 的外键中,即时类型更改为 int
- html - 如何根据宽度百分比设置高度 - 纯 CSS
- azure - 创建新的 API 管理服务实例后,为什么内置管理员帐户无法登录开发者门户批准注册的应用程序?
- node.js - 如何查询 mongodb 以比较对象数组?
- python - 如何在 StopIteration 之后继续创建生成器?
- azure - 为什么我的 Service Fabric 间应用程序服务 RPC 需要 2 分钟?
- javascript - 如何使用 jhipster 和 Angular 在选项中显示图片?
- java - Apache POI:更改运行图片文本
- sql - UPDATE,然后在更新后返回整个表
- r - R从数据框中选择所有行,其中值在一列中重复但在另一列中具有特定值