d3js:将动画应用于气泡和文本

3
我有一个气泡车,里面包含了一些圆形和文本。在检查图表时,我得到了如下的结果:inspect。问题是我所应用的动画只作用于圆形上。我希望能够将圆形和文字整合在一起,并对每个组应用动画效果。正如我所指定的,有两种事件: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

解决方案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...
})

这是您的fiddle,包含了这些更改: 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/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接