在d3.js地图中单击以缩放和缩放栏

问题描述 投票:1回答:2

我正在为学校项目创建地图,其中涉及单击缩放功能here和模型here的比例尺,而脚本中没有缩放功能。我设法在源代码中都进行了编程,但是我希望在缩放国家/地区时通过使合适的值适合我缩放的比例尺,比例尺能够正确响应。这是点击放大功能:

function clicked(d) {

var bounds = path.bounds(d),
  dx = bounds[1][0] - bounds[0][0],
  dy = bounds[1][1] - bounds[0][1],
  x = (bounds[0][0] + bounds[1][0]) / 2,
  y = (bounds[0][1] + bounds[1][1]) / 2,
  scale = .9 / Math.max(dx / width, dy / height),
  translate = [width / 2 - scale * x, height / 2 - scale * y];

pays.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale + 
"px").style("width", 1.5 / scale + "px").style("height", 1.5 / scale + "px").attr("transform", 
"translate(" + translate + ")scale(" + scale + ")");
villes.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale + 
"px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
capitales.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale + 
"px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
labels.selectAll("text").transition().duration(750).style("font-size", 11 / scale + 
"px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
}

这是比例尺中的一个:

    // Start Scale ---------------------------------------------------------
function scale() {
// baseWidth refers to ideal scale width on the screen it also is the width of the initial measurement point
var g = svg.append("g");
var baseWidth = width / 4;
var p1 = projection.invert([width/2 - baseWidth/2, height / 2]);
var p2 = projection.invert([width/2 + baseWidth/2, height / 2]);
var distance = getDistance(p1,p2);
var unit = "m"; 
var multiply = 1; 
var bestFit = 1;
var increment = 0.1; // This could be scaled to map width maybe width/10000;
var scaleDistance = 0;
var scaleWidth = 0;

if ( distance > 1000 ) { 
    unit = "km"; multiply = 0.001;          
}
// Adjust distance to a round(er) number
var i = 0;
while (i < 400) {
    var temp = getDistance( projection.invert([ width/2 - (baseWidth / 2) + (increment * i), height / 2 ]),  projection.invert([ width/2 + baseWidth/2 - (increment * i), height / 2 ]));
    var ratio = temp / temp.toPrecision(1);

    // If the second distance is moving away from a cleaner number, reverse direction.
    if (i == 1) {
        if (Math.abs(1 - ratio) > bestFit) { increment = - increment; }
    }
    // If we are moving away from a best fit after that, break
    else if (i > 2) {
        if (Math.abs(1 - ratio) > bestFit) { break }
    }               
    // See if the current distance is the cleanest number
    if (Math.abs(1-ratio) < bestFit) {
        bestFit = Math.abs(1 - ratio); 
        scaleDistance = temp; 
        scaleWidth = (baseWidth) - (2 * increment * i);
    }
    i++;
}

// Now to build the scale           
var bars = [];
var smallBars = 10; 
var bigBars = 4;
var odd = true;
var label = false;

// Populate an array to represent the bars on the scale
for (i = 0; i < smallBars; i++) {
    if (smallBars - 1 > i ) { label = false; } else { label = true; }
    bars.push( {width: 1 / (smallBars * (bigBars + 1)), offset: i / (smallBars * (bigBars + 1)), label: label, odd: odd } );
    odd = !odd;
    }
for (i = 0; i < bigBars; i++) {
    bars.push( {width: 1 / (bigBars + 1), offset: (i + 1) / (bigBars + 1), label: true, odd: odd } );
    odd = !odd;
    }

// Append the scale
var scaleBar = g.selectAll(".scaleBar")
    .data(bars);

      // enter bars with no width
      scaleBar
            .enter()
            .append("rect")
            .attr("x", 20)
            .attr("y", height - 40)
            .attr("height",20)
            .attr("width",0)
            .attr("class","scaleBar")
            .merge(scaleBar) // merge so that rect are updates if they are in the enter selection or the update selection.
            .transition()
    .attr("x", function(d) { return d.offset * scaleWidth + 20 })
    //.attr("y", height - 30)
    .attr("width", function(d) { return d.width * scaleWidth})
    //.attr("height", 10)
    .attr("fill", function (d) { if (d.odd) { return "#eee"; } else { return "#222"; } })
            .duration(1000);

    g.selectAll(".scaleText").remove();

g.selectAll(".scaleText") 
    .data(bars).enter()
    .filter( function (d) { return d.label == true })
    .append("text")
    .attr("class","scaleText")
    .attr("x",0)
    .attr("y",0)
    .style("text-anchor","start")
    .text(function(d) { return d3.format(",")(((d.offset + d.width) * scaleDistance).toPrecision(2) * multiply); })
    .attr("transform", function(d) { return "translate("+ ((d.offset + d.width) * scaleWidth + 20 )+","+ (height - 45) +") rotate(-45)" })
            .style("opacity",0)
            .transition()
            .style("opacity",1)
            .duration(1000);


g.append("text")
    .attr("x", scaleWidth/2 + 20)
    .attr("y", height - 5)
    .text( function() { if(unit == "km") { return "Kilometres"; } else { return "metres";}  })
    .style("text-anchor","middle")            
            .attr("class","scaleText")
            .style("opacity",0)
            .transition()
            .style("opacity",1)
            .duration(1000);
 }
 // End Scale -----------------------------------------
 scale(); 

 function getDistance(p1,p2) { 

 var lat1 = p1[1];
var lat2 = p2[1];
var lon1 = p1[0];
var lon2 = p2[0];

var R = 6371e3; // metres
var φ1 = lat1* Math.PI / 180;
var φ2 = lat2* Math.PI / 180;
var Δφ = (lat2-lat1)* Math.PI / 180;
var Δλ = (lon2-lon1)* Math.PI / 180;

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var distance = R * c;

return distance;

}

