Reputation: 510
Maybe this is a silly question but I am unable to include a chart for each point on a map.
I am collecting the data from a JSON, this data I print it in the popup, each one with its class .scoreA, .scoreB... I would like from this data to create a chart for each point like the one I have. I would prefer to take them from the content of the popup (.scoreA, .scoreB) rather than from the JSON in case the structure changes. is it possible?
var mymap = L.map('mapid').setView([39.46975, -0.37739], 8 );
L.tileLayer('https://api.mapbox.com/styles/v1/jamaldols/cktwljkom0vzo18l9ggtnky83/tiles/256/{z}/{x}/{y}@2x?access_token={accessToken}', {
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 12,
minZoom: 8,
id: 'mapbox/standard',
tileSize: 512,
zoomOffset: -1,
// maxNativeZoom: 16,
accessToken: ''
}).addTo(mymap);
$.getJSON('data.geo.json', function (geojson) {
L.geoJson(geojson, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng);
},
onEachFeature: function (feature, layer) {
const coordinates = feature.geometry.coordinates;
const normalizedCoordinates = feature.geometry.coordinates.sort(function(a,b){return a.typeid-b.typeid});
console.log( `Coordinates: ${coordinates}`);
console.log( `Coordinates N: ${normalizedCoordinates}`);
const content =
`
<p id="heading">${feature.properties.name}</p>
<p class="scoreA"><strong>ScoreA: </strong>${feature.properties.scoreA}</p>
<p class="scoreB"><strong>ScoreB: </strong>${feature.properties.scoreB}</p>
<p class="scoreC"><strong>ScoreC: </strong>${feature.properties.scoreC}</p>
<p class="scoreD"><strong>ScoreD: </strong>${feature.properties.scoreD}</p>
<div class="popup__chart">chart</div>
`;
layer.on('click', function (e) {
document.getElementById("popup__content").innerHTML = content;
$(".popup").fadeOut(10);
$(".popup").fadeIn("slow");
console.log( `Click on ${feature.properties.name}`);
const maxZoom = mymap.getMaxZoom();
console.log(maxZoom)
mymap.flyTo(this.getLatLng(), maxZoom, {easeLinearity: 0.12, duration:1});
});
}
}).addTo(mymap);
});
//Chart
var marksCanvas = document.getElementById("marksChart");
var marksData = {
labels: ["Score A", "Score B", "Score C", "Score D"],
datasets: [{
label: "City",
backgroundColor: "rgba(200,0,0,1)",
data: [65, 60, 90, 80]
},]
};
var radarChart = new Chart(marksCanvas, {
type: 'radar',
data: marksData
});
$(document).ready(function(){
$(".popup__bar__close").click(function(){
$('.popup').css('display', 'none');
mymap.flyTo([39.46975, -0.37739], 8, {easeLinearity: 0.12, duration:1});
});
});
html,
body {
height: 100%;
font-family: 'Montserrat', sans-serif;
}
.popup-fixed {
position: fixed;
top: auto;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
transform: none !important;
margin: 0;
border-radius: 0;
}
.leaflet-popup-tip-container {
display: none;
}
.leaflet-popup-content-wrapper {
border-radius: 0;
}
.popup {
width: 300px;
padding-bottom: 50px;
background: white;
position: absolute;
top: 50px;
right: 50px;
border: none;
display:none;
z-index: 1000;
}
#heading {
font-size: 35px;
color:black;
text-transform: uppercase;
margin: 15px 0;
}
#main {
display: flex;
overflow: hidden;
}
.popup {
}
.popup__bar {
width: 100%;
height: 50px;
position: relative;
display: flex;
align-items: center;
background: black;
}
.popup__bar__close {
background-image: url(img/close.svg);
background-size: 30px;
background-repeat: no-repeat;
background-position: center;
position: absolute;
height: 30px;
width: 30px;
right: 15px;
transform: rotate(45deg);
cursor: pointer;
}
.popup__chart {
}
.popup__chart img{
max-width: 100%;
height: auto;
}
#popup__content {
padding: 0 30px;
}
#info {
}
#footer {
font-family: 'Roboto Condensed', sans-serif;
display: flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
letter-spacing: 6px;
height: 70px;
position: absolute;
background: white;
bottom: 0;
width: calc(100% - 90px);
right: 0;
}
#marksChart {
display: block;
box-sizing: border-box;
height: 250px;
width: 250px;
position: absolute;
top: 100px;
left: 90px;
background: white;
z-index: 200000;
border-radius: 12px;
padding: 20px;
}
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js" integrity="sha512-Wt1bJGtlnMtGP0dqNFH1xlkLBNpEodaiQ8ZN5JLA5wpc1sUlk/O5uuOMNgvzddzkpvZ9GLyYNa8w2s7rqiTk5Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<style>
#mapid {
height: calc(100vh - 70px);
width: calc(100vw - 90px);
}
body {
padding: 0;
margin: 0;
}
</style>
<main id="main">
<div id="mapid"></div>
</main>
<div class="chart-container" style="max-width: 200px;">
<canvas id="marksChart" width="200" height="400"></canvas>
</div>
<script>
</script>
<div class="popup">
<div class="popup__bar">
<div class="popup__bar__close"></div>
</div>
<div id="popup__content"></div>
</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
<!-- <script type="text/javascript" src="data.geo.json"></script> -->
<script type="text/javascript" src="main.js"></script>
</body>
Upvotes: 3
Views: 1536
Reputation: 11338
Change your javascript to following:
$.getJSON('data.geo.json', function (geojson) {
L.geoJson(geojson, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng);
},
onEachFeature: function (feature, layer) {
const coordinates = feature.geometry.coordinates;
const normalizedCoordinates = feature.geometry.coordinates.sort(function(a,b){return a.typeid-b.typeid});
console.log( `Coordinates: ${coordinates}`);
console.log( `Coordinates N: ${normalizedCoordinates}`);
const content =
`
<p id="heading">${feature.properties.name}</p>
<p class="scoreA"><strong>ScoreA: </strong><span>${feature.properties.scoreA}</span></p>
<p class="scoreB"><strong>ScoreB: </strong><span>${feature.properties.scoreB}</span></p>
<p class="scoreC"><strong>ScoreC: </strong><span>${feature.properties.scoreC}</span></p>
<p class="scoreD"><strong>ScoreD: </strong><span>${feature.properties.scoreD}</span></p>
<div class="popup__chart">chart</div>
`;
layer.on('click', function (e) {
var popupElm = document.getElementById("popup__content");
popupElm.innerHTML = content;
$(".popup").fadeOut(10);
$(".popup").fadeIn("slow");
console.log( `Click on ${feature.properties.name}`);
const maxZoom = mymap.getMaxZoom();
console.log(maxZoom)
mymap.flyTo(this.getLatLng(), maxZoom, {easeLinearity: 0.12, duration:1});
var marksData = {
labels: ["Score A", "Score B", "Score C", "Score D"],
datasets: [{
label: "City",
backgroundColor: "rgba(200,0,0,1)",
data: [
popupElm.querySelectorAll('.scoreA span')[0].innerHTML,
popupElm.querySelectorAll('.scoreB span')[0].innerHTML,
popupElm.querySelectorAll('.scoreC span')[0].innerHTML,
popupElm.querySelectorAll('.scoreD span')[0].innerHTML
],
},]
};
if(radarChart){
radarChart.destroy();
}
radarChart = new Chart(marksCanvas, {
type: 'radar',
data: marksData
});
});
}
}).addTo(mymap);
});
//Chart
var marksCanvas = document.getElementById("marksChart");
var radarChart = null;
$(document).ready(function(){
$(".popup__bar__close").click(function(){
$('.popup').css('display', 'none');
mymap.flyTo([39.46975, -0.37739], 8, {easeLinearity: 0.12, duration:1});
});
});
What changed:
Add in the Popup around the score value a span
, so it can easily read out
<p class="scoreA"><strong>ScoreA: </strong><span>${feature.properties.scoreA}</span></p>
Move the chart generation into the click function but keep the global variables
Destroy the existing chart, else an error is thrown radarChart.destroy();
Get the valus from popup and use it in the data
array. It searches for the class .scoreA
and then it get the child span
element
popupElm.querySelectorAll('.scoreA span')[0].innerHTML,
Btw. you can also get the values from the clicked layer:
data: [
layer.feature.properties.scoreA,
layer.feature.properties.scoreB,
layer.feature.properties.scoreC,
layer.feature.properties.scoreD,
]
Upvotes: 2