Thank you very much, I really appreciate the effort you did for solving my problem. But I'm afraid I might not quite get the complete way to include your code. Here is the new version, I still don't get a change in the scalebar values by clicking on entities to zoom.
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;
}