如何使用 D3.js v4 使时间轴上的元素跟随缩放
How to have elements on a timeline follow zooming using D3.js v4
我有一个时间线图,其中包含指示特定事件的数据点。我试图在图表中构建缩放功能,但已走到尽头。我可以放大轴,但无法将数据点重新定位到新比例。我经历过许多 d3 bl.ocks 但没有找到解决方案。
我在 jsfiddle 中有一个最小版本:
https://jsfiddle.net/q73ggw3e/2/
主要部分是:
缩放:
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
数据点:
svg.append("g")
.selectAll("logo")
.attr("class", "logo")
.data(data)
.enter()
.append("circle")
.attr("cy", 40)
.attr("cx", function(d) { return x(d);})
.attr("r", 10)
.style("fill", "#000000")
缩放区域:
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.call(zoom);
以及缩放功能:
function zoomed() {
svg.select(".axis--x")
.call(xAxis.scale(d3.event.transform.rescaleX(x)));
var new_x = d3.event.transform.rescaleX(x);
svg.selectAll(".logo")
.attr("cx", function(d) { return new_x(d);});
};
我也应该将圆圈的 (.logo) class 绑定到缩放事件,但由于某些原因只有轴缩放...
我哪里错了?或者是否有一些完全不同的方式来做到这一点...
如果重要的话,数据点也将具有拖放、鼠标悬停和单击功能。这些目前工作正常,但缩放矩形会阻止指针事件。但这是在缩放工作后进行排序...
你做的图表很奇怪
var margin = {
top: 30,
right: 20,
bottom: 30,
left: 120
},
width = 800 - margin.left - margin.right,
height = 210 - margin.top - margin.bottom;
var svg = d3.select(".zoom")
.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 + ")");
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var x = d3.scaleTime()
.rangeRound([0, width]);
var xAxis = d3.axisTop(x)
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var parseTime = d3.timeParse("%Y-%m-%d");
var lanes = ["A", "B", "C"]
var lanesLength = lanes.length
var a = ["2010-02-12", "2013-08-15", "2015-01-23", "2017-01-22"]
var data = [];
a.forEach(function (d){
data.push(parseTime(d));
});
var today = new Date();
x.domain([d3.min(data, function(d) { return d;}), today]);
y.domain([0, lanesLength]);
svg.append("g")
.attr("class", "axis axis--x")
.style("stroke-width", 2)
.attr("transform", "translate(0)")
.call(xAxis);
svg.append("g")
.selectAll(".lanetext")
.data(lanes)
.enter()
.append("text")
.text(function(d) { return d;})
.attr("x", -margin.right)
.attr("y", function(d, i) { return y(i + .5);})
.attr("dy", ".5ex")
.attr("text-anchor", "end")
.attr("class", "lanetext")
svg.append("g")
.attr("class", "logomu")
.selectAll("logomu")
.data(data)
.enter()
.append("circle")
.attr("cy", 40)
.attr("class", "logo")
.attr("cx", function(d) { return x(d);})
.attr("r", 10)
.style("fill", "#000000")
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.call(zoom);
function zoomed() {
svg.select(".axis--x")
.call(xAxis.scale(d3.event.transform.rescaleX(x)));
var new_x = d3.event.transform.rescaleX(x);
svg.selectAll(".logo")
.attr("cx", function(d) { return new_x(d);});
};
.axis line{
stroke: #000
}
.axis path{
stroke: #000
}
.axis text{
fill: #000
}
.lanetext {
fill: #000
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
.logo {
fill: #000;
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
<body>
<div class="zoom">
</div>
</body>
I should be binding the (.logo) class of circles to the zoom event
too, but for some reason only the axis zooms...
是否有class名称标识?检查 html 确保你附加它正确
Where am I going wrong? Or is there some completely other way of doing
this...
你没有检查你画的是什么。是的,只需要经验
我有一个时间线图,其中包含指示特定事件的数据点。我试图在图表中构建缩放功能,但已走到尽头。我可以放大轴,但无法将数据点重新定位到新比例。我经历过许多 d3 bl.ocks 但没有找到解决方案。
我在 jsfiddle 中有一个最小版本: https://jsfiddle.net/q73ggw3e/2/
主要部分是:
缩放:
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
数据点:
svg.append("g")
.selectAll("logo")
.attr("class", "logo")
.data(data)
.enter()
.append("circle")
.attr("cy", 40)
.attr("cx", function(d) { return x(d);})
.attr("r", 10)
.style("fill", "#000000")
缩放区域:
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.call(zoom);
以及缩放功能:
function zoomed() {
svg.select(".axis--x")
.call(xAxis.scale(d3.event.transform.rescaleX(x)));
var new_x = d3.event.transform.rescaleX(x);
svg.selectAll(".logo")
.attr("cx", function(d) { return new_x(d);});
};
我也应该将圆圈的 (.logo) class 绑定到缩放事件,但由于某些原因只有轴缩放...
我哪里错了?或者是否有一些完全不同的方式来做到这一点...
如果重要的话,数据点也将具有拖放、鼠标悬停和单击功能。这些目前工作正常,但缩放矩形会阻止指针事件。但这是在缩放工作后进行排序...
你做的图表很奇怪
var margin = {
top: 30,
right: 20,
bottom: 30,
left: 120
},
width = 800 - margin.left - margin.right,
height = 210 - margin.top - margin.bottom;
var svg = d3.select(".zoom")
.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 + ")");
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var x = d3.scaleTime()
.rangeRound([0, width]);
var xAxis = d3.axisTop(x)
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var parseTime = d3.timeParse("%Y-%m-%d");
var lanes = ["A", "B", "C"]
var lanesLength = lanes.length
var a = ["2010-02-12", "2013-08-15", "2015-01-23", "2017-01-22"]
var data = [];
a.forEach(function (d){
data.push(parseTime(d));
});
var today = new Date();
x.domain([d3.min(data, function(d) { return d;}), today]);
y.domain([0, lanesLength]);
svg.append("g")
.attr("class", "axis axis--x")
.style("stroke-width", 2)
.attr("transform", "translate(0)")
.call(xAxis);
svg.append("g")
.selectAll(".lanetext")
.data(lanes)
.enter()
.append("text")
.text(function(d) { return d;})
.attr("x", -margin.right)
.attr("y", function(d, i) { return y(i + .5);})
.attr("dy", ".5ex")
.attr("text-anchor", "end")
.attr("class", "lanetext")
svg.append("g")
.attr("class", "logomu")
.selectAll("logomu")
.data(data)
.enter()
.append("circle")
.attr("cy", 40)
.attr("class", "logo")
.attr("cx", function(d) { return x(d);})
.attr("r", 10)
.style("fill", "#000000")
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.call(zoom);
function zoomed() {
svg.select(".axis--x")
.call(xAxis.scale(d3.event.transform.rescaleX(x)));
var new_x = d3.event.transform.rescaleX(x);
svg.selectAll(".logo")
.attr("cx", function(d) { return new_x(d);});
};
.axis line{
stroke: #000
}
.axis path{
stroke: #000
}
.axis text{
fill: #000
}
.lanetext {
fill: #000
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
.logo {
fill: #000;
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
<body>
<div class="zoom">
</div>
</body>
I should be binding the (.logo) class of circles to the zoom event too, but for some reason only the axis zooms...
是否有class名称标识?检查 html 确保你附加它正确
Where am I going wrong? Or is there some completely other way of doing this...
你没有检查你画的是什么。是的,只需要经验