Я не буду вдаваться в различия между v3 и v5 отчасти потому, что прошло достаточно много времени, и я забыл многие детали и детали относительно того, как v3 отличался.Вместо этого я просто посмотрю, как реализовать этот пример с v5. Этот ответ потребует адаптации для негеографических случаев - в этом случае географическая проекция выполняет визуальное масштабирование.
В вашем примере масштабирование отслеживает состояние масштабирования, чтобыустановить проекцию правильно.Масштабирование не устанавливает преобразование ни к одному элементу SVG, вместо этого проекция репроецирует объекты при каждом увеличении (или щелчке).
Итак, чтобы начать работу с d3v5, после того, как мы вызовем масштабирование нашего выбора, мыможно установить масштаб выбранного элемента с помощью:
selection.call(zoom.transform, transformObject);
Если базовый объект преобразования:
d3.zoomIdentity
d3.zoomIdentity имеет масштаб (k), равный 1, перевод x (x)) и значения y (y), равные 0. В прототип идентичности встроены некоторые методы, поэтому простой объект не подойдет, но мы можем использовать идентичность, чтобы установить новые значения для k, x и y:
var transform = d3.zoomIdentity;
transform.x = projection.translate()[0]
transform.y = projection.translate()[1]
transform.k = projection.scale()
Это очень похоже на пример, но вместо того, чтобы предоставлять значения для самого поведения масштабирования, мы создаем объект, который описывает состояние масштабирования.Теперь мы можем использовать selection.call(zoom.transform, transform)
, чтобы применить преобразование.Это будет:
- установить преобразование масштабирования на предоставленные значения
- вызвать событие масштабирования
В нашей функции масштабирования мы хотим получить обновленное масштабированиепреобразовать, применить его к проекции, а затем перерисовать наши пути:
function zoomed() {
// Get the new zoom transform
transform = d3.event.transform;
// Apply the new transform to the projection
projection.translate([transform.x,transform.y]).scale(transform.k);
// Redraw the features based on the updaed projection:
g.selectAll("path").attr("d", path);
}
Примечание - d3.event.translate
и d3.event.scale
ничего не вернут в d3v5 - теперь это x, y,k свойств d3.event.transform
Без функции щелчка мы можем получить this , что напрямую адаптировано из примера в вопросе. Функция щелчка не включена, но вы все равно можете панорамировать .
Если мы хотим включить функцию щелчка по центру, как оригинал, мы можем обновить наш объект преобразования с помощью нового translate ивызвать масштабирование:
function clicked(d) {
var centroid = path.centroid(d),
translate = projection.translate();
// Update the translate as before:
projection.translate([
translate[0] - centroid[0] + width / 2,
translate[1] - centroid[1] + height / 2
]);
// Update the transform object:
transform.x = projection.translate()[0];
transform.y = projection.translate()[1];
// Apply the transform object:
g.call(zoom.transform, transform);
}
По аналогии с версией v3 - но применяя преобразование масштабирования (как мы это делали изначально), мы запускаем событие масштабирования, поэтому нам не нужно обновлять путь как частьфункции щелчка.
Все вместе, что может выглядеть как this .
Есть детали, которые я не включил, переход по щелчку.Поскольку мы запускаем функцию масштабирования как при щелчке, так и при масштабировании, если мы включили переход, панорамирование также будет переходным, и панорамирование вызывает слишком много событий масштабирования, чтобы переходы выполнялись по желанию.У нас есть один вариант - запускать переход, только если исходным событием был щелчок.Эта модификация может выглядеть так:
function zoomed() {
// Was the event a click?
var event = d3.event.sourceEvent ? d3.event.sourceEvent.type : null;
// Get the new zoom transform
transform = d3.event.transform;
// Apply the new transform to the projection
projection.translate([transform.x,transform.y]).scale(transform.k);
// Redraw the features based on the updaed projection:
(event == "click") ? g.selectAll("path").transition().attr("d",path) : g.selectAll("path").attr("d", path);
}