Built with blockbuilder.org
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HACKARTO.js</title>
<!-- Include Leaflet 1.2.0 Library -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script>
<!-- Fonts -->
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'>
<link href="https://fonts.googleapis.com/css?family=Pacifico" rel="stylesheet">
<!-- Include cartodb.js Library -->
<script src="https://cdn.jsdelivr.net/gh/cartodb/cartodb.js/@4.0.0-alpha.28/carto.js"></script>
<style>
/* https://www.cssportal.com/style-input-range/ */
input[type=range] {
height: 25px;
-webkit-appearance: none;
margin: 10px 0;
width: 100%;
background: transparent;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000;
background: #E3A976;
border-radius: 1px;
border: 1px solid #AB7320;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #000000;
border: 1px solid #E3992B;
height: 18px;
width: 18px;
border-radius: 25px;
background: #F5E02A;
cursor: pointer;
-webkit-appearance: none;
margin-top: -7.5px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #E3A976;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 5px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000;
background: #E3A976;
border-radius: 1px;
border: 1px solid #AB7320;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px #000000;
border: 1px solid #E3992B;
height: 18px;
width: 18px;
border-radius: 25px;
background: #F5E02A;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 5px;
cursor: pointer;
animate: 0.2s;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #E3A976;
border: 1px solid #AB7320;
border-radius: 2px;
box-shadow: 0px 0px 0px #000000;
}
input[type=range]::-ms-fill-upper {
background: #E3A976;
border: 1px solid #AB7320;
border-radius: 2px;
box-shadow: 0px 0px 0px #000000;
}
input[type=range]::-ms-thumb {
margin-top: 1px;
box-shadow: 0px 0px 0px #000000;
border: 1px solid #E3992B;
height: 18px;
width: 18px;
border-radius: 25px;
background: #F5E02A;
cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
background: #E3A976;
}
input[type=range]:focus::-ms-fill-upper {
background: #E3A976;
}
* { margin:0; padding:0; }
#timeline {
background: white;
position: absolute;
left: 10px;
padding: 15px;
bottom: 10px;
height: 30px;
width: 350px;
display: flex;
align-items: center;
z-index: 1000000;
background-image: url('https://i.imgur.com/SmQkqXx.png');
background-repeat:repeat;
border-style: solid;
border-width: 3px;
border-color: #381a00;
font-family: 'Pacifico', cursive;
font-size: x-large;
color: #381a00;
}
#timeline input {
flex: 1;
}
#timeline label {
font-size: 12px;
margin-left: 20px;
}
html { box-sizing:border-box; height:100%; }
body { background:#f2f6f9; height:100%; font-family:"Open sans", Helvetica, Arial, sans-serif; }
#container { display:flex; width:100%; height:100%; background: #fff3e8;}
#map { flex:1; margin:10px; }
#widgets { width:300px; margin:10px 10px 10px 0; }
.widget { background:white; padding:10px; margin-bottom:10px; }
.widget h1 { font-size:1.2em; }
.leaflet-popup-content-wrapper {
background: #fff3e8
}
.leaflet-popup-content-wrapper .leaflet-popup-content {
background: #fff3e8;
font-family: 'Pacifico', cursive;
font-size: medium;
color: #381a00;
}
.leaflet-popup-tip {
background: #fff3e8;
}
#map {
border-style: solid;
border-width: 3px;
border-color: #381a00;
}
#container {
background-image: url('https://i.imgur.com/SmQkqXx.png');
background-repeat:repeat;
}
</style>
</head>
<body>
<div id="container">
<div id="map"></div>
</div>
<div id="timeline">
<input id="timeSlider" type="range" value="0" step="1" />
<label id="dateValue" />
</div>
<script>
// Is this an italian restaurant? Because man, is this some spaghetti code :D
const dateValue = document.querySelector('#dateValue');
const timeSlider = document.querySelector('#timeSlider');
const table = 'jgoizueta.cshapes2';
let timeSeriesData;
function iso(t) {
return t.toISOString().substring(0,10);
}
function countries_at(t) {
var year;
if (t === undefined) {
// Please don't judge me
year = 46;
} else {
year = t.getYear()
}
t = new Date(year, 0, 1, 1);
console.log(t);
var sql = `SELECT * FROM ${table} WHERE year = '${iso(t)}'::date`;
console.log(sql);
return sql
}
function input_date (offset) {
return new Date(timeSeriesData.bins[timeSlider.value].start * 1000);
}
function updateDate (e) {
dateValue.innerHTML = input_date().getFullYear();
}
var source = new carto.source.SQL(countries_at());
function inputChange () {
source.setQuery(countries_at(input_date()));
}
timeSlider.oninput = updateDate;
timeSlider.addEventListener('change', inputChange);
// 1. Setting up the Leaflet Map
var map = L.map('map').setView([0, 0], 2);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '©<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>, ©<a href="https://carto.com/attribution">CARTO</a>'
}).addTo(map);
// 2 Defining a carto.Client
var client = new carto.Client({
apiKey: 'fake',
username: 'jgoizueta'
});
// 3. Displaying on the map
// 3.1 Defining the layer
var fullDataset = new carto.source.Dataset('jgoizueta.cshapes2');
var style = new carto.style.CartoCSS(`
#layer {
polygon-fill: #fff;
polygon-opacity: 1;
polygon-pattern-file: url(https://cdn.pixabay.com/photo/2017/01/12/11/14/background-1974467_960_720.jpg);
::outline {
line-color: #FFFFFF;
line-width: 1.1;
line-opacity: 1;
}
}
#jgoizueta.cshapes2[new='t']{
#layer::outline {
line-color: #FF0000;
}
}
`
);
var countries = new carto.layer.Layer(source, style, {
featureOverColumns: ['cntry_name']
});
client.addLayer(countries);
// 3.3. Adding the layers to the map
client.getLeafletLayer().addTo(map);
var popup = L.popup();
countries.on('featureOver', function (featureEvent) {
popup.setLatLng(featureEvent.latLng);
popup.setContent(featureEvent.data.cntry_name);
popup.openOn(map);
});
countries.on('featureOut', function (featureEvent) {
popup.removeFrom(map);
});
// 4 Creating a TimeSeries widget
// 4.1 Defining a TimeSeries dataview, the second parameter is the column we want to aggregate.
var timeSeries = new carto.dataview.TimeSeries(fullDataset, 'year', {
aggregation: 'year'
});
// 4.2 Listening to data changes on the dataview
timeSeries.on('dataChanged', function (newData) {
timeSeriesData = newData;
timeSlider.min = 0;
timeSlider.max = newData.bins.length;
updateDate();
});
// Listen to timeSeries status, currently we are showing a console.log but looks like a good place to display a loader!
timeSeries.on('statusChanged', function (newStatus, error) {
});
// 4.3 Adding the dataviews to the client
client.addDataview(timeSeries);
</script>
</body>
</html>
Updated missing url https://cdn.rawgit.com/CartoDB/cartodb.js/@4.0.0-alpha.28/carto.js to https://cdn.jsdelivr.net/gh/cartodb/cartodb.js/@4.0.0-alpha.28/carto.js
https://unpkg.com/leaflet@1.2.0/dist/leaflet.js
https://cdn.rawgit.com/CartoDB/cartodb.js/@4.0.0-alpha.28/carto.js