【问题标题】:d3.js v4 brushY - can't change overlay widthd3.js v4 brushY - 无法更改覆盖宽度
【发布时间】:2018-02-15 20:02:44
【问题描述】:

我一直在尝试将具有平行坐标的 this 项目从 d3 V3 转换为 V4。遇到的问题是当我尝试在 Y 轴上为每个维度应用画笔时。

我无法更改刷牙时应用的叠加层的宽度。它始终具有 1000 个单位的宽度。一旦我实施刷牙,它就会发生。

这是我目前的代码:

// main.js
var margin = { top: 30, right: 10, bottom: 10, left: 40 },
    width = 1000 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

// The first element in domain will be mapped to the first point, the second domain value to the second point, and so on.
var x = d3.scalePoint()
    .range([0, width])

var y = {}; // Store linear scales for each dimension here!

var line = d3.line();     // https://github.com/d3/d3-shape#line
var axis = d3.axisLeft();
var background;
var foreground;

var dragging = {};
var dimensions = {};

// Create the main svg
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


d3.csv("cars.csv", function (error, cars) {
    if (error) throw error;

    //// ==== Set Dimensions START ==== ////
    // d3.keys will get the field "names": { cylinders: 8 } cylinders is the key in this case. All the keys will be recieved!
    // For each car variable! d is the variable
    dimensions = d3.keys(cars[0]).filter(function (d) {
        if (d === "name") return false; // Exclude the dimension "name"
        return true;
    });
    // Set the x-axis domain to the dimensions
    x.domain(dimensions);

    // Create a linear y scale for each dimension.
    dimensions.forEach(function (d) {
        y[d] = d3.scaleLinear()
            .domain(d3.extent(cars, function (data) {
                // Return each cars value for specfied dimension d.
                return +data[d];
            }))
            .range([height, 0]);
    })
    //// ==== Set Dimensions END ==== ////

    //// ==== Draw Lines START ==== ////
    background = svg.append("g")
            .attr("class", "background")
            .selectAll("path")
            .data(cars).enter()
        .append("path")
            .attr("d", path)
    foreground = svg.append("g")
            .attr("class", "foreground")
            .selectAll("path")
            .data(cars).enter()
        .append("path")
            .attr("d", path)
    //// ==== Draw Lines END ==== ////

    //// ==== Draw Axis START ==== ////
    var g = svg.selectAll(".dimension")
            .data(dimensions).enter() // g's data is the dimensions
        .append("g")
            .attr("class", "dimension")
            // Give the axis it's propper x pos
            .attr("transform", function(d) {return "translate("+x(d)+ ")"; });
    g.append("g") // The Axis
        .attr("class", "axis")
        .each(function(d) { d3.select(this).call(axis.scale(y[d])); });
    g.append("text") // Axis Label
        .attr("class", "title")
        .style("text-anchor", "middle")
        .attr("y", -10)
        .attr("font-size", 15)
        .text(function(d) { return d; });
    //// ==== Draw Axis END ==== ////

    //// ==== Axis dragging START ==== ////
    g.call(d3.drag()
        .on("start", function(d) {
            dragging[d] = x(d);
            background.attr("visibility", "hidden");
        })
        .on("drag", function(d) {
            // Make sure the dragging is within the range.
            dragging[d] = Math.min(width, Math.max(0, d3.event.x));
            foreground.attr("d", path) // Redraw the lines when draging an axis
            dimensions.sort(function(a,b) {return xPosition(a) - xPosition(b)});
            // Set the domain to the new order of the dimension
            x.domain(dimensions);
            // Translate the axis to mouse position
            g.attr("transform", function(d) { return "translate("+ xPosition(d) +")"; 
        })
    })
    .on("end", function(d) {
        delete dragging[d];
        d3.select(this)
                .transition().duration(200)
                .attr("transform", "translate("+x(d)+")");
        foreground
                .transition().duration(200)
                .attr("d", path)
        background
                .attr("d", path)
                .transition().delay(200).duration(0)
                .attr("visibility", null);
    }));
    //// ==== Axis dragging END ==== ////

    //// ==== Brushing START ==== ////
    g.append("g")
        .attr("class", "brush")
        .each(function(d){
            d3.select(this).call(d3.brushY()
                .on("start", function(){ d3.event.sourceEvent.stopPropagation(); })
                .on("brush", function(d, i){ console.log(d) }))
        })
        .selectAll("rect") 
        .attr("width", 20)  // This part doesn't do anything!
    //// ==== Brushing END ==== ////
});

function xPosition(d) {
  var v = dragging[d]; // This array holds the temporary positions when dragging. 
    if(v == null) return x(d);
    return v;
}

function path(data) {
    return line(dimensions.map(function(dim){
        return [xPosition(dim), y[dim](data[dim])]
    }))
}

这是错误的屏幕截图,如果有帮助的话。在其中,我刷了最左边的维度,它一直延伸到右边。

当我尝试刷任何其他维度时会发生同样的事情,除了覆盖从该特定维度开始,然后一直延伸到右侧。

【问题讨论】:

    标签: css d3.js brush parallel-coordinates


    【解决方案1】:

    嗯,如果我在 .on("start") 和 .on("brush") 处应用适当的宽度,它就会起作用。 不过,这感觉像是一种 hack,我不明白为什么以前的解决方案在 V3 中有效,而在 V4 中无效。

    //// ==== Brushing START ==== ////
    g.append("g")
            .attr("class", "brush")
            .each(function(d){
                d3.select(this).call(d3.brushY()
                    .on("start", function(){ 
                        d3.event.sourceEvent.stopPropagation(); 
                        g.selectAll("rect") 
                            .attr("width", 20)
                            .attr("x", -10)
                    })
                    .on("brush", function(d, i){ 
                        console.log(d) 
                        g.selectAll("rect") 
                            .attr("width", 20)
                            .attr("x", -10)
                    }))
            })
    //// ==== Brushing END ==== ////
    

    【讨论】:

      【解决方案2】:

      看到这个帖子How do I apply a scale to a d3 v4.0 brush?

      我在平行坐标图中为多个维度制作了每个画笔,如下所示:

      dim.brush = d3.brushY()
          .extent([[dim.xPos - 10, this.margins.top], [dim.xPos + 10, this.height - this.margins.top]]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-10
        • 1970-01-01
        • 2016-11-16
        • 1970-01-01
        • 2018-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多