Понимание функции доступа (d) - PullRequest
1 голос
/ 26 мая 2020
var cs1 = drawCircles(svg1,data,d=>d["A"],d=>d["B"],sc1); 

Пытаемся интуитивно понять, как d используется при связывании. Вышеупомянутая функция вызывает .append('circle') и использует две функции доступа d=>d["A"], d=>d["B"] для размещения кругов.

Я понимаю, что d, по сути, действует как итерация для «данных» и что здесь мы неявно возвращение d['B']. Я не понимаю, почему мы не можем просто передать d нефункциональным способом, например drawCircles(...,d['A'] ,...). Когда я пробовал использовать d таким образом, он возвращает d, не определено.

Используя более простой пример,

svg.selectAll('circle').data(data).enter.append('circle')
  .attr('id', (d) => {return d['name']})

Почему я не могу просто указать d['name'] для второго arg of .attr()

Как я могу рассуждать об использовании d исключительно в качестве аргумента функции?

Спасибо!

1 Ответ

1 голос
/ 26 мая 2020

2-й параметр .style () /. Attr ()

При использовании чего-то вроде:

.attr("fill", someParameter);

D3 проверяет, someParameter - функция или константа.

Если someParameter - константа, «всем элементам присваивается одно и то же значение атрибута», в конце концов, мы используем константу. ( см. Также документацию D3 ).

Если someParameter - функция, D3 использует function.apply() ( см. Также документацию MDN function.apply () ) для вызова этой функции для каждого элемента в выделенном фрагменте, предоставляя его с 3 параметрами:

  • текущие данные (по соглашению d),
  • индекс текущего элемента (по соглашению i),
  • и группу узлов в выбранном (противоречивое соглашение, я буду использовать здесь nodes).

Использование apply также позволяет указать this, который является текущим элементом (который также: nodes[i]).

Использование of function.apply () определяет d, i и nodes только внутри предоставленной функции.

Это имеет смысл, если вы предоставляете константу, нечего применять, э-э, применять и не нужно.


Что происходит, когда вы указываете d [ 'name'] в качестве второго аргумента для .style () /. attr ()

При использовании:

.attr("fill", d.color)`

d в приведенном выше примере не имеет отношения к данные. Если вы не объявили d и не присвоили ему свойство color, здесь оно будет неопределенным. D3 не вызывает здесь функцию с применением для определения d - вы не предоставляете функцию для этого.

Только если d.color оценивается как function(d) { return d.color; }, вы сможете сделать о чем вы спрашиваете. Это была бы очень необычная форма с D3 .

Если d не определено, вы, скорее всего, выдадите ошибку при доступе к d.color, как вы видели. Если d определено, но d.color не является функцией, оно будет рассматриваться как константа, и каждый элемент получит свойство с тем же значением.

Следовательно, поэтому мы видим формат:

.attr("fill", function(d,i,nodes) { return ... });

Stop Here

Теоретически возможно , но не рекомендуется, чтобы выполнить sh то, что, по вашему мнению, должно быть возможным.

Я делюсь только потому, что

  • У меня это валялось на while
  • Он показывает, сколько обходного пути требуется для достижения шаблона, о котором вы спрашиваете (без предварительного определения ваших функций как свойств некоторого объекта с именем d).

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

Здесь вы можете использовать форму:

.attr("fill", d.color) 

При доступе к любому из свойств прокси (d) (здесь color) необходимо будет вернуть соответствующую функцию доступа. (function(d) { return d.color;}), который затем будет передан в .attr(), и к нему будут привязаны соответствующие данные. Вы можете использовать только свойство, вы не сможете использовать d.x + 2.

// create a proxy `d` to return accessor functions, 
var d = new Proxy({},{ get: f })

var data = [
  {style:{fill:"steelblue",stroke:{color:"crimson", width:4}},width: 30, y: 50, x: 10},
  {style:{fill:"yellow",stroke:{color:"orange", width:2}},width: 20, y: 50, x: 50},
  {style:{fill:"crimson",stroke:{color:"steelblue", width:8}},width: 30, y: 50, x: 80}
]

var svg = d3.select("body").append("svg");

svg.selectAll(null)
  .data(data)
  .enter()
  .append("rect")
  .attr("x", d.x)
  .attr("y", d.y)
  .attr("width", d.width)
  .attr("height",d.width)
  .attr("fill",d.style.fill)
  .attr("stroke-width",d.style.stroke.width)
  .attr("stroke", d.style.stroke.color);
  
  
  
// To resolve paths (https://stackoverflow.com/a/45322101/7106086):
function resolve(path, obj) {
    return path.reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}
// Proxy to dynamically access properties of any depth:
function f(obj, prop) {
    if(prop in obj) return obj[prop];
    else { 
       var g = function() {
          var accessor = function(d) {
            return resolve(accessor._path_,d);
          }
          // keep track of path:
          if(obj._path_) accessor._path_ = [...obj._path_,prop];
          else (accessor._path_) = [prop];
          return accessor;
       }
       return obj[prop] = new Proxy(g(), {get:f});     
    }
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...