【问题标题】:d3js: Hightlight bubble with specific parameters coming from input in bubble chartd3js:使用来自气泡图中输入的特定参数突出显示气泡
【发布时间】:2018-04-11 03:14:54
【问题描述】:

我有一个 d3 脚本,其中包含以下格式的数据:

var data = [{name: "A", rank: 0, student_percentile: 100.0, 
             admit_probability: 24},
            {name: "B", rank: 45, student_percentile: 40.3, 
             admit_probability: 24},
            {name: "C", rank: 89, student_percentile: 89.7, 
             admit_probability: 24},
            {name: "D", rank: 23, student_percentile: 10.9, 
             admit_probability: 24},
            {name: "E", rank: 56, student_percentile: 30.3, 
             admit_probability: 24}];

最初当页面加载时,我用这些数据制作了一个气泡图。之后,用户可以输入(从 A 到 E)。图的x-axis 由_student_percentile_ 和y-axis 来自rank。用户输入进入后,我想用这个名称突出显示气泡(我有用户输入的 rank 和 _student_percentile_)

现在,我不明白,如何过滤带有cx=xscale(student_percentile)、cy=yscale(rank) 的圆圈,以及从输入中接收到的 student_percentile 和 rank。

我的脚本如下:

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

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

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);

    svg = d3.select('.chart')
                    .classed("svg-container", true)
                    .append('svg')
                    .attr('class', 'chart')
                    .attr("viewBox", "0 0 680 490")
                    .attr("preserveAspectRatio", "xMinYMin meet")
                    .classed("svg-content-responsive", true)
                    .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 legend = svg.append("g")
    //  .attr('class', 'legend')
    var color = d3.scaleOrdinal(d3.schemeCategory10);

    var local = d3.local();
    circles = svg.selectAll(null)
          .data(data)
          .enter()
          .append("circle")
          .attr("cx", width / 2)
          .attr("cy", height / 2)
          .attr("opacity", 0.3)
          .attr("r", 20)
          .style("fill", function(d){
            if(+d.admit_probability <= 40){
                return "red";
            }
            else if(+d.admit_probability > 40 && +d.admit_probability <= 70){
                return "yellow";
            }
            else{
                return "green";
            }
          })
          .attr("cx", function(d) {
            return xscale(+d.student_percentile);
          })
          .attr("cy", function(d) {
            return yscale(+d.rank);
          })
          .on('mouseover', function(d, i) {
            local.set(this, d3.select(this).style("fill"));
            d3.select(this)
              .transition()
              .duration(1000)
              .ease(d3.easeBounce)
              .attr("r", 32)
              .style("fill", "orange")
              .style("cursor", "pointer")
              .attr("text-anchor", "middle");
            }
           )
          .on('mouseout', function(d, i) {
            d3.select(this).style("fill", local.get(this));
            d3.select(this).transition()
              .style("opacity", 0.3)
              .attr("r", 20)
              .style("cursor", "default")
            .transition()
            .duration(1000)
            .ease(d3.easeBounce)
          });

    texts = svg.selectAll(null)
      .data(data)
      .enter()
      .append('text')
      .attr("x", function(d) {
        return xscale(+d.student_percentile);
      })
      .attr("text-anchor", "middle")
      .attr("y", function(d) {
        return yscale(+d.rank);
      })
      .text(function(d) {
        return +d.admit_probability;
      })
      .attr("pointer-events", "none")
      .attr("font-family", "sans-serif")
      .attr("font-size", "12px")
      .attr("fill", "red");

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

    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");

提前致谢!

