D3js Гео елемент за премахване на мащаба при мащабиране на картата

Имам 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>s, съдържащ изображението на карфица. Това ви позволява да премахнете текущото изчисление на ширината и височината от възлите <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