2017-01-04 12 views
0

У меня 100 прямоугольников расположены в квадрате 10x10. Я хочу цвет число прямоугольников согласно номерам в следующем массивеКак заполнить число прямоугольников в строке, соответствующей номерам в массиве. d3.js

var avg = [1, 4, 4, 7, 11, 15, 58] 

Я застрял на значение 4, так как он появляется в два раза плюс код выглядит очень некрасиво. Есть ли лучший способ достичь этого, не используя if/else?

Выход должен быть 1 прямоугольник должен иметь цвет от цвета [0], а затем 4 Прямоугольники из цветов 1 и следующий 4 из цветов [2] и так далее. JS fiddle вот мой код:

var avg = [1, 4, 4, 7, 11, 15, 58] 
var colors = ['#009BFF', '#AAC30A', '#DC0f6e', '#82b905', '#96be00', '#C8D205', 
    '#82141E', '#BE232D', '#E14614', '#EB6E14', '#EB8614', '#F0AA00' 
] 

var ContainerWidth = document.querySelector('#mainContainer').offsetWidth; 
var rectWidth = ContainerWidth/20 
var svgContainer = d3.select("#boxy") 

var rectangle = svgContainer.selectAll("rect") 
    .data(d3.range(100)); 

var rectangle = rectangle.enter() 
    .append("rect") 
    .style("stroke", "#fff") 
    .style("fill", function(d, i){ 
    for(var k=0; k<avg.length; k++){ 
    if(i<=avg[0]-1){ 
      return colors[0] 
      } else if(i<=avg[1] && i>=avg[0]-1){ 
      return colors[1] 
      } else if(i<=avg[2]-1 && i>=avg[1]-1 || avg[2]-1===avg[1]-1){ 
      return colors[2] 
      } else if(i<=avg[3]-1 && i>=avg[2]-1){ 
      return colors[3] 

      } 
    } 
    }) 
    .attr("x", function(d, i) { 
    return i % 10 * 45 
    }) 
    .attr("y", function(d, i) { 
    return Math.floor(i/10) % 10 * 45 
    }) 
    .attr("width", rectWidth) 
    .attr("height", rectWidth); 
+0

Есть множество примеров вокруг о том, как создать сетку из некоторых элементов, например, , [* «Фильтрация сетки» *] (http://bl.ocks.org/herrstucki/5710596) и [* «Сортировка сетки» *] (http://bl.ocks.org/herrstucki/5694697) , – altocumulus

ответ

2

Есть несколько подходов можно принять. Основная проблема заключается в том, что в вашем массиве данных не содержится 100 элементов, соответствующих вашим 100 прямоугольникам. Как вы не можете привязать эти данные к вашим элементам svg.

Вы можете создать массив данных длиной 100 единиц и использовать его для создания прямоугольников (вместо d3.range(100)). Или вы можете использовать пользовательскую функцию, добавляя прямоугольники для определения цвета.


Для первого подхода, вы могли бы сделать переменную данных, длиной 100 пунктов (или что-то общее количество всех ваших avg элементов массива):

var avg = [1, 4, 4, 7, 11, 15, 58]; 
var data = []; 
var category = 0; 

for (i = 0; i < avg.length; i++) { 
    for (j=0; j < avg[i]; j++) { 
    data.push(category); 
    } 
    category++; 
} 

данные: [ 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 90 more… ]

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

var rectangle = svgContainer.selectAll("rect") 
    .data(data) 
    .enter() 
    .append("rect") 
    .style("fill", function(d) { return colors[d]; }) 

Fiddle: https://jsfiddle.net/e44y72v8/


Или вы могли бы держать d3.range(100), чтобы добавить 100 прямоугольниками, но использовать функцию, чтобы определить, какой цвет должен быть применен. Это требует отслеживания совокупной совокупности элементов массива, когда мы продвигаемся через 100 прямоугольников. Это требует двух новых переменных:

var currentIndex = 0; // What element of the array are we at 
var cumulative = 0; // What is the cumulative total of all array elements between 0 and current index. 

И ваша функция может выглядеть следующим образом:

.style("fill", function(d, i){ 
    if (i == cumulative) { 
     cumulative += avg[currentIndex+1]; 
     return colors[currentIndex++]; 
     } 
    else { 
      return colors[currentIndex];  
    } 

    }) 

Fiddle: https://jsfiddle.net/sttL9vaz/