D3js Geo уменьшает масштаб элемента при масштабировании карты

У меня есть карта D3js, созданная с помощью topojson.js.

var projection = d3.geo.mercator();

Все работает нормально, но я ищу эффект, которого не могу добиться. Когда, увеличивая карту, я хотел бы, чтобы булавки над ней уменьшались, но если я уменьшаю ее, мне нужно пересчитать их координаты, и я не могу найти формулу для этого.

Обработчик масштабирования

scale = d3.event.scale;
if (scale >= 1) { 
   main.attr("transform", "translate(" + d3.event.translate + ")
   scale(" + d3.event.scale + ")");
}    
else {
   main.attr("transform", "translate(" + d3.event.translate + ")scale(1)");
}

//43x49 is the size initial pine size when scale = 1 
var pins = main.select("#pins").selectAll("g").select("image")
            .attr("width", function () {
                return 43 - (43 * (scale - 1));
            })
            .attr("height", function () {
                return 49 - (49 * (scale - 1));
            })
            .attr("x", function () {
                //Calculate new image coordinates;
            })
            .attr("y", function () {
                //Calculate new image coordinates;
            });

Мой вопрос: как рассчитать x и y на основе новой шкалы?

Я надеюсь, что я достаточно ясен.

Спасибо за вашу помощь

РЕДАКТИРОВАТЬ :

Расчет начальных координат пинов:

"translate(" + (projection([d.lon, d.lat])[0] - 20) + "," 
+ (projection([d.lon, d.lat])[1] - 45) + ")"

-20 и -45, чтобы острие булавки попало точно в цель.


person Yooz    schedule 15.04.2015    source источник
comment
Не могли бы вы показать, как вы рассчитываете начальные позиции пинга? Если контакты находятся внутри main (который, как я предполагаю, является элементом g или svg), то вам вообще не нужно менять x и y при scale контейнере. Кроме того, вы можете установить scaleExtent вместо ручной проверки scale >= 1. Это также дало бы вам лучшее поведение (например, отсутствие гистерезиса при масштабировании, если пользователь слишком сильно уменьшает масштаб).   -  person musically_ut    schedule 15.04.2015
comment
Вы правы, все в главном. и булавки отлично работают при увеличении, но они становятся слишком большими, поэтому я хотел бы уменьшить их масштаб при увеличении. Но я не знаю, как пересчитать координаты после счетчика масштаба.   -  person Yooz    schedule 16.04.2015


Ответы (1)


Вам нужно «противомасштабировать» выводы, т. е. когда main масштабируется вверх/вниз, вам нужно масштабировать выводы вниз/вверх в противоположном направлении. Масштабный коэффициент счетчика равен 1/scale, и вы должны применить его к каждому из <g>, содержащих изображение булавки. Это позволяет вам удалить текущий расчет ширины и высоты из узлов <image> (поскольку об этом позаботится родительский масштаб <g>).

Однако, чтобы это работало должным образом, вам также необходимо удалить атрибуты x и y из <image> и применить позицию через масштабированный со счетчиком родитель <g>. Это необходимо, потому что, если есть локальное смещение (как в случае, когда x и y установлены на <image>), это локальное смещение масштабируется по мере масштабирования родительского <g>, что приводит к перемещению вывода в неправильное положение.

So:

var pinContainers = main.select("#pins").selectAll("g")
    .attr("transform", function(d) {
        var x = ... // don't know how you calculate x (since you didn't show it)
        var y = ... // don't know how you calculate y
        var unscale = 1/scale;
        return "translate(" + x + " " + y + ") scale(" + unscale + ")";
    })
pinContainers.select("image")
    .attr("width", 43)
    .attr("height", 49)
    // you can use non-zero x and y to get the image to scale
    // relative to some point other than the top-left of the
    // image (such as the tip of the pin)
    .attr("x", 0)
    .attr("y", 0)
person meetamit    schedule 15.04.2015
comment
Спасибо, мне нравится групповой счетчик. Я не указал x и y, так как это то, что я ищу. Я отредактировал свой вопрос, чтобы устранить путаницу. - person Yooz; 16.04.2015