D3忽略具有相同数据的条形图,尽管使用了键函数

to94eoyn  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(182)

我试图创建一个条形图,并在条形图上添加mouseover和mouseout事件。我在代码中使用了scaleBand()。因此,从可接受的解决方案here中,我收集到序数刻度将重复的值视为相同。因此,我试图向data()函数添加一个键,我希望它能解决这个问题,并给予我所有的条形图,但这并没有发生。
下面是我的代码:

<!DOCTYPE html>
<html>
    <head>
        <title>Tooltip</title>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    <body>
<script>
            var bardata = [100, 200, 60, 150, 80, 300, 25, 75, 200, 50, 10, 200];

            var svgHeight = 400,
                svgWidth = 600;

            var barWidth = 30,
                barOffset = 1;

            var yScale = d3.scaleLinear()
                           .domain([0, d3.max(bardata)])
                           .range([0, svgHeight-10]);

            var xScale = d3.scaleBand()
                           .domain(bardata)
                           .range([0, svgWidth])
                           .paddingOuter(.5)
                           .paddingInner(.01);

            var colorYScale = d3.scaleLinear()
                                .domain([0, d3.max(bardata)*0.33,
                                            d3.max(bardata)*0.66],
                                            d3.max(bardata))
                                .range(['green', 'yellow', 'orange', 'red']);

            d3.select('body')
                .append('svg')
                .attr('width', svgWidth)
                .attr('height', svgHeight)
                .style('background-color', '#eeeeee');
                
            function id (d) { return d; }
            function idx (d,i) { return i;}

            var barchart = d3.select('svg')
                             .selectAll('rect')
                             .data(bardata, function(d,i){
                                return i;
                             })
                             .join(
                                enter => {
                                    enter.append('rect')
                                         .attr('width', xScale.bandwidth())
                                         .attr('height', d => yScale(d))    // animate
                                         .attr('x', d => xScale(d))
                                         .attr('y', d => svgHeight-yScale(d))   //animate
                                         .attr('fill', d => colorYScale(d))

                                         .on('mouseover', function(event){
                                            d3.select(this)
                                              .style('opacity', 0.3)
                                         })

                                         .on('mouseout', function(event){
                                            d3.select(this)
                                              .style('opacity', 1)
                                         })
                                }
                             )
        </script>
    </body>
</html>

字符串
这是我在data()中使用的键的问题吗?还是在使用序数标度时需要做更多的事情才能使代码工作?
谢谢你,谢谢

ruyhziif

ruyhziif1#

键函数在这种情况下没有任何区别,因为波段刻度仍然将具有相同值的不同项目视为相同。实际上,您添加了12个条形(您的barData数组长度),但您看不到它们,因为某些具有相同值的条形位于其他条形之上。
一个简单的解决方案是将索引传递给域.

xScale.domain(d3.range(bardata.length))

字符串
然后你使用它们:

.attr('x', (d, i) => xScale(i))


下面是修改后的代码:

<!DOCTYPE html>
<html>

<head>
  <title>Tooltip</title>
  <script src="https://d3js.org/d3.v7.min.js"></script>
</head>

<body>
  <script>
    var bardata = [100, 200, 60, 150, 80, 300, 25, 75, 200, 50, 10, 200];

    var svgHeight = 400,
      svgWidth = 600;

    var barWidth = 30,
      barOffset = 1;

    var yScale = d3.scaleLinear()
      .domain([0, d3.max(bardata)])
      .range([0, svgHeight - 10]);

    var xScale = d3.scaleBand()
      .domain(d3.range(bardata.length))
      .range([0, svgWidth])
      .paddingOuter(.5)
      .paddingInner(.01);

    var colorYScale = d3.scaleLinear()
      .domain([0, d3.max(bardata) * 0.33,
          d3.max(bardata) * 0.66
        ],
        d3.max(bardata))
      .range(['green', 'yellow', 'orange', 'red']);

    d3.select('body')
      .append('svg')
      .attr('width', svgWidth)
      .attr('height', svgHeight)
      .style('background-color', '#eeeeee');

    function id(d) {
      return d;
    }

    function idx(d, i) {
      return i;
    }

    var barchart = d3.select('svg')
      .selectAll('rect')
      .data(bardata, function(d, i) {
        return i;
      })
      .join(
        enter => {
          enter.append('rect')
            .attr('width', xScale.bandwidth())
            .attr('height', d => yScale(d)) // animate
            .attr('x', (d, i) => xScale(i))
            .attr('y', d => svgHeight - yScale(d)) //animate
            .attr('fill', d => colorYScale(d))

            .on('mouseover', function(event) {
              d3.select(this)
                .style('opacity', 0.3)
            })

            .on('mouseout', function(event) {
              d3.select(this)
                .style('opacity', 1)
            })
        }
      )
  </script>
</body>

</html>


请记住,正确的解决方案涉及创建具有唯一属性的对象。

相关问题