我在d3.js映射中的水平很弱,对于任何线索或解决方案,我将不胜感激!

dictionary d3.js zoom scale
2个回答
0
投票

比例尺示例假定[width/2,height/2]的任一侧(水平)的两个坐标都代表地图。该中心坐标是固定的。该示例使用projection.invert()计算这两个点之间的真实距离。

缩放示例使用SVG变换来缩放和平移地图。更新缩放变换的操作与投影无关,因此,只要坐标是固定的且独立于变换,projection.invert()始终返回相同的距离。

在此example中,比例栏在更新投影时更新,但是我们可以对其进行修改,以便我们也可以考虑缩放变换。

比例尺示例使用以下方法获取两个初始参考中心点:

var baseWidth = width / 4;
var p1 = projection.invert([width/2 - baseWidth/2, height / 2]);
var p2 = projection.invert([width/2 + baseWidth/2, height / 2]);

question涵盖了如何将坐标转换为缩放坐标:

var xy = d3.mouse(this);         // relative to specified container
var transform = d3.zoomTransform(selection.node());
var xy1 = transform.invert(xy);  // relative to zoom

所以我们可以做一些修改:

// Points relative to parent container:
var xy1 = [width/2 - baseWidth/2, height/2];
var xy2 = [width/2 + baseWidth/2, height/2];

// Zoom transform:
var transform = d3.zoomTransform(g.node());

// Points relative to zoom:
xy1 = transform.invert(xy1);
xy2 = transform.invert(xy2);

现在,我们有两个点应用了缩放变换,以及它们需要在哪里。现在,我们可以像以前一样进行其他更改。原始比例尺示例使用以下命令将其长度调整为一个不错的整数:

var temp = getDistance( projection.invert([ width/2 - (baseWidth / 2) + (increment * i), height / 2 ]),  projection.invert([ width/2 + baseWidth/2 - (increment * i), height / 2 ]));

我们需要对其进行更新,以使用与缩放变换相关的点,并根据缩放比例缩放增量长度:

var temp = getDistance( projection.invert([xy1[0] + (increment * i/transform.k), xy1[1]]),  projection.invert([ xy2[0] - (increment * i/transform.k), xy2[1] ]));

比我在示例中采用的方法要简单得多,但是由于屏幕距离通常不是线性的,因此引入的误差可能比其他情况要多]]