【问题讨论】:

    标签: javascript d3.js bubble-chart


    【解决方案1】:

    您可以处理keyup 输入事件并使用本机d3.filter 方法过滤您的circle 选择。查看下面隐藏的 sn-p 中的工作示例。

    d3.select('#user-input').on('keyup', function() {
      var value = d3.event.target.value;
    
      circles.filter(function(circle) {
        return circle.name === value.trim().toUpperCase();
      })
      .each(function() {
        local.set(this, d3.select(this).style("fill"));
      })
      .transition()
      .duration(1000)
      .ease(d3.easeBounce)
      .attr("r", 32)
      .style("fill", "orange")
      .style("cursor", "pointer")
      .attr("text-anchor", "middle");
    
      circles.filter(function(circle) {
        return circle.name !== value.trim().toUpperCase();
      })
      .transition()
      .attr("r", 20)
      .style("cursor", "default")
      .style("fill", function() { return  local.get(this) || d3.select(this).style("fill"); })
      .transition()
      .duration(1000)
      .ease(d3.easeBounce)
    });
    

    var svg;
    var margin = 40,
      width = 600,
      height = 400;
    
    var data = [{
      name: "A",
      rank: 0,
      student_percentile: 100.0,
      admit_probability: 24
    }, {
      name: "B",
      rank: 45,
      student_percentile: 40.3,
      admit_probability: 24
    }, {
      name: "C",
      rank: 89,
      student_percentile: 89.7,
      admit_probability: 24
    }, {
      name: "D",
      rank: 23,
      student_percentile: 10.9,
      admit_probability: 24
    }, {
      name: "E",
      rank: 56,
      student_percentile: 30.3,
      admit_probability: 24
    }];
    
    xscale = d3.scaleLinear()
      .domain(
        d3.extent(data, function(d) {
          return +d.student_percentile;
        })
      )
      .nice()
      .range([0, width]);
    
    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);
    
    svg = d3.select('.chart')
      .classed("svg-container", true)
      .append('svg')
      .attr('class', 'chart')
      .attr("viewBox", "0 0 680 490")
      .attr("preserveAspectRatio", "xMinYMin meet")
      .classed("svg-content-responsive", true)
      .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 legend = svg.append("g")
    //  .attr('class', 'legend')
    var color = d3.scaleOrdinal(d3.schemeCategory10);
    
    var local = d3.local();
    circles = svg.selectAll(null)
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", width / 2)
      .attr("cy", height / 2)
      .attr("opacity", 0.3)
      .attr("r", 20)
      .style("fill", function(d) {
        if (+d.admit_probability <= 40) {
          return "red";
        } else if (+d.admit_probability > 40 && +d.admit_probability <= 70) {
          return "yellow";
        } else {
          return "green";
        }
      })
      .attr("cx", function(d) {
        return xscale(+d.student_percentile);
      })
      .attr("cy", function(d) {
        return yscale(+d.rank);
      })
      .on('mouseover', function(d, i) {
        local.set(this, d3.select(this).style("fill"));
        d3.select(this)
          .transition()
          .duration(1000)
          .ease(d3.easeBounce)
          .attr("r", 32)
          .style("fill", "orange")
          .style("cursor", "pointer")
          .attr("text-anchor", "middle");
      })
      .on('mouseout', function(d, i) {
        d3.select(this).transition()
          .style("opacity", 0.3)
          .style("fill", local.get(this))
          .attr("r", 20)
          .style("cursor", "default")
          .transition()
          .duration(1000)
          .ease(d3.easeBounce)
      });
    
    texts = svg.selectAll(null)
      .data(data)
      .enter()
      .append('text')
      .attr("x", function(d) {
        return xscale(+d.student_percentile);
      })
      .attr("text-anchor", "middle")
      .attr("y", function(d) {
        return yscale(+d.rank);
      })
      .text(function(d) {
        return +d.admit_probability;
      })
      .attr("pointer-events", "none")
      .attr("font-family", "sans-serif")
      .attr("font-size", "12px")
      .attr("fill", "red");
    
    svg.append("text")
      .attr("transform", "translate(" + (width / 2) + " ," + (height + margin) + ")")
      .style("text-anchor", "middle")
      .text("Percentile");
    
    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");
    
    d3.select('#user-input').on('keyup', function() {
    	var value = d3.event.target.value;
      
      circles.filter(function(circle) {
      	return circle.name === value.trim().toUpperCase();
      })
      .each(function() {
      	local.set(this, d3.select(this).style("fill"));
      })
      .transition()
        .duration(1000)
        .ease(d3.easeBounce)
        .attr("r", 32)
        .style("fill", "orange")
        .style("cursor", "pointer")
        .attr("text-anchor", "middle");
        
      circles.filter(function(circle) {
      	return circle.name !== value.trim().toUpperCase();
      })
      .transition()
      .attr("r", 20)
      .style("cursor", "default")
      .style("fill", function() { return local.get(this) || d3.select(this).style("fill") })
      .transition()
      .duration(1000)
      .ease(d3.easeBounce)
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
    <div class="chart"></div>
    <h2>Type "A", "B", "C", "D", or "E" in input below</h2>
    <input type="text" id="user-input">

    【讨论】:

    • 完美!非常感谢:D
    猜你喜欢
    • 2016-02-13
    • 1970-01-01
    • 2013-12-28
    • 2017-04-29
    • 2018-03-28
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2013-10-31
    相关资源
    最近更新 更多