Сопоставление строки с указанным c цветом каждый раз? - PullRequest
1 голос
/ 21 января 2020

Моя цель: Я пытаюсь создать диаграмму ap ie, каждый «срез» будет связан с меткой. На странице будет несколько диаграмм p ie, и каждый p ie может иметь разное количество меток, но я хочу, чтобы каждая метка имела свой собственный цвет, независимо от того, сколько всего там меток за p ie.

Например, P ie один имеет метку 1, 2, 3, 4, а P ie два имеет метку 1, 3, 4. P ie один цвет будет be, красный, синий, зеленый, фиолетовый и P ie 2 среза должны быть красного, зеленого, фиолетового.

Моя методология: Согласно документации d3, я веду к полагайте, что следующая конфигурация будет работать.

let color = d3.scaleOrdinal()
    .range(['red','blue','green','purple'])
    .domain('Label 1','Label 2', 'Label 3','Label 4')

Метка 3 ВСЕГДА вернется зеленым, если я

console.log(color('Label 3')

Проблема:

Сейчас, Я увеличил масштаб и использовал фиктивные данные (объект данных будет больше). Вместо того, чтобы вручную вводить домен, я создал массив. Чтобы учесть разницу в возможностях надписей, я «хэшировал» каждое значение с большим индексом (между 0-10000), то же самое для цветов.

Моя теория такова: если у меня есть массив 10k, а метка 1 находится в индексе 9015, я ожидаю, что при выполнении color('Label 1') вернется фиолетовый , потому что (9015 % 4) = 3 означает индекс 9015 в массиве цветов должен быть фиолетовым (что я проверил с помощью console.log).

Вместо него возвращается синий , и я не понимаю, почему.

Ниже приведен мой исходный код

// Create dummy data
var data = {
    "Label 1": {count: "1"},
    "Label 2": {count: "5"},
    "Label 3": {count: "5"},
    "Label 4": {count: "39"},
    "Label 5": {count: "32"},
    "Label 6": {count: "5"},
    "Label 7": {count: "7"},
    "Label 8": {count: "1"}
}

// This will create an Array of 10k colors looping the base 4 colors
// example: ['red', 'blue', 'green', 'purple','red', 'blue', 'green'...]
let availableColors = createColorArray() 

// An empty array of 10k, Labels will get a new index, and be placed here.
let hash_array = new Array(10000)
hash_array.fill("")

var color = d3.scaleOrdinal()
    .range(availableColors)
    .domain(hash_array)
Object.keys(data).forEach(element => {

    // Map Hash Stuff
    let hash = computeHash(element)
    hash_array[hash] = element;
    console.log(element + ' = ' + hash)
})

console.log("======================================================================")
Object.keys(data).forEach(element => {
    console.log(element + ' = ' + color(element) + " | Color at index: " + availableColors[computeHash(element)])
})

Мой вывод:

Label 1 = blue | Color at index: purple
Label 2 = green | Color at index: green
Label 3 = purple | Color at index: blue
Label 4 = red | Color at index: red
Label 5 = blue | Color at index: purple
Label 6 = green | Color at index: green
Label 7 = purple | Color at index: blue
Label 8 = red | Color at index: red

Мой ожидаемый вывод Я ожидаю, что цвет, возвращаемый функцией color (), будет равен цвету, найденному в индексе того места, где находится эта метка.

Label 1 = purple| Color at index: purple
Label 2 = green | Color at index: green
Label 3 = blue| Color at index: blue
Label 4 = red | Color at index: red
Label 5 = purple| Color at index: purple
Label 6 = green | Color at index: green
Label 7 = blue| Color at index: blue
Label 8 = red | Color at index: red

1 Ответ

2 голосов
/ 22 января 2020

Существует недоразумение относительно того, как порядковая шкала работает в D3. Суть в том, что значения доменов должны быть уникальными .

внутренне , порядковый масштаб D3 использует карту JavaScript для создания таблицы доменов / диапазонов. Хотя в качестве ключа карты можно использовать пустую строку (""), в результате использования нескольких пустых строк все последующие будут игнорироваться.

Как API объясняет (выделено мое):

Значения домена хранятся внутри карты от строкового значения до индекса; результирующий индекс затем используется для извлечения значения из диапазона. Таким образом, значения порядковой шкалы должны быть принудительно введены в строку, а строковая версия значения домена однозначно идентифицирует соответствующее значение диапазона.

Посмотрите на эту основу c demo (обращая внимание на пустые строки в массиве домена): согласно вашим логам c, возвращаемые значения для Label 1 (третья позиция, индекс 2) и Label 2 (последняя позиция, индекс 7) должны быть green и purple (3-я и 8-я позиции в массиве диапазонов)

const scale = d3.scaleOrdinal()
  .range(['red', 'blue', 'green', 'purple', 'red', 'blue', 'green', 'purple'])
  .domain(['', '', 'Label 1', '', '', '', '', 'Label 2']);

console.log(scale('Label 1'));
console.log(scale('Label 2'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Как вы можете ясно видеть, это не результат. Здесь происходит то, что первая пустая строка связана с red, как и ожидалось. Однако вторая пустая строка не получает следующее значение диапазона (blue), и то же самое происходит со всеми другими пустыми строками: они игнорируются. Таким образом, следующее уникальное значение Label 1 получает следующее значение диапазона (blue), в то время как уникальное значение после этого (Label 2) получает последующее значение диапазона (green), и т. д.

Наконец, о том, как исправить ваш подход: для избежания проблемы classi c XY, пожалуйста, опубликуйте новый вопрос (не редактируйте этот) с желаемым результатом, чтобы мы могли помочь Вы с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...