Skip to content

Instantly share code, notes, and snippets.

@jsanz
Last active June 17, 2019 09:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jsanz/285982c3f170e6aafabfab809939d699 to your computer and use it in GitHub Desktop.
Save jsanz/285982c3f170e6aafabfab809939d699 to your computer and use it in GitHub Desktop.
CARTO VL - Basemap Switcher
<!DOCTYPE html>
<html lang="en">
<head>
<title>CARTO VL: Switch the basemap</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="shortcut icon" href="https://carto.com/favicon.ico">
<link rel="stylesheet" href="https://libs.cartocdn.com/airship-style/v1.0.3/airship.css">
<script src="https://libs.cartocdn.com/airship-components/v1.0.3/airship.js"></script>
<script src="https://libs.cartocdn.com/carto-vl/v1.0.0/carto-vl.min.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.js"></script>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<style>
.basemaps ul{
padding-inline-start: 5px;
margin: 5px;
}
</style>
</head>
<body class="as-app-body as-app">
<as-responsive-content>
<main class="as-main">
<div class="as-map-area">
<div id="map" style="width:100%;height:100vh;"></div>
</div>
</main>
<div class="as-map-panels">
<div class="as-panel as-panel--top as-panel--right" id="app">
<div class="as-panel__element as-p--4 basemaps">
<ul v-for="basemap in basemaps">
<li class="as-radio">
<input class="as-radio__input" type="radio" id="{{basemap.id}}" name="basemapSelect"
v-bind:value="basemap.id" v-model="basemapSelected" :checked="basemap.id == basemapSelected">
<label class="as-caption" for="{{basemap}}">{{basemap.name }}</label>
</li>
</ul>
</div>
</div>
</div>
</as-responsive-content>
<script>
function simpleTilesStyle(urls){
return {
version: 8,
sources: {
"simple-tiles": {
type: "raster",
tiles: urls,
tileSize: 256
}
},
layers: [{
id: "simple-tiles",
type: "raster",
source: "simple-tiles",
minzoom: 0,
maxzoom: 22
}]
}
}
function run() {
const basemapsData = [{
id: 'voyager',
name: 'Color (CARTO)',
style: carto.basemaps.voyager,
databelow: 'watername_ocean',
}, {
id: 'positron',
name: 'Light (CARTO)',
style: carto.basemaps.positron,
databelow: 'watername_ocean',
}, {
id: 'darkmatter',
name: 'Dark (CARTO)',
style: carto.basemaps.darkmatter,
databelow: 'watername_ocean',
}, {
id: 'here',
name: 'HERE',
style: simpleTilesStyle( ['1', '2', '3', '4'].map(s => { return `https://${s}.base.maps.api.here.com/maptile/2.1/maptile/newest/reduced.day/{z}/{x}/{y}/256/png8?app_id=W5LaaXz5OWFgAHEQnIoZ&app_code=bcrpWpQGiM2b72u9_ygFWA`; }))
}];
// Vue app to control state and rendering
new Vue({
el: '#app',
data: {
basemaps: basemapsData,
basemapSelected: basemapsData[0].id,
map: null
},
computed: {
basemapSelectedObj: function () {
return this.basemaps.filter(b => b.id == this.basemapSelected)[0];
}
},
watch: {
basemapSelected: function () {
const basemap = this.basemapSelectedObj;
this.map.removeLayer('layer');
this.map.setStyle(basemap.style, basemap.databelow);
}
},
methods: {
initialize: function () {
this.map = new mapboxgl.Map({
container: 'map',
style: carto.basemaps.voyager,
center: [39.29, 3.54],
zoom: 4,
scrollZoom: true,
hash: true
});
const nav = new mapboxgl.NavigationControl({
showCompass: false
});
this.map.addControl(nav, 'top-left');
// Define user
carto.setDefaultAuth({
username: 'cartovl',
apiKey: 'default_public'
});
this.map.on('sourcedata', this.drawLayer);
},
drawLayer: function () {
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
async function wait(ctx, howMuch) {
await sleep(howMuch);
if (!ctx.map.getLayer('layer')) {
const source = new carto.source.Dataset('populated_places');
const viz = new carto.Viz();
const layer = new carto.Layer('layer', source, viz);
if (ctx.basemapSelectedObj && ctx.basemapSelectedObj.hasOwnProperty(
'databelow')) {
layer.addTo(ctx.map, ctx.basemapSelectedObj.databelow);
} else {
layer.addTo(ctx.map);
}
console.log('Layer redrawn');
}
}
wait(this, 100);
}
}
}).initialize();
}
// Run the script when content is ready
document.querySelector('as-responsive-content').addEventListener('ready', run);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment