【问题标题】:How to color lines in parallel coordinate plot in d3?如何在d3中为平行坐标图中的线条着色?
【发布时间】:2019-10-08 21:11:44
【问题描述】:

我的问题是我无法在这个 d3 图表中为线条着色。我尝试了一些东西,但没有奏效。

我也尝试添加这个:

 var color = d3.scale.ordinal()
  .domain([1,2,3])
  .range(['red','green','blue']); 

然后我添加了这个:

 foreground = svg.append('svg:g')
  .attr('class', 'foreground')
  .selectAll('path')
  .data(data)
  .enter().append('svg:path')
  .attr('d', path)
  .attr('stroke', function(d) { return color(d.label); }); 

这是jsfiddle 中的代码,其中我有一个平行坐标图,悬停在线条上,但现在我想为每辆车的线条着色不同。 代码是这样的:

var margin = {top: 30, right: 40, bottom: 20, left: 200},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var dimensions = [
  {
    name: "name",
    scale: d3.scale.ordinal().rangePoints([0, height]),
    type: "string"
  },
  {
    name: "economy (mpg)",
    scale: d3.scale.linear().range([0, height]),
    type: "number"
  },
  {
    name: "cylinders",
    scale: d3.scale.linear().range([height, 0]),
    type: "number"
  },
  {
    name: "displacement (cc)",
    scale: d3.scale.linear().range([height, 0]),
    type: "number"
  },
  {
    name: "power (hp)",
    scale: d3.scale.linear().range([height, 0]),
    type: "number"
  },
  {
    name: "weight (lb)",
    scale: d3.scale.linear().range([height, 0]),
    type: "number"
  },
  {
    name: "0-60 mph (s)",
    scale: d3.scale.linear().range([height, 0]),
    type: "number"
  },
  {
    name: "year",
    scale: d3.scale.linear().range([height, 0]),
    type: "number"
  },
];

var x = d3.scale.ordinal()
    .domain(dimensions.map(function(d) { return d.name; }))
    .rangePoints([0, width]);

var line = d3.svg.line()
    .defined(function(d) { return !isNaN(d[1]); });

// CREATE A COLOR SCALE
var color = d3.scale.ordinal()
  .domain(['Buick','Chevrolet','Dodge'])
  .range(['red','blue','green'])    

var yAxis = d3.svg.axis()
    .orient("left");

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

var dimension = svg.selectAll(".dimension")
    .data(dimensions)
  .enter().append("g")
    .attr("class", "dimension")
    .attr("transform", function(d) { return "translate(" + x(d.name) + ")"; });

function parallelchart(data) {
  dimensions.forEach(function(dimension) {
    dimension.scale.domain(dimension.type === "number"
        ? d3.extent(data, function(d) { return +d[dimension.name]; })
        : data.map(function(d) { return d[dimension.name]; }).sort());
  });

  svg.append("g")
      .attr("class", "background")
    .selectAll("path")
      .data(data)
    .enter().append("path")
      .attr("d", draw);

/*   svg.append("g")
      .attr("class", "foreground")
    .selectAll("path")
      .data(data)
    .enter().append("path")
      .attr("d", draw); */

  // USE THE COLOR SCALE TO SET THE STROKE BASED ON THE DATA
  foreground = svg.append("g")
      .attr("class", "foreground")
    .selectAll("path")
      .data(data)
    .enter().append("path")
      .attr("d", path)
      .attr("stroke", function(d) {
        var company = d.name.slice(0,d.name.indexOf(' '));
        return color(company);
      })


  dimension.append("g")
      .attr("class", "axis")
      .each(function(d) { d3.select(this).call(yAxis.scale(d.scale)); })
    .append("text")
      .attr("class", "title")
      .attr("text-anchor", "middle")
      .attr("y", -9)
      .text(function(d) { return d.name; });

  var ordinal_labels = svg.selectAll(".axis text")
      .on("mouseover", mouseover)
      .on("mouseout", mouseout);

  var projection = svg.selectAll(".background path,.foreground path")
      .on("mouseover", mouseover)
      .on("mouseout", mouseout);

  function mouseover(d) {
    svg.classed("active", true);

    // this could be more elegant
    if (typeof d === "string") {
      projection.classed("inactive", function(p) { return p.name !== d; });
      projection.filter(function(p) { return p.name === d; }).each(moveToFront);
      ordinal_labels.classed("inactive", function(p) { return p !== d; });
      ordinal_labels.filter(function(p) { return p === d; }).each(moveToFront);
    } else {
      projection.classed("inactive", function(p) { return p !== d; });
      projection.filter(function(p) { return p === d; }).each(moveToFront);
      ordinal_labels.classed("inactive", function(p) { return p !== d.name; });
      ordinal_labels.filter(function(p) { return p === d.name; }).each(moveToFront);
    }
  }

  function mouseout(d) {
    svg.classed("active", false);
    projection.classed("inactive", false);
    ordinal_labels.classed("inactive", false);
  }

  function moveToFront() {
    this.parentNode.appendChild(this);
  }
}

