d3js多线散点图缩放
Posted
技术标签:
【中文标题】d3js多线散点图缩放【英文标题】:d3js multi-line scatterplot zoom 【发布时间】:2022-01-05 03:32:00 【问题描述】:我正在使用 d3 v6 绘制带有缩放功能的多线散点图。我是 d3 的新手,根据不同的示例,我可以让缩放功能适用于图像/点。问题是线条没有缩放。我查看了许多类似的问题,但这些解决方案都不适合我。
我正在使用的代码:
var margin =
top: 50,
right: 30,
bottom: 30,
left: 210,
;
var svg = d3.select("svg"),
width = 1410 - margin.left - margin.right,
height = 620 - margin.top - margin.bottom;
svg
.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
d3.csv("CSV_files/NSW_pathway.csv").then(function (data1)
var groupData = d3.group(data1, (d) => d.pathway_name);
var xScale = d3.scaleLinear().domain([0, 1]).range([0, width]);
var yScale = d3.scaleLinear().domain([0, 1]).range([height, 0]);
var xAxis = d3.axisBottom(xScale).ticks(0).tickSize(-height);
var yAxis = d3.axisLeft(yScale).ticks(0).tickSize(-width);
var gX = svg
.append("g")
.attr(
"transform",
"translate(" + margin.left + "," + (margin.top + height) + ")"
)
.call(xAxis);
var gY = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
var focus = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "line")
.attr("clip-path", "url(#clip)");
const color = d3
.scaleOrdinal()
.range(["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]);
var points_g = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("clip-path", "url(#clip)")
.classed("points_g", true);
var label = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "label")
.attr("clip-path", "url(#clip)");
var div = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
const mouseover = function (event, d)
div.style("opacity", 1);
;
const mousemove = function (event, d)
div
.html(function (d1)
if (d.type != "learner")
return `The resource name is $d.resource_name`;
else return `This is $d.name`;
)
.style("position", "absolute")
.style("left", event.pageX + 15 + "px")
.style("top", event.pageY + 15 + "px");
;
const mouseleave = function (event, d)
div.transition().duration(200).style("opacity", 0);
;
var points = points_g.selectAll("point").data(data1);
points = points
.enter()
.append("image")
.attr("xlink:href", function (d)
if (d.type == "video") return "Images/3.jpg";
else if (d.type == "pdf") return "Images/4.png";
else if (d.type == "none") return "Images/5.png";
)
.attr("x", function (d)
return xScale(+d.x) - 10;
)
.attr("y", function (d)
return yScale(+d.y) - 10;
)
.attr("width", 20)
.attr("height", 20)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
label
.selectAll(".text")
.data(data1)
.enter()
.append("text")
.text(function (d)
return d.topic;
)
.attr("x", function (d)
return xScale(+d.x) + 10;
)
.attr("y", function (d)
return yScale(+d.y) + 10;
);
focus
.selectAll("line")
.data(groupData)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function (d)
return color(d[0]);
)
.attr("stroke-width", 1)
.attr("d", function (d)
return d3
.line()
.curve(d3.curveMonotoneX)
.x(function (d)
return xScale(+d.x);
)
.y(function (d)
return yScale(+d.y);
)(d[1]);
);
var zoom = d3
.zoom()
.scaleExtent([0.5, 20])
.extent([
[0, 0],
[width, height],
])
.on("zoom", zoomed);
svg
.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.lower();
svg.call(zoom).call(zoom.transform, d3.zoomIdentity);
function zoomed( transform )
var new_xScale = transform.rescaleX(xScale);
var new_yScale = transform.rescaleY(yScale);
gX.call(xAxis.scale(new_xScale));
gY.call(yAxis.scale(new_yScale));
points
.data(data1)
.attr("x", function (d)
return new_xScale(d.x) - 10;
)
.attr("y", function (d)
return new_yScale(d.y) - 10;
);
label
.selectAll("text")
.data(data1)
.attr("x", function (d)
return new_xScale(d.x) + 15;
)
.attr("y", function (d)
return new_yScale(d.y) + 15;
);
focus.selectAll("line").attr("d", function (d)
return d3
.line()
.curve(d3.curveMonotoneX)
.x(function (d)
return xScale(+d.x);
)
.y(function (d)
return yScale(+d.y);
)(d[1]);
);
);
csv 文件示例:
x,y,name,type,topic,resource_name,pathway_name
0,0,start,none,Sponsored Search Markets,Networks Crowd and Markets_NCMch15.pdf,pathwayOne
0,0,start,none,Sponsored Search Markets,Networks Crowd and Markets_NCMch15.pdf,pathwayTwo
0.086511627906977,0.16,horse,pdf,Graphs,Networks Crowd and Markets_NCMch2.pdf,pathwayOne
0.12,0.283768436578171,choice,pdf,Network Centrality,Notes_CGT BASED network CENTRALITY - L2.pdf,pathwayTwo
0.32,0.27217943628424,plex,video,Network Models,Network Analysis_LNch13.pdf,pathwayOne
0.775398773006135,0.33,social,pdf,Clustering,Network Analysis_LNch8.pdf,pathwayTwo
1,1,end,none,Allocation in Networks,Notes_Allocation in networks with DON-L3.pdf,pathwayOne
1,1,end,none,Allocation in Networks,Notes_Allocation in networks with DON-L3.pdf,pathwayTwo
感谢您的帮助。
【问题讨论】:
【参考方案1】:它不是缩放整个页面,而是缩放整个 svg,您的大边距超出了图表区域。一种解决方案是添加 g
元素,而不是在您的 svg 上,而仅在您的图表区域上。
但是使用您的代码,有两件事会阻止您的线条缩放。
1:您的选择是空的 - 行是返回路径的 d3 抽象
function zoomed()
...
// empty selection
console.log(focus.selectAll('line'))
// try instead
console.log(focus.selectAll('path'))
2:简单的错误 - 您使用的是旧秤而不是新秤
function zoomed()
...
focus.selectAll('path').attr('d', d =>
return d3.line()
// using old scale
.x(di => xScale(+di.x))
// change to
.x(di => new_xScale(+di.x))
)
【讨论】:
非常感谢,我没有意识到选择。【参考方案2】:我没有您的 csv 文件的样本,因此未对此进行测试,但如果您想放大整个图表,只需在您的 svg 和 transform
之后添加父级 g
..
...
svg
.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
// NEW - add g
.append('g')
// NEW - adjust scaleExtent to your needs
const zoom = d3.zoom()
.scaleExtent([1, 8])
.on('zoom', updateChart)
svg.call(zoom)
function updateChart(event)
svg.attr('transform', event.transform)
请注意,这也会添加平移,但如果您只想缩放,可以使用:
let scale = 1
...
function updateChart(event)
if(event.transform.k === scale) return
svg.attr('transform', event.transform)
scale = event.transform.k
【讨论】:
感谢您的回复。我添加了一些示例 csv 数据,添加父“g”不是缩放图表,而是缩放整个页面本身。以上是关于d3js多线散点图缩放的主要内容,如果未能解决你的问题,请参考以下文章
matplotlib 中带有散点图和使用 set_offsets 的动画:图形的自动缩放不起作用
matplotlib:通过用于为散点图着色的对数颜色条值对 2D 线进行着色
100天精通Python(可视化篇)——第82天:matplotlib绘制不同种类炫酷散点图参数说明+代码实战(二维散点图三维散点图散点图矩阵)