首页 > 解决方案 > 以编程方式控制画笔并传递相关信息

问题描述

这是昨天这个问题的延伸。我正在尝试绘制和创建多个画笔。我使用的蛮力方法没问题,但我需要额外的功能来以编程方式控制这些新创建的画笔,

    createBrush(){
        //Brushes
        var brushGroups = []
        for(var i=0; i<this.uniqueCats.length; i++){
            //BRUSH CONTAINER
            brushGroups[i] = d3.select('#brushContainer')
                .append('g')
                .attr('id',`${this.uniqueCats[i]}brush`)
                .attr('transform', `translate(${this.margin.left},0)`)
                .attr('class','brush');

            //BRUSH
            var brushID = this.uniqueCats[i]
            this[`${this.uniqueCats[i]}Brush`] = d3.brushX()
                .extent([[0, (i*135)+38], [this.width,(i*135)+170]])
                .on('end',(i)=>{
                    console.log('hi')
                    this.updateBubbles(i)
                })

            //CALL BRUSH from the brush container
            brushGroups[i].call(this[`${this.uniqueCats[i]}Brush`])
        }
    }

正如您在上面看到的,我 1)创建一个画笔容器 2)创建一个画笔,3)从容器中调用该画笔。我让它将相关信息传递给onfor的主要问题this.updateBubbles()。希望每个画笔都能传递特定信息updatebubbles(),让我了解哪个画笔被激活。

从那里我决定使用更优雅的 d3 方法,enter()但是,这种方法根本无法调用画笔,

    createBrushv2(){var that =this
        var brushContainer = d3.select('#brushContainer')
            .selectAll('g')
            .data(this.uniqueCats)

        var brushContainerEnter = brushContainer
            .enter()
            .append('g')
            .attr('id', d=> `${d}brush`)

        brushContainer = brushContainerEnter.merge(brushContainer)
            .attr('transform', `translate(${this.margin.left},0)`)
            .attr('class','brush')
            .each( function(d,i){
                console.log(i)
                d3.brushX()
                    .extent([[0,(i*135)+38], [that.width,(i*135)+170]])
                    .on('end',that.updateBubbles(d))
            })

    }

updateBubbles()功能是从每个画笔中唤起的,因此该功能需要能够了解选择了哪个画笔。

标签: javascriptd3.js

解决方案


您的代码中有几个问题,这使您的问题过于宽泛。因此,我将只处理未调用画笔的问题。

首先,恭喜您从方法#1(for循环)移动到方法#2(D3 选择)。在 D3 代码中,使用循环附加任何内容几乎是一个非常糟糕的主意。

话虽如此,与您的第一个片段不同,您实际上并没有在第二个片段中调用画笔。

因此,这...

d3.brushX()
    .extent([[0,(i*135)+38], [that.width,(i*135)+170]])
    .on('end',that.updateBubbles(d))

应该:

d3.brushX()
    .extent([[0,(i*135)+38], [that.width,(i*135)+170]])
    .on('end', that.updateBubbles)(d3.select(this))

更好的是,您应该使用 a selection.call,就像在您的第一种方法中一样。另外,请记住,这that.updateBubbles(d)将立即调用该函数,这不是您想要的。

这是一个非常基本的片段作为演示:

const data = d3.range(5);

const svg = d3.select("svg");

createBrushv2();

function createBrushv2() {
  var brushContainer = svg.selectAll(".brush")
    .data(data)

  var brushContainerEnter = brushContainer.enter()
    .append('g');

  brushContainer = brushContainerEnter.merge(brushContainer)
    .attr('transform', function(d) {
      return "translate(0," + (d * 25) + ")"
    })
    .attr('class', 'brush')
    .each(function(d) {
      d3.brushX()
        .extent([
          [0, 0],
          [300, 20]
        ])
        .on('end', updateBubbles)(d3.select(this))
    })
    .each(function() {
      d3.brushX().move(d3.select(this), [0, 300])
    })
};

function updateBubbles(brush) {
  console.log(brush)
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>


推荐阅读