Путаница с d3.interpolateObject - PullRequest
       21

Путаница с d3.interpolateObject

0 голосов
/ 05 декабря 2018

Я только что исследовал функцию D3 Interpolate Object , и заметил какое-то странное поведение.Тем не менее, я не очень знаком с D3, так что, может быть, я просто что-то неправильно понимаю.С учетом следующих данных и функции интерполяции:

var a = {"Country": "Ireland", "Year": 2010, "Data": 10};
var b = {"Country": "Ireland", "Year": 2015, "Data": 50};

var iFunc = d3.interpolateObject(a, b);

Следующие результаты соответствуют ожидаемым:

console.log(iFunc(0.2)) // Returns: { Country: "Ireland", Year: 2011, Data: 18 }
console.log(iFunc(0.4)) // Returns: { Country: "Ireland", Year: 2012, Data: 26 }

Однако, когда оба вызова функций включены в один и тот же консольный журнал, например:

console.log(iFunc(0.2), iFunc(0.4)) 

Выходной результат - просто второй объект дважды:

{ Country: "Ireland", Year: 2012, Data: 26 } { Country: "Ireland", Year: 2012, Data: 26 }

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

console.log([iFunc(0.2), iFunc(0.4)])

Предыдущий результат умножается на два:

[{ Country: "Ireland", Year: 2014, Data: 42 }, { Country: "Ireland", Year: 2014, Data: 42 }]

Что здесь происходит?

Причина, по которой я исследую это, заключается в том, что я хотел бы создать серию промежуточных объектов, используя что-токак:

var iVals = d3.range(0, 1, 0.2).map( iFunc );

Если кто-нибудь покажет мне, как я могу этого достичь, я буду очень признателен!

1 Ответ

0 голосов
/ 05 декабря 2018

Это интересная проблема.Объяснение можно найти в собственной документации :

Примечание: защитная копия объекта шаблона не создается;Модификации возвращенного объекта могут отрицательно повлиять на последующую оценку интерполятора .Никакая копия не сделана по причинам производительности;Интерполяторы часто являются частью внутреннего цикла анимированных переходов.(выделение мое)

Как видите, если вы используете тот же интерполятор, вы получите странный результат, который вы описали (откройте консоль вашего браузера, не используйте фрагмент):

var a = {
  "Country": "Ireland",
  "Year": 2010,
  "Data": 10
};
var b = {
  "Country": "Ireland",
  "Year": 2015,
  "Data": 50
};

var iFunc = d3.interpolateObject(a, b);

var iVals = d3.range(0, 1, 0.2).map(iFunc);

console.log(iVals)
<script src="https://d3js.org/d3.v5.min.js"></script>

Итак, простейшим решением является определение функции интерполяции внутри map():

var iVals = d3.range(0, 1, 0.2).map(function(d) {
  return d3.interpolateObject(a, b)(d)
});

Вот демонстрационная версия:

var a = {
  "Country": "Ireland",
  "Year": 2010,
  "Data": 10
};
var b = {
  "Country": "Ireland",
  "Year": 2015,
  "Data": 50
};

var iVals = d3.range(0, 1, 0.2).map(function(d) {
  return d3.interpolateObject(a, b)(d)
});

console.log(iVals)
<script src="https://d3js.org/d3.v5.min.js"></script>

В качестве альтернативы создайте функцию, которая возвращает интерполятор:

var iFunc = function(d) {
    return d3.interpolateObject(a, b)(d)
};

var iVals = d3.range(0, 1, 0.2).map(iFunc);

Вот соответствующая демонстрационная программа:

var a = {
  "Country": "Ireland",
  "Year": 2010,
  "Data": 10
};
var b = {
  "Country": "Ireland",
  "Year": 2015,
  "Data": 50
};

var iFunc = function(d) {
  return d3.interpolateObject(a, b)(d)
};

var iVals = d3.range(0, 1, 0.2).map(iFunc);

console.log(iVals)
<script src="https://d3js.org/d3.v5.min.js"></script>

PS: Не относится к вашему вопросу, но значение «стоп» в d3.range() не включено.Итак, если вы хотите получить значения в объекте b, оно должно быть:

d3.range(0, 1.2, 0.2)

Вот оно:

var a = {
  "Country": "Ireland",
  "Year": 2010,
  "Data": 10
};
var b = {
  "Country": "Ireland",
  "Year": 2015,
  "Data": 50
};

var iVals = d3.range(0, 1.2, 0.2).map(function(d) {
  return d3.interpolateObject(a, b)(d)
});

console.log(iVals)
<script src="https://d3js.org/d3.v5.min.js"></script>
...