我正在研究d3.js的径向直方图。
问题如下:我有一个初始转换,使条形“增长”到它们的实际高度(eyecandy)。
一切正常。现在我想添加一个悬停过渡,即所有项目的不透明度应该在悬停时转换为.5,并在悬停状态结束时转换为1.
这也可以自行完成。
如果在初始转换仍然发生时触发悬停状态,它将停止正常工作。然后,初始过渡只是停止,并且条形没有达到它们的最终高度。
问题:如何让两个转换一起工作,以便悬停转换不会停止初始转换?
Here is a jsfiddle。以下是代码:
<script src="http://d3js.org/d3.v3.js"></script>
<div id="chart"></div>
<script>
var margin = {
top: 0,
right: 0,
bottom: 0,
left: 0
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var arcMin = 150;
var arcMax = 250;
var pi = Math.PI;
var color = d3.scale.category10();
var data = [
{
"value": 20,
"category": "category1"
},
{
"value": 24,
"category": "category1"
},
{
"value": 9,
"category": "category1"
},
{
"value": 93,
"category": "category1"
},
{
"value": 82,
"category": "category1"
},
{
"value": 56,
"category": "category1"
},
{
"value": 29,
"category": "category1"
},
{
"value": 6,
"category": "category1"
},
{
"value": 10,
"category": "category1"
},
{
"value": 4,
"category": "category1"
},
{
"value": 45,
"category": "category1"
},
{
"value": 25,
"category": "category1"
},
{
"value": 26,
"category": "category2"
},
{
"value": 53,
"category": "category2"
},
{
"value": 60,
"category": "category2"
},
{
"value": 87,
"category": "category2"
},
{
"value": 77,
"category": "category2"
},
{
"value": 40,
"category": "category2"
},
{
"value": 12,
"category": "category2"
},
{
"value": 80,
"category": "category2"
},
{
"value": 23,
"category": "category2"
},
{
"value": 53,
"category": "category2"
},
{
"value": 26,
"category": "category2"
},
{
"value": 34,
"category": "category2"
},
{
"value": 79,
"category": "category2"
},
{
"value": 98,
"category": "category3"
},
{
"value": 1,
"category": "category3"
},
{
"value": 13,
"category": "category3"
},
{
"value": 80,
"category": "category3"
},
{
"value": 66,
"category": "category3"
},
{
"value": 5,
"category": "category3"
},
{
"value": 36,
"category": "category3"
},
{
"value": 74,
"category": "category3"
},
{
"value": 32,
"category": "category3"
},
{
"value": 4,
"category": "category3"
},
{
"value": 54,
"category": "category3"
},
{
"value": 8,
"category": "category3"
},
{
"value": 64,
"category": "category3"
},
{
"value": 5,
"category": "category3"
},
{
"value": 58,
"category": "category3"
},
{
"value": 41,
"category": "category3"
},
{
"value": 81,
"category": "category3"
},
{
"value": 73,
"category": "category3"
},
{
"value": 20,
"category": "category3"
},
{
"value": 32,
"category": "category3"
},
{
"value": 42,
"category": "category3"
},
{
"value": 55,
"category": "category3"
},
{
"value": 74,
"category": "category3"
},
{
"value": 17,
"category": "category3"
},
{
"value": 6,
"category": "category3"
},
{
"value": 96,
"category": "category3"
},
{
"value": 18,
"category": "category3"
},
{
"value": 1,
"category": "category3"
},
{
"value": 18,
"category": "category3"
},
{
"value": 40,
"category": "category3"
},
{
"value": 9,
"category": "category3"
},
{
"value": 30,
"category": "category3"
},
{
"value": 28,
"category": "category3"
},
{
"value": 25,
"category": "category3"
},
{
"value": 44,
"category": "category3"
},
{
"value": 20,
"category": "category3"
},
{
"value": 99,
"category": "category3"
},
{
"value": 95,
"category": "category3"
},
{
"value": 50,
"category": "category3"
},
{
"value": 65,
"category": "category3"
},
{
"value": 66,
"category": "category3"
},
{
"value": 7,
"category": "category3"
},
{
"value": 70,
"category": "category4"
},
{
"value": 39,
"category": "category4"
},
{
"value": 12,
"category": "category4"
},
{
"value": 94,
"category": "category4"
},
{
"value": 55,
"category": "category4"
},
{
"value": 15,
"category": "category4"
},
{
"value": 84,
"category": "category4"
},
{
"value": 31,
"category": "category4"
},
{
"value": 48,
"category": "category4"
},
{
"value": 26,
"category": "category4"
},
{
"value": 70,
"category": "category4"
},
{
"value": 30,
"category": "category4"
},
{
"value": 26,
"category": "category4"
},
{
"value": 75,
"category": "category4"
},
{
"value": 43,
"category": "category4"
},
{
"value": 83,
"category": "category4"
},
{
"value": 64,
"category": "category5"
},
{
"value": 52,
"category": "category5"
},
{
"value": 37,
"category": "category5"
},
{
"value": 11,
"category": "category5"
},
{
"value": 77,
"category": "category6"
},
{
"value": 94,
"category": "category6"
},
{
"value": 37,
"category": "category6"
},
{
"value": 64,
"category": "category6"
},
{
"value": 92,
"category": "category6"
},
{
"value": 58,
"category": "category6"
},
{
"value": 70,
"category": "category6"
},
{
"value": 47,
"category": "category6"
},
{
"value": 87,
"category": "category6"
},
{
"value": 6,
"category": "category6"
},
{
"value": 87,
"category": "category6"
},
{
"value": 32,
"category": "category6"
},
{
"value": 70,
"category": "category6"
},
{
"value": 38,
"category": "category6"
},
{
"value": 38,
"category": "category6"
},
{
"value": 31,
"category": "category6"
},
{
"value": 82,
"category": "category6"
},
{
"value": 44,
"category": "category6"
},
{
"value": 21,
"category": "category6"
},
{
"value": 78,
"category": "category6"
},
{
"value": 97,
"category": "category6"
},
{
"value": 67,
"category": "category6"
},
{
"value": 29,
"category": "category6"
},
{
"value": 6,
"category": "category6"
}
];
var vis = d3.select("#chart").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 min = 1;
var max = data.length;
var middle = Math.round((max + min) / 2) - 0.5;
var innerArc = d3.svg.arc()
.innerRadius(arcMin)
.outerRadius(arcMin + 10)
.startAngle(function (d, i) {
return (i + 0.1 - middle) * (pi / middle);
})
.endAngle(function (d, i) {
return (i + 1 - 0.1 - middle) * (pi / middle);
});
var outerArc = d3.svg.arc()
.innerRadius(arcMin)
.outerRadius(function (d, i) {
// Use min-max-normalization to scale value into interval [arcMin, arcMax]
return (d.value - min) * ((arcMax - arcMin) / (max - min)) + arcMin;
})
.startAngle(function (d, i) {
return (i + 0.1 - middle) * (pi / middle);
})
.endAngle(function (d, i) {
return (i - 0.1 + 1 - middle) * (pi / middle);
});
var lines = vis.selectAll(".line")
.data(data)
.enter()
.append("path")
.attr("class", function (d) {
return d.category + " line";
})
.attr("d", innerArc)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.attr("fill", function (d) {
return color(d.category);
})
.on("mouseleave", function () {
d3.selectAll(".line")
.transition()
.duration(300)
.style("opacity", 1);
})
.on("mouseenter", function (d, i) {
d3.selectAll(".line")
.transition()
.duration(150)
.style("opacity", .5);
})
.transition()
.duration(2000)
.delay(function (d) {
return ((d.value - min) / (max - min)) * 500;
})
.attr("d", outerArc);
</script>
答案 0 :(得分:2)
在其他过渡开始后添加的过渡总是取消那些早期过渡,参见the documentation:
在给定时间,给定元素上只能有一个转换处于活动状态。但是,可以在同一元素上调度多个转换;如果它们在时间上交错,每个过渡将按顺序进行。如果在给定元素上运行较新的转换,则它会隐式取消任何较旧的转换,包括已安排但尚未运行的任何转换。
特别是:
这允许新的转换(例如响应新用户事件的转换)取代较旧的转换,即使这些较旧的转换已暂存或交错延迟。
因此,您正在寻找的用例明确不受D3支持。
实现您想要的功能将涉及在第二次转换开始时捕获状态并手动合并转换(请参阅here以获取指针),或转换到不同的元素。
答案 1 :(得分:1)
它只是一个d3&#34;限制&#34;。无论是由悬停还是其他东西触发,转换都无法同时运行。
尝试将悬停过渡移至CSS,并在d3中保持高度转换。
.hovertest {
background: steelblue;
transition: background 1s ease;
}
.hovertest:hover {
background: gray;
}
答案 2 :(得分:1)
更新:自D3版本3.5(2014年10月)以来,可以通过使用命名转换对元素执行并发转换。
Here你可以看到问题的原始jsfiddle与命名过渡。
var lines = vis.selectAll(".line")
.data(data)
.enter()
.append("path")
.attr("class", function (d) {
return d.category + " line";
})
.attr("d", innerArc)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.attr("fill", function (d) {
return color(d.category);
})
.on("mouseleave", function () {
d3.selectAll(".line")
.transition("opacity") // NAMED TRANSITION
.duration(300)
.style("opacity", 1);
})
.on("mouseenter", function (d, i) {
d3.selectAll(".line")
.transition("opacity") // NAMED TRANSITION
.duration(150)
.style("opacity", .5);
})
.transition("creation") // NAMED TRANSITION
.duration(2000)
.delay(function (d) {
return ((d.value - min) / (max - min)) * 500;
})
.attr("d", outerArc);
Bostock的另一个例子: http://bl.ocks.org/mbostock/5d8039fb983a29e2ad49
答案 3 :(得分:0)
作为我的具体问题的解决方法,我只是延迟了在初始转换的相同持续时间内添加了负责悬停效果的代码:
setTimeout(function () {
lines.on("mouseleave", function () {
tip.hide();
d3.selectAll(".line")
.transition()
.duration(300)
.style("opacity", 1);
})
.on("mouseenter", function (d, i) {
tip.show(d, container.node());
d3.selectAll(".line")
.transition()
.duration(150)
.style("opacity", .5);
})
}, 2000);
有关一般解决方案,请参阅Pablo EM和Lars Kotthoff的答案。