2017-10-16 105 views
3

我有一个包含圆圈和一些文本的气泡购物车。在检查图表时,我得到类似如下的结果:d3js:在气泡和文本上一起应用动画

inspect

问题是我应用的动画只能在圆圈上工作。我想以某种方式将圆圈和文本组合在一起,然后在每个组上应用动画。 就像我指定的那样,2个事件:mouseover和mouseout。我想将它们应用于圆圈和圆圈内的文本。

我的脚本如下:

var margin = 40, 
width = 600, 
height = 400; 

var data = [{"admit_probability":54,"rank":20, "c":12}, 
      {"admit_probability":79,"rank":111, "c":9}, 
      {"admit_probability":70,"rank":68, "c":6}, 
      {"admit_probability":12,"rank":1, "c":20}, 
      {"admit_probability":197,"rank":87, "c":10}]; 

var xscale = d3.scaleLinear() 
       .domain(
        d3.extent(data, function(d) { return +d.admit_probability; }) 
       ) 
       .nice() 
       .range([0, width]); 

var yscale = d3.scaleLinear() 
       .domain(d3.extent(data, function(d) { return +d.rank; })) 
       .nice() 
       .range([height, 0]); 

var xAxis = d3.axisBottom().scale(xscale); 

var yAxis = d3.axisLeft().scale(yscale); 

var svg = d3.select('.chart') 
       .append('svg') 
       .attr('class', 'chart') 
       .attr("width", width + margin + margin) 
       .attr("height", height + margin + margin) 
       .append("g") 
       .attr("transform", "translate(" + margin + "," + margin + ")"); 

svg.append("g") 
    .attr("class", "y axis") 
    .call(yAxis); 

svg.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + height + ")") 
    .call(xAxis); 

var color = d3.scaleOrdinal(d3.schemeCategory10); 

svg.selectAll("circle") 
    .data(data) 
    .enter() 
    .insert("circle") 
    .attr("cx", width/2) 
    .attr("cy", height/2) 
    .attr("opacity", 0.3) 
    .attr("r", 20) 
    .style("fill", "blue") 
    .on('mouseover', function (d, i) { 
     d3.select(this) 
     .attr("r", 32) 
     .style("fill", "orange"); 
     }) 
    .on('mouseout', function (d, i) { 
     fadeOut(); 
    }) 
    .attr("cx", function (d) { return xscale(+d.admit_probability); }) 
    .attr("cy", function (d) { return yscale(+d.rank); }); 
    // .ease("elastic"); 

var text = svg.selectAll(null) 
    .data(data) 
    .enter() 
    .append('text'); 

var textLabels = text 
     .attr("x", function (d) { return xscale(+d.admit_probability); }) 
     .attr("text-anchor", "middle") 
     .attr("y", function (d) { return yscale(+d.rank); }) 
     .text("Hi") 
     .attr("font-family", "sans-serif") 
     .attr("font-size", "10px") 
     .attr("fill", "red"); 

svg.append("text") 
    .attr("transform", "translate(" + (width/2) + " ," + (height + margin) + ")") 
    .style("text-anchor", "middle") 
    .text("Average Acceptance"); 

svg.append("text") 
    .attr("transform", "rotate(-90)") 
    .attr("y", 0 - margin) 
    .attr("x",0 - (height/2)) 
    .attr("dy", "1em") 
    .style("text-anchor", "middle") 
    .text("Rank"); 

function fadeOut() { 
    svg.selectAll("circle") 
    .transition() 
    .style("opacity", 0.3) 
    .attr("r", 20) 
    .style("fill", "blue"); 
} 

我怎样才能做到这一点?

回答

1

解决方案1:

一个简单的解决方案是附加<g>元件以保持两种文本和圆:

var group = svg.selectAll(null) 
    .data(data) 
    .enter() 
    .append("g"); 

group.append("circle") 
    //etc... 

group.append("text") 
    //etc... 

然后该事件监听器添加到组中,选择两种文本和圆:

group.on('mouseover', function(d, i) { 
    d3.select(this).select("circle") 
     //etc... 

    d3.select(this).select("text") 
     /etc... 
}) 

这里是你的那些变化的小提琴:https://jsfiddle.net/p5f0eey1/

解决方案2:

的第二溶液不涉及任何一组。这是一个问题:当你想对一组元素应用相同的过渡或相同的属性时,人们立即认为“我会将它们放入一个组元素”。问题是创建越来越多的SVG元素可能会减慢你的页面。另一方面,这些脚本现在可以运行得非常快。因此,您可以依靠脚本来选择您想要的文本,只需将事件侦听器添加到该圆圈即可。

由于两个圆和文本具有相同的数据,就可以得到该事件处理程序内正确的文本为圆:

circles.on('mouseover', function(d, i) { 
    d3.select(this) 
     .attr("r", 32) 
     .style("fill", "orange"); 

    texts.filter(function(e) { 
     return e.rank === d.rank; 
    }).attr("font-size", "20px") 
}) 

这里是更新的小提琴:https://jsfiddle.net/mtjoxp3a/

+0

非常感谢了解决方案和解释:) – Yesha

+0

嗯,我看到你从来没有在StackOverflow接受任何答案。作为个人规则,我不回答那些一再不承认答案的用户提出的问题。祝你好运。 –

+0

对不起,以任何方式冒犯你。我无法赞扬你提供的答案,因为我没有足够的声誉。如果我错过了这个东西,请让我知道。 – Yesha