这里是一个更新的example(我将缩放放置在它自己的g容器中,以便不对其应用缩放-对此进行了一些更改。我也很懒:仅缩放在此示例中与土地互动)。

非常感谢,我非常感谢您为解决我的问题所做的努力。但是,恐怕我可能还没有完全的方法来包含您的代码。这是新版本,通过单击实体进行缩放,我仍然没有改变比例尺值。

var startYear = 1990,
    currentYear = startYear;

const width = 960, height = 600;

const path = d3.geoPath();

const projection = d3.geoMercator()
    .center([9, 47])
    .scale(1000)
    .translate([width/2, height/2]);

path.projection(projection);

const svg = d3.select('#carte')
    .append("svg")
    .attr("id", "svg")
    .attr("width", width)
    .attr("height", height);


/***************************************************************************/
/*************************************** AJOUT DES OBJETS SUR LA CARTE *****/
/***************************************************************************/

const pays = svg.append("g");
pays.selectAll("path")
    // La variable geojson est créée dans le fichier JS qui contient le GeoJSON
    .data(geojson_ue.features)
    .enter()
    .append("path")
    .attr("d", path)
    // Sémiologie (par défaut) des objets
    .style("fill", "#e6e6e6")
    .style("stroke-width", 3)
    .style("stroke", "#fff");

const pays2 = svg.append("g");
pays.selectAll("path")
    // La variable geojson est créée dans le fichier JS qui contient le GeoJSON
    .data(geojson_pays.features)
    .enter()
    .append("path")
    .attr("d", path)
    // Sémiologie (par défaut) des objets
    .style("fill", "rgba(232, 232, 232,0.8)")
    .style("stroke-width", .5)
    .style("stroke", "#fff");

const rail = svg.append("g");
rail.selectAll("path")
    // La variable geojson est créée dans le fichier JS qui contient le GeoJSON
    .data(geojson_rail.features)
    .enter()
    .append("path")
    .attr("d", path)
    .attr("stroke-opacity",0)
    .attr("fill-opacity",0)
    .on("click", clicked);

// VILLES ET CAPITALES

const villes = svg.append("g");
villes.selectAll("path")
    // La variable geojson est créée dans le fichier JS qui contient le GeoJSON
    .data(geojson_villes.features)
    .enter()
    .append("path")
    .attr("d", path)
//  Sémiologie (par défaut) des objets
    .style("fill", "black")
    .style("stroke", "white")
    .style("stroke-width", 0.5)
    .attr("stroke-opacity",0)
    .attr("fill-opacity",0);


const capitales = svg.append("g");
capitales.selectAll("path")
    // La variable geojson est créée dans le fichier JS qui contient le GeoJSON
    .data(geojson_capitales.features)
    .enter()
    .append("path")
    .attr("d", path)
    // Sémiologie (par défaut) des objets
    .style("fill", "#180093")
    ;


/***************************************************************************/
/**************************** PREVOIR UNE ACTION AU CLIC SUR UN BOUTON *****/
/***************************************************************************/

//BOUTONS
$("#action1").click(function(){
    affiche_rail(1980, projection.scale);
    document.getElementById("legende").innerHTML = '<img src ="Untitled-1.png"/>';
});

$("#action2").click(function(){
    affiche_rail(1990, projection.scale);
    document.getElementById("legende").innerHTML = '<img src ="Untitled-2.png"/>';
});

$("#action3").click(function(){
    affiche_rail(2000, projection.scale);
    document.getElementById("legende").innerHTML = '<img src ="Untitled-3.png"/>';
});

$("#action4").click(function(){
    affiche_rail(2010, projection.scale);
    document.getElementById("legende").innerHTML = '<img src ="Untitled-4.png"/>';
});

$("#action5").click(function(){
    affiche_rail(2020, projection.scale);
    document.getElementById("legende").innerHTML = '<img src ="Untitled-5.png"/>';
});

