Как обновить цвет заливки на существующих элементах svg с помощью d3.js?
Итак, я пытаюсь сделать карту из Ан .svg-файл я создал с помощью Illustrator, потому что это карта Нидерландов с не такими простыми регионами.
Все регионы имеют свой собственный # ID.
Теперь я пытаюсь раскрасить каждую область в соответствии с их значением в наборе данных. Я могу заставить цвет на регионах с помощью CSS я сделал это на одном регионе, но это, очевидно, не хорошее решение.
Если я, например, попытаюсь выбрать(#id), а затем изменить.attr ("заполнение", "красный"); он не делает работа.
Как бы я обновил цвета области по id, используя d3.js в соответствии со значением d[1] в наборе данных ?
Файлы: https://gist.github.com/gordonhatusupy/9466794
Прямая связь: http://www.gordonjakob.me/regio_map/
1 ответ:
Проблема в том, что ваш файл Illustrator уже определяет цвета заливки для отдельных элементов
Есть пара вещей, которые вы можете сделать, чтобы изменить его:<path>
, а значения идентификаторов-для родительских элементов<g>
. Дочерние элементы наследуют стили от родителей, но только в том случае, если у дочернего элемента нет собственных значений.
Измените файл Illustrator так, чтобы пути не были заполнены. Затем они унаследуют цвет заливки, установленный на родитель.
Выберите пути напрямую, используя
d3.selectAll("g#id path")
илиd3.select("g#id").selectAll("path")
; в любой версии будут выбраны все элементы<path>
, являющиеся потомками элемента<g>
с идентификатором "id". Затем вы можете установить атрибут fill непосредственно для перезаписи значения из Illustrator.
Как обсуждалось в комментариях к основному вопросу, если вы хотите сделать этот шаг дальше и фактически присоединить данные к элементам для дальнейшего использования (например, в обработчике событий), проще всего способ заключается в циклическом просмотре набора данных, выделении каждого элемента, а затем использовании
.datum(newData)
способ прикрепления данных к каждому элементу:dataset.forEach(function(d){ //d is of form [id,value] d3.select("g#"+d[0]) //select the group matching the id .datum(d) //attach this data for future reference .selectAll("path, polygon") //grab the shapes .datum(d) //attach the data directly to *each* shape for future reference .attr("fill", colour(d[1]) ); //colour based on the data });
Если вы хотите иметь возможность выбрать все элементы верхнего уровня
<g>
в будущем, я бы предложил также дать им класс, чтобы вы могли выбрать их, например,d3.select("g.region")
. Например:dataset.forEach(function(d){ //d is of form [id,value] d3.select("g#"+d[0]) //select the group matching the id .datum(d) //attach this data for future reference .classed("region", true) //add a class, without erasing any existing classes .selectAll("path, polygon") //grab the shapes .datum(d) //attach the data directly to *each* shape for future reference .attr("fill", colour(d[1]) ); //colour based on the data }); d3.selectAll("g.region") .on("click", function(d,i) { infoBox.html("<strong>" + d[0] + ": </strong>" + d[1] ); //print the associated data to the page });
Пример реализации: http://jsfiddle.net/ybAj5/7/
Хотя использование
dataset.forEach
не кажется полным использованием возможностей d3, на самом деле это намного проще, чем пытаться присоединить весь набор данных сразу - тем более, что существует такая вариабельность в структуре областей, некоторые из которых имеют вложенные<g>
элементы://Option two: select all elements at once and create a datajoin d3.selectAll("g[id]") //select only g elements that have id values .datum(function(){ var id=d3.select(this).attr("id"); return [id, null]; }) //create an initial [id, value] dataset based on the id attribute, //with null value for now .data(dataset, function(d){return d[0];}) //use the first entry in [id,value] as the key //to match the dataset with the placeholder data we just created for each .selectAll("path, polygon") //grab the shapes .datum(function(){ return d3.select(this.parentNode).datum() || d3.select(this.parentNode.parentNode).datum(); }) //use the parent's data if it exists, else the grandparent's data .attr("fill", function(d){return d?colour(d[1]):"lightgray";}); //set the colour based on the data, if there is a valid data element //else use gray.
Эта скрипка показывает приведенный выше код в действии, но я снова рекомендую использовать подход
forEach
.
Comments