function draw(d) {
  return line(dimensions.map(function(dimension) {
    return [x(dimension.name), dimension.scale(d[dimension.name])];
  }));
}

parallelchart(data);

输出应该是我为每辆车的线条添加颜色。:

 var color = d3.scale.ordinal()
  .domain(['BMW', Buick, 'Chevrolet'])
  .range(['red','green','blue']); 

或者以另一种方式,我做错了什么?

【问题讨论】:

    标签: javascript css d3.js


    【解决方案1】:

    您的代码是正确的。问题在于您使用的是attr...

    .attr("stroke", function(d) {
        var company = d.name.slice(0, d.name.indexOf(' '));
        return color(company);
    })
    

    ...虽然您有路径的 CSS 规则:

    .foreground path {
        stroke: steelblue;
    }
    

    因此,attr 中设置的值被覆盖。

    解决方案只是使用style(或删除CSS):

    .style("stroke", function(d) {
      var company = d.name.slice(0, d.name.indexOf(' '));
      return color(company);
    }) 
    

    这是您的更改代码:

    var data = [{
        "name": "AMC Ambassador Brougham",
        "economy (mpg)": 13,
        "cylinders": 8,
        "displacement (cc)": 360,
        "power (hp)": 175,
        "weight (lb)": 3821,
        "0-60 mph (s)": 11,
        "year": 73
      },
      {
        "name": "AMC Ambassador DPL",
        "economy (mpg)": 15,
        "cylinders": 8,
        "displacement (cc)": 390,
        "power (hp)": 190,
        "weight (lb)": 3850,
        "0-60 mph (s)": 8.5,
        "year": 70
      },
      {
        "name": "AMC Ambassador SST",
        "economy (mpg)": 17,
        "cylinders": 8,
        "displacement (cc)": 304,
        "power (hp)": 150,
        "weight (lb)": 3672,
        "0-60 mph (s)": 11.5,
        "year": 72
      },
      {
        "name": "AMC Concord DL 6",
        "economy (mpg)": 20.2,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 90,
        "weight (lb)": 3265,
        "0-60 mph (s)": 18.2,
        "year": 79
      },
      {
        "name": "AMC Concord DL",
        "economy (mpg)": 18.1,
        "cylinders": 6,
        "displacement (cc)": 258,
        "power (hp)": 120,
        "weight (lb)": 3410,
        "0-60 mph (s)": 15.1,
        "year": 78
      },
      {
        "name": "AMC Concord DL",
        "economy (mpg)": 23,
        "cylinders": 4,
        "displacement (cc)": 151,
        "power (hp)": "",
        "weight (lb)": 3035,
        "0-60 mph (s)": 20.5,
        "year": 82
      },
      {
        "name": "AMC Concord",
        "economy (mpg)": 19.4,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 90,
        "weight (lb)": 3210,
        "0-60 mph (s)": 17.2,
        "year": 78
      },
      {
        "name": "AMC Concord",
        "economy (mpg)": 24.3,
        "cylinders": 4,
        "displacement (cc)": 151,
        "power (hp)": 90,
        "weight (lb)": 3003,
        "0-60 mph (s)": 20.1,
        "year": 80
      },
      {
        "name": "AMC Gremlin",
        "economy (mpg)": 18,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 100,
        "weight (lb)": 2789,
        "0-60 mph (s)": 15,
        "year": 73
      },
      {
        "name": "AMC Gremlin",
        "economy (mpg)": 19,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 100,
        "weight (lb)": 2634,
        "0-60 mph (s)": 13,
        "year": 71
      },
      {
        "name": "AMC Gremlin",
        "economy (mpg)": 20,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 100,
        "weight (lb)": 2914,
        "0-60 mph (s)": 16,
        "year": 75
      },
      {
        "name": "AMC Gremlin",
        "economy (mpg)": 21,
        "cylinders": 6,
        "displacement (cc)": 199,
        "power (hp)": 90,
        "weight (lb)": 2648,
        "0-60 mph (s)": 15,
        "year": 70
      },
      {
        "name": "AMC Hornet Sportabout (Wagon)",
        "economy (mpg)": 18,
        "cylinders": 6,
        "displacement (cc)": 258,
        "power (hp)": 110,
        "weight (lb)": 2962,
        "0-60 mph (s)": 13.5,
        "year": 71
      },
      {
        "name": "AMC Hornet",
        "economy (mpg)": 18,
        "cylinders": 6,
        "displacement (cc)": 199,
        "power (hp)": 97,
        "weight (lb)": 2774,
        "0-60 mph (s)": 15.5,
        "year": 70
      },
      {
        "name": "AMC Hornet",
        "economy (mpg)": 18,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 100,
        "weight (lb)": 2945,
        "0-60 mph (s)": 16,
        "year": 73
      },
      {
        "name": "AMC Hornet",
        "economy (mpg)": 19,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 100,
        "weight (lb)": 2901,
        "0-60 mph (s)": 16,
        "year": 74
      },
      {
        "name": "AMC Hornet",
        "economy (mpg)": 22.5,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 90,
        "weight (lb)": 3085,
        "0-60 mph (s)": 17.6,
        "year": 76
      },
      {
        "name": "AMC Matador (Wagon)",
        "economy (mpg)": 14,
        "cylinders": 8,
        "displacement (cc)": 304,
        "power (hp)": 150,
        "weight (lb)": 4257,
        "0-60 mph (s)": 15.5,
        "year": 74
      },
      {
        "name": "AMC Matador (Wagon)",
        "economy (mpg)": 15,
        "cylinders": 8,
        "displacement (cc)": 304,
        "power (hp)": 150,
        "weight (lb)": 3892,
        "0-60 mph (s)": 12.5,
        "year": 72
      },
      {
        "name": "AMC Matador",
        "economy (mpg)": 14,
        "cylinders": 8,
        "displacement (cc)": 304,
        "power (hp)": 150,
        "weight (lb)": 3672,
        "0-60 mph (s)": 11.5,
        "year": 73
      },
      {
        "name": "AMC Matador",
        "economy (mpg)": 15,
        "cylinders": 6,
        "displacement (cc)": 258,
        "power (hp)": 110,
        "weight (lb)": 3730,
        "0-60 mph (s)": 19,
        "year": 75
      },
      {
        "name": "AMC Matador",
        "economy (mpg)": 15.5,
        "cylinders": 8,
        "displacement (cc)": 304,
        "power (hp)": 120,
        "weight (lb)": 3962,
        "0-60 mph (s)": 13.9,
        "year": 76
      },
      {
        "name": "AMC Matador",
        "economy (mpg)": 16,
        "cylinders": 6,
        "displacement (cc)": 258,
        "power (hp)": 110,
        "weight (lb)": 3632,
        "0-60 mph (s)": 18,
        "year": 74
      },
      {
        "name": "AMC Matador",
        "economy (mpg)": 18,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 100,
        "weight (lb)": 3288,
        "0-60 mph (s)": 15.5,
        "year": 71
      },
      {
        "name": "AMC Pacer D/L",
        "economy (mpg)": 17.5,
        "cylinders": 6,
        "displacement (cc)": 258,
        "power (hp)": 95,
        "weight (lb)": 3193,
        "0-60 mph (s)": 17.8,
        "year": 76
      },
      {
        "name": "AMC Pacer",
        "economy (mpg)": 19,
        "cylinders": 6,
        "displacement (cc)": 232,
        "power (hp)": 90,
        "weight (lb)": 3211,
        "0-60 mph (s)": 17,
        "year": 75
      },
      {
        "name": "AMC Rebel SST (Wagon)",
        "economy (mpg)": "",
        "cylinders": 8,
        "displacement (cc)": 360,
        "power (hp)": 175,
        "weight (lb)": 3850,
        "0-60 mph (s)": 11,
        "year": 70
      },
      {
        "name": "AMC Rebel SST",
        "economy (mpg)": 16,
        "cylinders": 8,
        "displacement (cc)": 304,
        "power (hp)": 150,
        "weight (lb)": 3433,
        "0-60 mph (s)": 12,
        "year": 70
      },
      {
        "name": "AMC Spirit DL",
        "economy (mpg)": 27.4,
        "cylinders": 4,
        "displacement (cc)": 121,
        "power (hp)": 80,
        "weight (lb)": 2670,
        "0-60 mph (s)": 15,
        "year": 79
      },
      {
        "name": "Audi 100 LS",
        "economy (mpg)": 20,
        "cylinders": 4,
        "displacement (cc)": 114,
        "power (hp)": 91,
        "weight (lb)": 2582,
        "0-60 mph (s)": 14,
        "year": 73
      },
      {
        "name": "Audi 100 LS",
        "economy (mpg)": 23,
        "cylinders": 4,
        "displacement (cc)": 115,
        "power (hp)": 95,
        "weight (lb)": 2694,
        "0-60 mph (s)": 15,
        "year": 75
      },
      {
        "name": "Audi 100 LS",
        "economy (mpg)": 24,
        "cylinders": 4,
        "displacement (cc)": 107,
        "power (hp)": 90,
        "weight (lb)": 2430,
        "0-60 mph (s)": 14.5,
        "year": 70
      },
      {
        "name": "Audi 4000",
        "economy (mpg)": 34.3,
        "cylinders": 4,
        "displacement (cc)": 97,
        "power (hp)": 78,
        "weight (lb)": 2188,
        "0-60 mph (s)": 15.8,
        "year": 80
      },
      {
        "name": "Audi 5000",
        "economy (mpg)": 20.3,
        "cylinders": 5,
        "displacement (cc)": 131,
        "power (hp)": 103,
        "weight (lb)": 2830,
        "0-60 mph (s)": 15.9,
        "year": 78
      },
      {
        "name": "Audi 5000S (Diesel)",
        "economy (mpg)": 36.4,
        "cylinders": 5,
        "displacement (cc)": 121,
        "power (hp)": 67,
        "weight (lb)": 2950,
        "0-60 mph (s)": 19.9,
        "year": 80
      },
      {
        "name": "Audi Fox",
        "economy (mpg)": 29,
        "cylinders": 4,
        "displacement (cc)": 98,
        "power (hp)": 83,
        "weight (lb)": 2219,
        "0-60 mph (s)": 16.5,
        "year": 74
      },
      {
        "name": "BMW 2002",
        "economy (mpg)": 26,
        "cylinders": 4,
        "displacement (cc)": 121,
        "power (hp)": 113,
        "weight (lb)": 2234,
        "0-60 mph (s)": 12.5,
        "year": 70
      },
      {
        "name": "BMW 320i",
        "economy (mpg)": 21.5,
        "cylinders": 4,
        "displacement (cc)": 121,
        "power (hp)": 110,
        "weight (lb)": 2600,
        "0-60 mph (s)": 12.8,
        "year": 77
      },
      {
        "name": "Buick Century 350",
        "economy (mpg)": 13,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 175,
        "weight (lb)": 4100,
        "0-60 mph (s)": 13,
        "year": 73
      },
      {
        "name": "Buick Century Limited",
        "economy (mpg)": 25,
        "cylinders": 6,
        "displacement (cc)": 181,
        "power (hp)": 110,
        "weight (lb)": 2945,
        "0-60 mph (s)": 16.4,
        "year": 82
      },
      {
        "name": "Buick Century Luxus (Wagon)",
        "economy (mpg)": 13,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 150,
        "weight (lb)": 4699,
        "0-60 mph (s)": 14.5,
        "year": 74
      },
      {
        "name": "Buick Century Special",
        "economy (mpg)": 20.6,
        "cylinders": 6,
        "displacement (cc)": 231,
        "power (hp)": 105,
        "weight (lb)": 3380,
        "0-60 mph (s)": 15.8,
        "year": 78
      },
      {
        "name": "Buick Century",
        "economy (mpg)": 17,
        "cylinders": 6,
        "displacement (cc)": 231,
        "power (hp)": 110,
        "weight (lb)": 3907,
        "0-60 mph (s)": 21,
        "year": 75
      },
      {
        "name": "Buick Century",
        "economy (mpg)": 22.4,
        "cylinders": 6,
        "displacement (cc)": 231,
        "power (hp)": 110,
        "weight (lb)": 3415,
        "0-60 mph (s)": 15.8,
        "year": 81
      },
      {
        "name": "Buick Electra 225 Custom",
        "economy (mpg)": 12,
        "cylinders": 8,
        "displacement (cc)": 455,
        "power (hp)": 225,
        "weight (lb)": 4951,
        "0-60 mph (s)": 11,
        "year": 73
      },
      {
        "name": "Buick Estate Wagon (Wagon)",
        "economy (mpg)": 14,
        "cylinders": 8,
        "displacement (cc)": 455,
        "power (hp)": 225,
        "weight (lb)": 3086,
        "0-60 mph (s)": 10,
        "year": 70
      },
      {
        "name": "Buick Estate Wagon (Wagon)",
        "economy (mpg)": 16.9,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 155,
        "weight (lb)": 4360,
        "0-60 mph (s)": 14.9,
        "year": 79
      },
      {
        "name": "Buick Lesabre Custom",
        "economy (mpg)": 13,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 155,
        "weight (lb)": 4502,
        "0-60 mph (s)": 13.5,
        "year": 72
      },
      {
        "name": "Buick Opel Isuzu Deluxe",
        "economy (mpg)": 30,
        "cylinders": 4,
        "displacement (cc)": 111,
        "power (hp)": 80,
        "weight (lb)": 2155,
        "0-60 mph (s)": 14.8,
        "year": 77
      },
      {
        "name": "Buick Regal Sport Coupe (Turbo)",
        "economy (mpg)": 17.7,
        "cylinders": 6,
        "displacement (cc)": 231,
        "power (hp)": 165,
        "weight (lb)": 3445,
        "0-60 mph (s)": 13.4,
        "year": 78
      },
      {
        "name": "Buick Skyhawk",
        "economy (mpg)": 21,
        "cylinders": 6,
        "displacement (cc)": 231,
        "power (hp)": 110,
        "weight (lb)": 3039,
        "0-60 mph (s)": 15,
        "year": 75
      },
      {
        "name": "Buick Skylark 320",
        "economy (mpg)": 15,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 165,
        "weight (lb)": 3693,
        "0-60 mph (s)": 11.5,
        "year": 70
      },
      {
        "name": "Buick Skylark Limited",
        "economy (mpg)": 28.4,
        "cylinders": 4,
        "displacement (cc)": 151,
        "power (hp)": 90,
        "weight (lb)": 2670,
        "0-60 mph (s)": 16,
        "year": 79
      },
      {
        "name": "Buick Skylark",
        "economy (mpg)": 20.5,
        "cylinders": 6,
        "displacement (cc)": 231,
        "power (hp)": 105,
        "weight (lb)": 3425,
        "0-60 mph (s)": 16.9,
        "year": 77
      },
      {
        "name": "Buick Skylark",
        "economy (mpg)": 26.6,
        "cylinders": 4,
        "displacement (cc)": 151,
        "power (hp)": 84,
        "weight (lb)": 2635,
        "0-60 mph (s)": 16.4,
        "year": 81
      },
      {
        "name": "Cadillac Eldorado",
        "economy (mpg)": 23,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 125,
        "weight (lb)": 3900,
        "0-60 mph (s)": 17.4,
        "year": 79
      },
      {
        "name": "Cadillac Seville",
        "economy (mpg)": 16.5,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 180,
        "weight (lb)": 4380,
        "0-60 mph (s)": 12.1,
        "year": 76
      },
      {
        "name": "Chevroelt Chevelle Malibu",
        "economy (mpg)": 16,
        "cylinders": 6,
        "displacement (cc)": 250,
        "power (hp)": 105,
        "weight (lb)": 3897,
        "0-60 mph (s)": 18.5,
        "year": 75
      },
      {
        "name": "Chevrolet Bel Air",
        "economy (mpg)": 15,
        "cylinders": 8,
        "displacement (cc)": 350,
        "power (hp)": 145,
        "weight (lb)": 4440,
        "0-60 mph (s)": 14,
        "year": 75
      },
      {
        "name": "Chevrolet Camaro",
        "economy (mpg)": 27,
        "cylinders": 4,
        "displacement (cc)": 151,
        "power (hp)": 90,
        "weight (lb)": 2950,
        "0-60 mph (s)": 17.3,
        "year": 82
      },
      {
        "name": "Chevrolet Caprice Classic",
        "economy (mpg)": 13,
        "cylinders": 8,
        "displacement (cc)": 400,
        "power (hp)": 150,
        "weight (lb)": 4464,
        "0-60 mph (s)": 12,
        "year": 73
      },
      {
        "name": "Chevrolet Caprice Classic",
        "economy (mpg)": 17,
        "cylinders": 8,
        "displacement (cc)": 305,
        "power (hp)": 130,
        "weight (lb)": 3840,
        "0-60 mph (s)": 15.4,
        "year": 79
      },
      {
        "name": "Chevrolet Caprice Classic",
        "economy (mpg)": 17.5,
        "cylinders": 8,
        "displacement (cc)": 305,
        "power (hp)": 145,
        "weight (lb)": 3880,
        "0-60 mph (s)": 12.5,
        "year": 77
      }
    ]
    
    
    var margin = {
        top: 30,
        right: 40,
        bottom: 20,
        left: 200
      },
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;
    
    var dimensions = [{
        name: "name",
        scale: d3.scale.ordinal().rangePoints([0, height]),
        type: "string"
      },
      {
        name: "economy (mpg)",
        scale: d3.scale.linear().range([0, height]),
        type: "number"
      },
      {
        name: "cylinders",
        scale: d3.scale.linear().range([height, 0]),
        type: "number"
      },
      {
        name: "displacement (cc)",
        scale: d3.scale.linear().range([height, 0]),
        type: "number"
      },
      {
        name: "power (hp)",
        scale: d3.scale.linear().range([height, 0]),
        type: "number"
      },
      {
        name: "weight (lb)",
        scale: d3.scale.linear().range([height, 0]),
        type: "number"
      },
      {
        name: "0-60 mph (s)",
        scale: d3.scale.linear().range([height, 0]),
        type: "number"
      },
      {
        name: "year",
        scale: d3.scale.linear().range([height, 0]),
        type: "number"
      },
    ];
    
    var x = d3.scale.ordinal()
      .domain(dimensions.map(function(d) {
        return d.name;
      }))
      .rangePoints([0, width]);
    
    var line = d3.svg.line()
      .defined(function(d) {
        return !isNaN(d[1]);
      });
    
    // CREATE A COLOR SCALE
    var color = d3.scale.ordinal()
      .domain(['Buick', 'Chevrolet', 'Dodge'])
      .range(['red', 'blue', 'green'])
    
    var yAxis = d3.svg.axis()
      .orient("left");
    
    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 + ")");
    
    var dimension = svg.selectAll(".dimension")
      .data(dimensions)
      .enter().append("g")
      .attr("class", "dimension")
      .attr("transform", function(d) {
        return "translate(" + x(d.name) + ")";
      });
    
    function parallelchart(data) {
      dimensions.forEach(function(dimension) {
        dimension.scale.domain(dimension.type === "number" ?
          d3.extent(data, function(d) {
            return +d[dimension.name];
          }) :
          data.map(function(d) {
            return d[dimension.name];
          }).sort());
      });
    
      svg.append("g")
        .attr("class", "background")
        .selectAll("path")
        .data(data)
        .enter().append("path")
        .attr("d", draw);
    
      /*   svg.append("g")
            .attr("class", "foreground")
          .selectAll("path")
            .data(data)
          .enter().append("path")
            .attr("d", draw); */
    
      // USE THE COLOR SCALE TO SET THE STROKE BASED ON THE DATA
      foreground = svg.append("g")
        .attr("class", "foreground")
        .selectAll("path")
        .data(data)
        .enter().append("path")
        .attr("d", draw)
        .style("stroke", function(d) {
          var company = d.name.slice(0, d.name.indexOf(' '));
          return color(company);
        })
    
    
      dimension.append("g")
        .attr("class", "axis")
        .each(function(d) {
          d3.select(this).call(yAxis.scale(d.scale));
        })
        .append("text")
        .attr("class", "title")
        .attr("text-anchor", "middle")
        .attr("y", -9)
        .text(function(d) {
          return d.name;
        });
    
      var ordinal_labels = svg.selectAll(".axis text")
        .on("mouseover", mouseover)
        .on("mouseout", mouseout);
    
      var projection = svg.selectAll(".background path,.foreground path")
        .on("mouseover", mouseover)
        .on("mouseout", mouseout);
    
      function mouseover(d) {
        svg.classed("active", true);
    
        // this could be more elegant
        if (typeof d === "string") {
          projection.classed("inactive", function(p) {
            return p.name !== d;
          });
          projection.filter(function(p) {
            return p.name === d;
          }).each(moveToFront);
          ordinal_labels.classed("inactive", function(p) {
            return p !== d;
          });
          ordinal_labels.filter(function(p) {
            return p === d;
          }).each(moveToFront);
        } else {
          projection.classed("inactive", function(p) {
            return p !== d;
          });
          projection.filter(function(p) {
            return p === d;
          }).each(moveToFront);
          ordinal_labels.classed("inactive", function(p) {
            return p !== d.name;
          });
          ordinal_labels.filter(function(p) {
            return p === d.name;
          }).each(moveToFront);
        }
      }
    
      function mouseout(d) {
        svg.classed("active", false);
        projection.classed("inactive", false);
        ordinal_labels.classed("inactive", false);
      }
    
      function moveToFront() {
        this.parentNode.appendChild(this);
      }
    }
    
    function draw(d) {
      return line(dimensions.map(function(dimension) {
        return [x(dimension.name), dimension.scale(d[dimension.name])];
      }));
    }
    
    parallelchart(data);
    svg {
      font: 12px sans-serif;
    }
    
    .background path {
      fill: none;
      stroke: none;
      stroke-width: 20px;
      pointer-events: stroke;
    }
    
    .foreground path {
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;
    }
    
    .axis .title {
      font-size: 11px;
      font-weight: bold;
      text-transform: uppercase;
    }
    
    .axis line,
    .axis path {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }
    
    .axis.string {
      font-size: 6px;
    }
    
    .label {
      -webkit-transition: fill 125ms linear;
    }
    
    .active .label:not(.inactive) {
      font-weight: bold;
      font-size: 11px;
    }
    
    .label.inactive {
      fill: #ccc;
    }
    
    .foreground path.inactive {
      stroke: #ccc;
      stroke-opacity: .5;
      stroke-width: 1px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多