我一直在研究水平条形图。我将transition
的{{1}}属性的width
从0添加到所需的值,它们工作正常。然后,我添加了一些rect
元素,并使用circle
使其一个接一个地“出现”,将delay
属性从0过渡到所需的r
值,以及所有也很好。如果我没有在所有元素都完成过渡之前将鼠标悬停在任何元素上,则可视化效果将达到预期的效果。
r
和rect
都在不同的延迟之间过渡它们的circle
和width
属性,这使得其中的一些在其他属性之前显示。
问题:如果我将鼠标悬停在任何r
上而其他元素尚未完成其转换,则所有这些元素都会突然停止转换其属性。因此,没有达到整个图表所需的最终状态,实际上变成了一片混乱。我不知道为什么将鼠标悬停在一个元素上会干扰其他“明显”独立元素的预期行为。
rect
function draw(){
var width = $( window ).width() ;
var height = document.body.clientHeight ;
var data = [
{country:"Pichonita", growth: 15},
{country:"Andromeda", growth: 12},
{country:"India", growth: 33},
{country:"Indonesia", growth: 22},
{country:"Russia", growth: 6},
{country:"Mars", growth: 41},
{country:"Pluton", growth: 16},
{country:"Earth", growth: 24},
{country:"Neptune", growth: 8}
];
//set margins
var margin = {top:30, right:30, bottom:30, left:40};
var width = width - margin.left - margin.right*2.5;
var height = height - margin.top - margin.bottom;
//set scales & ranges
var xScale = d3.scaleLinear()
.range([0, width - 100])
var yScale = d3.scaleBand()
.range([0, height]).padding(.2)
//draw the svg
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right * 3)
.attr("height",height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left*2 + "," + margin.top + ")")
//force data
data.forEach(function(d){
return d.growth = +d.growth;
});
//set domains
yScale.domain(data.map(d => d.country))
xScale.domain([0, d3.max(data, d=> d.growth)])
//add X & Y axes and append the bars to Y axis
var xAxis = svg.append("g")
.attr("class",xAxis)
.attr("transform","translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(xScale))
var yAxis = svg.append("g")
.attr("class",yAxis)
.call(d3.axisLeft(yScale))
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("stroke","transparent")
.attr("stroke-width",4)
.on("mouseover", function(){d3.select(this).transition().duration(600).attr("stroke","#6D2077").attr("stroke-width",3).style("fill","#6D2077")
d3.selectAll(".textCircle").transition().duration(600)
.attr("r",yScale.bandwidth() / 1.9)
.attr("stroke","#6D2077")
.attr("stroke-width",1)
})
.on("mouseout", function(){d3.select(this)
.transition()
.duration(600)
.attr("stroke","transparent")
.attr("stroke-width",0)
.style("fill","#00338D")
d3.selectAll(".textCircle")
.transition().duration(600)
.attr("r", yScale.bandwidth() / 2)
.attr("stroke","transparent")
})
.attr("class","bar")
.attr("height",yScale.bandwidth())
.attr("x",0.5)
.attr("y",function(d){
return yScale(d.country)
})
.attr("width",0)
.transition()
.duration(3800)
.delay( (d,i)=> (i+1) *200)
.ease(d3.easeElastic)
.attr("width", function(d){
return xScale(d.growth)
})
.style("fill","#00338D")
var newG = svg.append("g")
newG.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class","textCircle")
.attr("cx",d=> xScale(d.growth) )
.attr("cy",d=> yScale(d.country) + yScale.bandwidth() / 2)
.attr("r",0)
.transition()
.duration(1200)
.delay( (d,i)=> (i+1) *450)
.attr("r",yScale.bandwidth() / 2)
.attr("opacity",1)
.style("fill","#0091DA")
.attr("stroke","transparent")
}
draw();
$( window ).resize(function() {
$("body").empty();
draw();
});
html{
height: 98%;
margin: 0;
padding: 0;
}
body{
min-height: 98%;
margin: 0;
padding: 0;
}
svg{
text-rendering: geometricPrecision;
shape-rendering:geometricPrecision;
}
答案 0 :(得分:1)
事情变得混乱,因为您添加了mouseover
和mouseout
事件监听器,它们试图执行与正在进行的过渡事件冲突的动作。要解决此问题,请在图表栏执行初始转换之前,不要添加mouseover
/ mouseout
侦听器。您可以使用transition.on('end', function(){...}
在过渡结束时添加一个侦听器,然后在过渡完成后将鼠标事件侦听器添加到DOM元素中。
d3.select('#whateverItIs')
// stuff to do prior to transition
.transition()
// transition stuff
.on('end', function() {
d3.select(this)
.on("mouseover", function() {
// handler code here
})
.on("mouseout", function() {
// handler code here
})
})
使用您的代码:
function draw() {
var width = $(window).width();
var height = document.body.clientHeight;
var data = [{
country: "Pichonita",
growth: 15
},
{
country: "Andromeda",
growth: 12
},
{
country: "India",
growth: 33
},
{
country: "Indonesia",
growth: 22
},
{
country: "Russia",
growth: 6
},
{
country: "Mars",
growth: 41
},
{
country: "Pluton",
growth: 16
},
{
country: "Earth",
growth: 24
},
{
country: "Neptune",
growth: 8
}
];
//set margins
var margin = {
top: 30,
right: 30,
bottom: 30,
left: 40
};
var width = width - margin.left - margin.right * 2.5;
var height = height - margin.top - margin.bottom;
//set scales & ranges
var xScale = d3.scaleLinear()
.range([0, width - 100])
var yScale = d3.scaleBand()
.range([0, height]).padding(.2)
//draw the svg
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right * 3)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left * 2 + "," + margin.top + ")")
//force data
data.forEach(function(d) {
return d.growth = +d.growth;
});
//set domains
yScale.domain(data.map(d => d.country))
xScale.domain([0, d3.max(data, d => d.growth)])
//add X & Y axes and append the bars to Y axis
var xAxis = svg.append("g")
.attr("class", xAxis)
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(xScale))
var yAxis = svg.append("g")
.attr("class", yAxis)
.call(d3.axisLeft(yScale))
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("stroke", "transparent")
.attr("stroke-width", 4)
.attr("class", "bar")
.attr("height", yScale.bandwidth())
.attr("x", 0.5)
.attr("y", function(d) {
return yScale(d.country)
})
.attr("width", 0)
.transition()
.duration(3800)
.delay((d, i) => (i + 1) * 200)
.ease(d3.easeElastic)
.attr("width", function(d) {
return xScale(d.growth)
})
.style("fill", "#00338D")
.on('end', function() {
d3.select(this)
.on("mouseover", function() {
d3.select(this)
.transition().duration(600)
.attr("stroke", "#6D2077")
.attr("stroke-width", 3)
.style("fill", "#6D2077")
d3.selectAll(".textCircle")
.transition().duration(600)
.attr("r", yScale.bandwidth() / 1.9)
.attr("stroke", "#6D2077")
.attr("stroke-width", 1)
})
.on("mouseout", function() {
d3.select(this)
.transition()
.duration(600)
.attr("stroke", "transparent")
.attr("stroke-width", 0)
.style("fill", "#00338D")
d3.selectAll(".textCircle")
.transition().duration(600)
.attr("r", yScale.bandwidth() / 2)
.attr("stroke", "transparent")
})
})
var newG = svg.append("g")
newG.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "textCircle")
.attr("cx", d => xScale(d.growth))
.attr("cy", d => yScale(d.country) + yScale.bandwidth() / 2)
.attr("r", 0)
.transition()
.duration(1200)
.delay((d, i) => (i + 1) * 450)
.attr("r", yScale.bandwidth() / 2)
.attr("opacity", 1)
.style("fill", "#0091DA")
.attr("stroke", "transparent")
}
draw();
$(window).resize(function() {
$("body").empty();
draw();
});
html{
height: 98%;
margin: 0;
padding: 0;
}
body{
min-height: 98%;
margin: 0;
padding: 0;
}
svg{
text-rendering: geometricPrecision;
shape-rendering:geometricPrecision;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>