Заполнение столбчатой диаграммы цветами, взвешенными по значению данных, с помощью svg

#javascript #html #d3.js #svg

#javascript #HTML #d3.js #svg

Вопрос:

Привет, я пытаюсь сделать так, чтобы гистограмма имела уменьшающиеся оттенки синего в зависимости от значения данных. Однако в настоящее время мой код изменяет только 1-ю строку. Текущая диаграмма

  d3.csv("GDP2016TrillionUSDollars.csv",function(error, data){
    data.forEach(function(d) {
        d.key = d.key;
        d.value =  d.value;
    });

   xScale.domain(data.map(function(d){ return d.key; }));
    yScale.domain([0,d3.max(data, function(d) {return d.value; })]);
   
svg.selectAll('rect')
        .data(data)
        .enter()
        .append('rect')
        .attr("height", 0) 
        .attr("y", height)
        .attr({
            "x": function(d) { return xScale(d.key); },
            "y": function(d) { return yScale(d.value); },
            "width": xScale.rangeBand(),
            "height": function(d) { return  height - yScale(d.value); },
            // create increasing to decreasing shade of blue as shown on the output
             "fill": function(d) { return "rgb(0, 0, "    (height - yScale(d.value))   ")";}
             });  

Ответ №1:

Я не смог заставить код, который вы вставили, работать, если вы можете использовать рабочую реализацию, я могу помочь дальше. Но для свойства fill попробуйте использовать style, а не attr, поскольку это может быть переопределено CSS.

 .style('fill', 
    function (d) { 
        return "rgb(0, 0, "    (height - yScale(d.value))   ")";
    }
});
  

Надеюсь, это поможет.

Ответ №2:

Причина, по которой вы видите, что черный цвет перестраивается, заключается в том, что вы передаете нецелые значения в RGB. Согласно W3C:

Формат значения RGB в функциональной нотации — ‘rgb(‘, за которым следует разделенный запятыми список из трех числовых значений (либо трех целых значений, либо трех процентных значений), за которым следует ‘)’. (выделение мое)

Таким образом, просто сделайте это:

 "fill": function(d) { return "rgb(0, 0, "    Math.floor((height - yScale(d.value)))   ")";
  

При этом манипулирование значениями RGB может быть немного сложным. Я предлагаю вам создать шкалу для ваших цветов, чтобы вы могли легко изменять ее так, как хотите:

 var colours = d3.scaleLinear()
    .domain([minValue, maxValue])//your domain values go here
    .range(["gray", "blue"]);
//first colour--^     ^--last colour
  

А затем с помощью

 .style("fill", function(d){ return colours(d.value)})
  

Проверьте демонстрацию:

 var w = 500, h = 200, padding = 20;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var data = [{name: "foo", value:50},
            {name: "bar", value:170},
            {name: "baz", value: 120},
           {name: "foobar", value:10},
           {name: "foobaz", value:70},
           {name: "barbaz", value:140}];

var colours = d3.scaleLinear()
  .domain([0, 170])
  .range(["gray", "blue"]);

var xScale = d3.scaleBand()
  .range([0,w])
  .domain(data.map(function(d){ return d.name}))
  .paddingInner(0.2)
  .paddingOuter(0.2);

var xAxis = d3.axisBottom(xScale);

var bars = svg.selectAll(".bars")
  .data(data)
  .enter()
  .append("rect");

bars.attr("x", function(d){ return xScale(d.name)})
  .attr("width", xScale.bandwidth())
  .attr("y", function(d){ return (h - padding) - d.value})
  .attr("height", function(d){ return d.value})
  .style("fill", function(d){ return colours(d.value)})

var gX = svg.append("g")
  .attr("transform", "translate(0,"   (h - padding)   ")")
  .call(xAxis);  
 <script src="https://d3js.org/d3.v4.min.js"></script>  

PS: Вы используете v3, поэтому измените scaleLinear() на scale.linear() .