Ошибка: недопустимое значение для атрибута <path> - во время перехода проекции d3 - бесконечность и NaN
Я работаю над переходом между ортогональной проекцией и проекцией Меркатора на интерактивной карте (масштабирование + перетаскивание) мира. Я основал свою попытку на этом ответе @mbostock. Мой переход работает хорошо, но консоль возвращает это:
Ошибка: недопустимое значение для атрибута D = "M399.97994119370463,631.2543931983346L401.90905516286807,634.6157013775801L402.49382423943246,639.8924592362391L397.1999166487309,.......,InfinityL492, InfinityL298.23496934976544, InfinityZ"
также
Ошибка: Недопустимое значение атрибута г = "M407.5277462873383,448.4656515493841L407.3237573717514,448.5198670656254L408.0599991645186,448.54332648718287L408.0215749188842,448.4385574971469ZM410.40575858016456,448.5990104765492L410.8017911794915,448.571665201377L411.4470970198755..., NaNL415, NaNL415,NaNZM415, NaNL415, NaNL415, NaNZM415, NaNL415, 449.0295187376797L415,449.0295187376797L414.9999381778805,449.02952802059315L415,449.02952802059315L418.41200394
Я использую topoJson из шейп-файла Natural Earth и получаю только одну из этих ошибок пути каждый раз, когда возвращается функция анимации движения. Я считаю, что это означает, что только один элемент пути, который имеет эту проблему.
Вот мои методы перехода, которые у меня есть в классе проекции:
animation(timeout, newProjection) {
let self = this;
let projection = this.interpolatedProjection(this.prjFnc, newProjection);
let path = d3.geo.path().projection(projection);
this.svg.transition()
.duration(timeout / 2)
.tween('projection', function() {
return function(_) {
self.alpha(_);
self.svg.selectAll('path').attr('d', path);
};
});
}
interpolatedProjection(a, b) {
let self = this;
this.a = a;
this.b = b;
this.α = null;
function raw(λ, φ) {
let pa = self.a([λ *= 180 / Math.PI, φ *= 180 / Math.PI]), pb = self.b([λ, φ]);
return [(1 - self.α) * pa[0] + self.α * pb[0], (self.α - 1) * pa[1] - self.α * pb[1]];
}
this.intProjection = d3.geo.projection(raw).scale(1);
this.center = this.intProjection.center;
this.translate = this.intProjection.translate;
delete this.intProjection.scale;
delete this.intProjection.translate;
delete this.intProjection.center;
return this.alpha(0.1);
}
alpha(_) {
if(!arguments.length) {
return this.α;
}
this.α = +_;
let ca = this.a.center(),
cb = this.b.center(),
ta = this.a.translate(),
tb = this.b.translate();
this.center(
[(1 - this.α) * ca[0] + this.α * cb[0],
(1 - this.α) * ca[1] + this.α * cb[1]]
);
this.translate(
[Math.round((1 - this.α) * ta[0] + this.α * tb[0]),
Math.round((1 - this.α) * ta[1] + this.α * tb[1])]
);
return this.intProjection;
}
Какие-нибудь мысли?
1 ответ
Ошибки бесконечности были вызваны путями, которые пытались нарисовать вне svg. Мне удалось устранить эти ошибки, добавив экстент обрезки к интерполированной проекции.
interpolatedProjection(a, b) {
let self = this;
this.a = a;
this.b = b;
this.α = null;
function raw(λ, φ) {
let pa = self.a([λ *= 180 / Math.PI, φ *= 180 / Math.PI]), pb = self.b([λ, φ]);
return [(1 - self.α) * pa[0] + self.α * pb[0], (self.α - 1) * pa[1] - self.α * pb[1]];
}
this.intProjection = d3.geo.projection(raw).scale(1)
.clipExtent(this.extent); // this addition
this.center = this.intProjection.center;
this.translate = this.intProjection.translate;
delete this.intProjection.scale;
delete this.intProjection.translate;
delete this.intProjection.center;
return this.alpha(0.1);
}
Я также получал ошибку NaN в атрибуте d, которую я смог удалить, не позволив индексу анимации достичь значения 1.
animation(timeout, newProjection) {
let self = this;
let projection = this.interpolatedProjection(this.prjFnc, newProjection);
let path = d3.geo.path().projection(projection);
this.svg.transition()
.duration(timeout)
.tween('projection', function() {
return function(_) {
if (_ === 1) { return; } // This addition
self.alpha(_);
self.paths.attr('d', path);
};
});
}