0

我一直在尝试将这个项目与平行坐标从 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])]
    }))
}

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

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

错误截图

4

2 回答 2

0

请参阅这篇文章如何将比例应用于 d3 v4.0 画笔?

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

dim.brush = d3.brushY()
    .extent([[dim.xPos - 10, this.margins.top], [dim.xPos + 10, this.height - this.margins.top]]);
于 2018-06-29T19:41:09.163 回答
0

嗯,如果我在 .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 ==== ////
于 2018-02-15T20:21:57.357 回答