$("#dezoom").click(function(){

    var bounds = path.bounds(),
        dx = bounds[1][0] - bounds[0][0],
        dy = bounds[1][1] - bounds[0][1],
        x = (bounds[0][0] + bounds[1][0]) / 2,
        y = (bounds[0][1] + bounds[1][1]) / 2,
        scale = 1 / Math.max(dx / width, dy / height),
        translate = [width / 2 - scale * x, height / 2 - scale * y];

    pays.selectAll("path").transition().duration(750).style("stroke-width", "1.5px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    villes.selectAll("path").transition().duration(750).style("stroke-width", 0.5).attr("d", path.pointRadius(4.5)).attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    capitales.selectAll("path").transition().duration(750).style("stroke-width", 3).attr("d", path.pointRadius(4.5)).attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    rail.selectAll("path").transition().duration(750).style("stroke-width", "2px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
});



var tooltip = d3.select("body").append("div") 
        .attr("class", "tooltip")       
        .style("opacity", 0);

var tooltip2 = d3.select("body").append("div") 
        .attr("class", "tooltip")       
        .style("opacity", 0);




// FONCTION D'AFFICHAGE
function affiche_rail(date, scale){ // Affiche les lignes en fonction de la date de construction 

    rail.selectAll("path")
        .attr("stroke", function(d,i){ // Couleur de contour des lignes concernées
            if (geojson_rail.features[i].properties.Date_Const < date){
                return "grey"
            }
            else if (geojson_rail.features[i].properties.Date_Const == date) {
                return "red"
            }
        })
        .attr("stroke-opacity", function(d,i){ // Opacité des contours des lignes
            if (geojson_rail.features[i].properties.Date_Const <= date){
                return "1"
            }
            else if (geojson_rail.features[i].properties.Date_Const > date) {
                return "0"
            }
        })
        .attr("fill-opacity", "0") // 0 sinon c'est moche
        // Sémiologie (par défaut) des objets
        .style("stroke-width", 2)
        .style("stroke-dasharray", function(d,i){
            if (geojson_rail.features[i].properties.Date_Const == 2020){
                return 2
            }
        });

    villes.selectAll("path")
        .attr("stroke-opacity", function(d,i){ // Opacité des contours des points
            if (geojson_villes.features[i].properties.date <= date){
                return "1"
            }
            else if (geojson_villes.features[i].properties.date > date) {
                return "0"
            }
        })
        .attr("fill-opacity", function(d,i){ // Opacité des contours des points
            if (geojson_villes.features[i].properties.date <= date){
                return "1"
            }
            else if (geojson_villes.features[i].properties.date > date) {
                return "0"
            }
        })
        // Sémiologie (par défaut) des objets
        .style("fill", "black")
        .style("stroke", "white")
        .style("stroke-width", 0.5);

    // infos sur les villes au survol
    villes.selectAll("path").filter(function(d) {
        return d.properties.date <= date;
    }).on("mouseover", function(d) {
        d3.select(this)
            .style("fill", "blue")
        .style("stroke", "black")
        .style("stroke-width", 1.5/scale)
        .style("cursor", "pointer");
        tooltip.transition()    
                .duration(200)    
                .style("opacity", .9);    
                tooltip.html(d.properties.nom)  
                .style("left", (d3.event.pageX) + "px")   
                .style("top", (d3.event.pageY - 28) + "px");
    }).on("mouseout", function(d) {
        d3.select(this)
            .style("fill", "black")
        .style("stroke", "white")
        .style("stroke-width", 2/scale)
        tooltip.transition()    
                .duration(500)    
                .style("opacity", 0);
    }).on("click",function(d){
        // tooltip2.transition()    
                // .duration(200)    
                // .style("opacity", .9);    
        // tooltip2.html(d.properties.date)  
                // .style("left", (d3.event.pageX) + "px")   
                // .style("top", (d3.event.pageY - 28) + "px");
        tooltip.html(d.properties.nom + "<br />Date : " + d.properties.date);
    });

    //infos sur les capitales au survol
    capitales.selectAll("path").filter(function(d) {
        return d.properties.nom != "NULL";
    }).on("mouseover", function(d) {
        d3.select(this)
            .style("fill", "blue")
        .style("stroke", "black")
        .style("stroke-width", 1.5/scale)
        .style("cursor", "pointer");
        tooltip.transition()    
                .duration(200)    
                .style("opacity", .9);    
                tooltip.html(d.properties.nom)  
                .style("left", (d3.event.pageX) + "px")   
                .style("top", (d3.event.pageY - 28) + "px");
    }).on("mouseout", function(d) {
        d3.select(this)
            .style("fill", "#180093")
            .style("stroke", "rgba(0,0,0,0)")
        tooltip.transition()    
                .duration(500)    
                .style("opacity", 0);
    });

    // Changer le style des lignes au survol
    rail.selectAll("path").filter(function(d) {
        return d.properties.Date_Const <= date;
    }).on("mouseover", function(d) {
        d3.select(this)
            .style("cursor", "pointer")
            .style("fill-opacity", 0)
            .style("stroke", "blue")
            .style("stroke-width", 7/scale)
        tooltip.transition()    
            .duration(200)
            .style("opacity", .9); 
            tooltip.html("Ligne " + d.properties.LGV + ". Ouverte en " + d.properties.ouverture + ".")  
            .style("left", (d3.event.pageX) + "px")   
            .style("top", (d3.event.pageY - 28) + "px");
    }).on("mouseout", function(d) {
        d3.select(this)
            .style("fill-opacity", 0)
            .style("stroke", function(d,i){ 
                if (geojson_rail.features[i].properties.Date_Const < date){
                    return "grey"
                }
                else if (geojson_rail.features[i].properties.Date_Const == date) {
                    return "red"
                }
            })
            .style("stroke-width", 2/scale)
        tooltip.transition()    
            .duration(500)    
            .style("opacity", 0);
    });
}

function clicked(d) {

    var bounds = path.bounds(d),
        dx = bounds[1][0] - bounds[0][0],
        dy = bounds[1][1] - bounds[0][1],
        x = (bounds[0][0] + bounds[1][0]) / 2,
        y = (bounds[0][1] + bounds[1][1]) / 2,
        scale = .5 / Math.max(dx / width, dy / height),
        translate = [width / 2 - scale * x, height / 2 - scale * y];

    pays.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale + "px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    pays2.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale + "px").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    villes.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale + "px").attr("d", path.pointRadius(1.5)).attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    capitales.selectAll("path").transition().duration(750).attr("d", path.pointRadius(1.5)).attr("transform", "translate(" + translate + ")scale(" + scale + ")");
    rail.selectAll("path").transition().duration(750).style("stroke-width", 1.5 / scale +"%").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
}

   // zoom
   var zoom = d3.zoom()
     .on("end",zoomed)

   rail.call(zoom);

   function zoomed() {
     rail.attr("transform",d3.event.transform);
     scale();
   }
//*/
  // Start Scale ---------------------------------------------------------
  function scale() {
    // baseWidth refers to ideal scale width on the screen it also is the width of the initial measurement point
    var baseWidth = width / 4;

    // Points relative to parent container:
    var xy1 = [width/2 - baseWidth/2, height/2];
    var xy2 = [width/2 + baseWidth/2, height/2];
    // Zoom transform:
    var transform = d3.zoomTransform(rail.node());
    // Points relative to zoom:
    xy1 = transform.invert(xy1);
    xy2 = transform.invert(xy2);

    // With a few changes below:
    var p1 = projection.invert(xy1);
    var p2 = projection.invert(xy2);
    var distance = getDistance(p1,p2);
    var unit = "m"; 
    var multiply = 1; 
    var bestFit = 1;
    var increment = 0.1; // This could be scaled to map width maybe width/10000;
    var scaleDistance = 0;
    var scaleWidth = 0;

    if ( distance > 1000 ) { 
        unit = "km"; multiply = 0.001;          
    }
    // Adjust distance to a round(er) number
    var i = 0;
    while (i < 400) {
        var temp = getDistance( projection.invert([xy1[0] + (increment * i/transform.k), xy1[1]]),  projection.invert([ xy2[0] - (increment * i/transform.k), xy2[1] ]));
        var ratio = temp / temp.toPrecision(1);

        // If the second distance is moving away from a cleaner number, reverse direction.
        if (i == 1) {
            if (Math.abs(1 - ratio) > bestFit) { increment = - increment; }
        }
        // If we are moving away from a best fit after that, break
        else if (i > 2) {
            if (Math.abs(1 - ratio) > bestFit) { break }
        }               
        // See if the current distance is the cleanest number
        if (Math.abs(1-ratio) < bestFit) {
            bestFit = Math.abs(1 - ratio); 
            scaleDistance = temp; 
            scaleWidth = (baseWidth) - (2 * increment * i);
        }
        i++;
    }

    // Now to build the scale           
    var bars = [];
    var smallBars = 10; 
    var bigBars = 4;
    var odd = true;
    var label = false;

    // Populate an array to represent the bars on the scale
    for (i = 0; i < smallBars; i++) {
        if (smallBars - 1 > i ) { label = false; } else { label = true; }
        bars.push( {width: 1 / (smallBars * (bigBars + 1)), offset: i / (smallBars * (bigBars + 1)), label: label, odd: odd } );
        odd = !odd;
        }
    for (i = 0; i < bigBars; i++) {
        bars.push( {width: 1 / (bigBars + 1), offset: (i + 1) / (bigBars + 1), label: true, odd: odd } );
        odd = !odd;
        }

    // Append the scale
    var scaleBar = rail.selectAll(".scaleBar")
        .data(bars);
          // enter bars with no width
          scaleBar
                .enter()
                .append("rect")
                .attr("x", 20)
                .attr("y", height - 40)
                .attr("height",20)
                .attr("width",0)
                .attr("class","scaleBar")
                .merge(scaleBar) // merge so that rect are updates if they are in the enter selection or the update selection.
                .transition()
        .attr("x", function(d) { return d.offset * scaleWidth + 20 })
        //.attr("y", height - 30)
        .attr("width", function(d) { return d.width * scaleWidth})
        //.attr("height", 10)
        .attr("fill", function (d) { if (d.odd) { return "#eee"; } else { return "#222"; } })
                .duration(1000);
        rail.selectAll(".scaleText").remove();
    rail.selectAll(".scaleText") 
        .data(bars).enter()
        .filter( function (d) { return d.label == true })
        .append("text")
        .attr("class","scaleText")
        .attr("x",0)
        .attr("y",0)
        .style("text-anchor","start")
        .text(function(d) { return d3.format(",")(((d.offset + d.width) * scaleDistance).toPrecision(2) * multiply); })
        .attr("transform", function(d) { return "translate("+ ((d.offset + d.width) * scaleWidth + 20 )+","+ (height - 45) +") rotate(-45)" })
                .style("opacity",0)
                .transition()
                .style("opacity",1)
                .duration(1000);
    rail.append("text")
        .attr("x", scaleWidth/2 + 20)
        .attr("y", height - 5)
        .text( function() { if(unit == "km") { return "kilometers"; } else { return "metres";}  })
        .style("text-anchor","middle")            
                .attr("class","scaleText")
                .style("opacity",0)
                .transition()
                .style("opacity",1)
                .duration(1000);
   }
    // End Scale -----------------------------------------
   scale();


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/* Latitude/longitude spherical geodesy tools                         (c) Chris Veness 2002-2016  */
/*                                                                                   MIT Licence  */
/* www.movable-type.co.uk/scripts/latlong.html                                                    */
/* www.movable-type.co.uk/scripts/geodesy/docs/module-latlon-spherical.html                       */
function getDistance(p1,p2) { 

    var lat1 = p1[1];
    var lat2 = p2[1];
    var lon1 = p1[0];
    var lon2 = p2[0];

    var R = 6371e3; // metres
    var φ1 = lat1* Math.PI / 180;
    var φ2 = lat2* Math.PI / 180;
    var Δφ = (lat2-lat1)* Math.PI / 180;
    var Δλ = (lon2-lon1)* Math.PI / 180;
    var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
            Math.cos(φ1) * Math.cos(φ2) *
            Math.sin(Δλ/2) * Math.sin(Δλ/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var distance = R * c;

return distance;

}

0
投票

非常感谢,我非常感谢您为解决我的问题所做的努力。但是,恐怕我可能还没有完全的方法来包含您的代码。这是新版本,通过单击实体进行缩放,我仍然没有改变比例尺值。

© www.soinside.com 2019 - 2024. All rights reserved.