Related
I want to make a separate tooltip for every stacked bar, Ex. My demo "2022-01-17" has TWO stacked bars with FOUR values but I need a total of Stack 1 group and Stack 2 group
I've reviewed most of the options in chartjs https://www.chartjs.org/docs/3.5.1/samples/bar/stacked-groups.html
var barChartData = {
labels: ["2022-01-17","2022-01-18","2022-01-19","2022-01-20","2022-01-21","2022-01-22","2022-01-23","2022-01-24","2022-01-25","2022-01-26","2022-01-27","2022-01-28","2022-01-29","2022-01-30"],
datasets: [{"label":"Product 2","data":["292.53","328.5","273.83","305.44","260.33","251.87","118.15","253.95","86.64","87.78","116.68","295.49","61.32","83.78"],"backgroundColor":"#66bb6a","borderColor":"#66bb6a","pointBackgroundColor":"#66bb6a","stack":"Stack 0"},{"label":"Product ","data":["1522.27","1844.83","1581.01","2767.68","2821.36","2940.31","2876.1","2037.79","1593.01","1900.86","1607.21","2188.92","2428.74","2508.81"],"backgroundColor":"#1b5e20","borderColor":"#1b5e20","pointBackgroundColor":"#1b5e20","stack":"Stack 0"},{"label":"Product 2","data":["200","4.14","28.51","13.68","0","0","19.93","0","0","0","10.47","23.05","9.42","10.58"],"backgroundColor":"#ffcdd2","borderColor":"#ffcdd2","pointBackgroundColor":"#ffcdd2","stack":"Stack 1"},{"label":"Product ","data":["680.2","536.51","524.41","479.69","453.19","521.87","530.57","485.13","440.25","591.29","722.73","711.58","686.63","510.72"],"backgroundColor":"#ef9a9a","borderColor":"#ef9a9a","pointBackgroundColor":"#ef9a9a","stack":"Stack 1"}]
};
const footer = (tooltipItems) => {
let sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += tooltipItem.parsed.y;
});
return 'Sum: ' + sum;
};
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
tooltip: {
callbacks: {
footer: (tooltipItem) => {
let sum = 0;
tooltipItem.forEach(function(tooltipItem) {
sum += tooltipItem.parsed.y;
});
return 'Sum: ' + sum;
}
}
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.0/dist/chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>
to get the total of each stack, you can use the dataPoints found in the tooltip context
and use the dataset labels to group by each stack
// group stacks
const groups = {};
tooltip.dataPoints.forEach(function (point) {
if (groups.hasOwnProperty(barChartData.datasets[point.datasetIndex].label)) {
groups[barChartData.datasets[point.datasetIndex].label] += parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
} else {
groups[barChartData.datasets[point.datasetIndex].label] = parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
}
});
e.g. --> {"Product 2":492.53,"Product ":2202.4700000000003}
then use the external option to create a custom tooltip
see following working snippet...
$(document).ready(function() {
var barChartData = {
labels: ["2022-01-17","2022-01-18","2022-01-19","2022-01-20","2022-01-21","2022-01-22","2022-01-23","2022-01-24","2022-01-25","2022-01-26","2022-01-27","2022-01-28","2022-01-29","2022-01-30"],
datasets: [{"label":"Product 2","data":["292.53","328.5","273.83","305.44","260.33","251.87","118.15","253.95","86.64","87.78","116.68","295.49","61.32","83.78"],"backgroundColor":"#66bb6a","borderColor":"#66bb6a","pointBackgroundColor":"#66bb6a","stack":"Stack 0"},{"label":"Product ","data":["1522.27","1844.83","1581.01","2767.68","2821.36","2940.31","2876.1","2037.79","1593.01","1900.86","1607.21","2188.92","2428.74","2508.81"],"backgroundColor":"#1b5e20","borderColor":"#1b5e20","pointBackgroundColor":"#1b5e20","stack":"Stack 0"},{"label":"Product 2","data":["200","4.14","28.51","13.68","0","0","19.93","0","0","0","10.47","23.05","9.42","10.58"],"backgroundColor":"#ffcdd2","borderColor":"#ffcdd2","pointBackgroundColor":"#ffcdd2","stack":"Stack 1"},{"label":"Product ","data":["680.2","536.51","524.41","479.69","453.19","521.87","530.57","485.13","440.25","591.29","722.73","711.58","686.63","510.72"],"backgroundColor":"#ef9a9a","borderColor":"#ef9a9a","pointBackgroundColor":"#ef9a9a","stack":"Stack 1"}]
};
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
tooltip: {
enabled: false,
position: 'nearest',
external: function (context) {
// init
const {chart, tooltip} = context;
// remove old tooltip
var container = chart.canvas.parentNode.querySelector('.tooltip');
if (container) {
chart.canvas.parentNode.removeChild(container);
}
// determine if tooltip exists
if (tooltip.opacity === 0) {
return;
}
// group stacks
const groups = {};
tooltip.dataPoints.forEach(function (point) {
if (groups.hasOwnProperty(barChartData.datasets[point.datasetIndex].label)) {
groups[barChartData.datasets[point.datasetIndex].label] += parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
} else {
groups[barChartData.datasets[point.datasetIndex].label] = parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
}
});
// build tooltip rows
var rows = '';
Object.keys(groups).forEach(function (groupName) {
rows += renderTemplate('template-tooltip-row', {
group: groupName,
value: groups[groupName].toLocaleString(undefined, {minimumFractionDigits: 2})
});
});
// build tooltip
chart.canvas.parentNode.insertAdjacentHTML('beforeEnd', renderTemplate('template-tooltip', {
rows: rows,
title: tooltip.title[0]
}));
// position tooltip
const {offsetLeft: positionX, offsetTop: positionY} = chart.canvas;
container = chart.canvas.parentNode.querySelector('.tooltip');
container.style.left = positionX + tooltip.caretX + 'px';
container.style.top = positionY + tooltip.caretY + 'px';
container.style.font = tooltip.options.bodyFont.string;
container.style.padding = tooltip.options.padding + 'px ' + tooltip.options.padding + 'px';
}
}
}
}
});
/**
* render html template
* #param {string} templateId - id of html template
* #param {object} templateValues - values for each template placeholder
* #return {string} template content
*/
function renderTemplate(templateId, templateValues) {
var propHandle; // property key
var templateText; // html template content
var templateValue; // value for template placeholder
// get template content, replace each placeholder with value
templateText = document.querySelector('#' + templateId).innerHTML;
if (templateValues) {
for (propHandle in templateValues) {
if (templateValues.hasOwnProperty(propHandle)) {
templateValue = '';
// convert template value to string
if (templateValues[propHandle] !== null) {
if (templateValues[propHandle].hasOwnProperty('results')) {
templateValue = encodeURIComponent(JSON.stringify(templateValues[propHandle].results));
} else {
templateValue = templateValues[propHandle].toString();
}
}
// handle dollar sign in template value
if (templateValue.indexOf('$') > -1) {
templateValue = templateValue.replace(new RegExp('\\$', 'g'), '$$$');
}
// replace template placeholder(s) with template value
if (templateText.indexOf('{{' + propHandle + '}}') > -1) {
templateText = templateText.replace(
new RegExp('{{' + propHandle + '}}', 'g'),
templateValue
);
}
}
}
}
return templateText.trim();
}
});
.align-right {
text-align: right;
}
.table {
border-collapse: separate;
border-spacing: 0vw 0vw;
display: table;
}
.table-body {
display: table-row-group;
}
.table-cell {
display: table-cell;
padding: 4px;
}
.table-foot {
display: table-footer-group;
}
.table-head {
display: table-header-group;
}
.table-row {
display: table-row;
}
.title {
font-weight: bold;
}
.tooltip {
background-color: rgba(0, 0, 0, 0.85);
border-radius: 3px;
color: #ffffff;
pointer-events: none;
position: absolute;
transform: translate(-50%, 0);
transition: all 0.1s ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.0/dist/chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>
<script id="template-tooltip" type="text/html">
<div class="tooltip">
<div class="title">{{title}}</div>
<div class="table">
<div class="table-body">{{rows}}</div>
</div>
</div>
</script>
<script id="template-tooltip-row" type="text/html">
<div class="table-row">
<div class="table-cell title">{{group}}:</div>
<div class="table-cell align-right">{{value}}</div>
</div>
</script>
Is it possible to detect state and county based on coordinates from a click on OSM map (US only)?
I can get the coordinated using click event in Leaflet JS:
map.on('click', function(ev) {
console.log(ev.latlng);
});
I can also get location data by doing something l;like this:
map.on("click", function(ev) {
var ln = ev.latlng["lng"],
lt = ev.latlng["lat"];
pt = "https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat="+lt+"&lon="+ln;
});
Which will return json data that looks like this:
https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=28.964162684075685&lon=-98.29776763916017
But I can't seem to be able to figure out what to do next... How do I get the county and state values from it?
You can just fetch, Ajax from jquery or use axios.
let config = {
minZoom: 2,
maxZoom: 18,
};
const zoom = 5;
const lat = 28.964162684075685;
const lng = -98.29776763916017;
const map = L.map("map", config).setView([lat, lng], zoom);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
map.on("click", function(e) {
const { lat, lng } = e.latlng;
const api = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`;
fetchData(api).then((data) => {
const { county, state } = data.address;
console.log(county, state);
});
});
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (err) {
console.error(err);
}
}
*,
:after,
:before {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
height: 100%;
}
body,
html,
#map {
width: 100%;
height: 100%;
}
body {
position: relative;
min-height: 100%;
margin: 0;
padding: 0;
background-color: #f1f1f1;
}
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" rel="stylesheet" />
<div id="map"></div>
I have a map with a layer control that has overlays specified in the baselayer parameter:
var overlays = {
'Layer 1': mylayer1,
'Layer 2': mylayer2
};
L.control.layers( overlays, null, { collapsed: false } ).addTo( map );
I specify my layers as follows:
var mylayer1 = L.esri.featureLayer({
url: 'https://.../MapServer/5'
}).on( 'load', function ( e ) {
...
}).on( 'loading', function ( e ) {
...
}).bindPopup( function ( layer ) {
return L.Util.template( '<p>{_score}</p>', layer.feature.properties );
});
The issue is that when I change layers in the control the bindPopup event no longer gets called.
It's almost like the layer z-index is not updated. Would appreciate any insight on how I can address this.
See: https://codepen.io/jvanulde/pen/LYyOWZo
I see no one has given an answer.
A little around, but it works.
You add the id: x to each layer. Later in the loop you check which layer is active, and all the rest of the layers you add the style display: none.
window.addEventListener('DOMContentLoaded', () => {
let tiles = L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors, Points © 2012 LINZ'
});
let l1 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/1',
id: 0, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 1: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let l2 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/2',
id: 1, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 2: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let map = L.map('map', {
center: [49.2827, -123.1207],
zoom: 12,
layers: [tiles]
});
let overlays = {
'Layer 1': l1,
'Layer 2': l2
};
L.control.layers(overlays, null, {
collapsed: false
}).addTo(map);
l1.addTo(map);
map.on('baselayerchange', function(e) {
const layersCanvas = document.querySelectorAll('.leaflet-overlay-pane > canvas');
layersCanvas.forEach((layer, index) => {
layer.style.display = '';
if (index !== e.layer.options.id) {
layer.style.display = 'none';
}
});
});
});
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100vh;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet#3.0.2/dist/esri-leaflet.js"></script>
<div id="map"></div>
I use
https://openlayers.org/en/latest/examples/feature-move-animation.html
code snippet:
// This long string is placed here due to jsFiddle limitations.
// It is usually loaded with AJAX.
var polyline = [
'hldhx#lnau`BCG_EaC??cFjAwDjF??uBlKMd#}#z#??aC^yk#z_#se#b[wFdE??wFfE}N',
'fIoGxB_I\\gG}#eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^',
'aMyBiHOkFNoI`CcVvM??gG^gF_#iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_E',
'kUFmq#hBiOqBgTwS??iYse#gYq\\cp#ce#{vA}s#csJqaE}{#iRaqE{lBeRoIwd#_T{]_',
'Ngn#{PmhEwaA{SeF_u#kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs#',
'sPua#_OkXaMeT_Nwk#ob#gV}TiYs[uTwXoNmT{Uyb#wNg]{Nqa#oDgNeJu_#_G}YsFw]k',
'DuZyDmm#i_#uyIJe~#jCg|#nGiv#zUi_BfNqaAvIow#dEed#dCcf#r#qz#Egs#{Acu#mC',
'um#yIey#gGig#cK_m#aSku#qRil#we#{mAeTej#}Tkz#cLgr#aHko#qOmcEaJw~C{w#ka',
'i#qBchBq#kmBS{kDnBscBnFu_Dbc#_~QHeU`IuyDrC_}#bByp#fCyoA?qMbD}{AIkeAgB',
'k_A_A{UsDke#gFej#qH{o#qGgb#qH{`#mMgm#uQus#kL{_#yOmd#ymBgwE}x#ouBwtA__',
'DuhEgaKuWct#gp#cnBii#mlBa_#}|Asj#qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAw',
'Xyn#ywMyOyqD{_#cfIcDe}#y#aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrX',
'itAhT}x#bE}Z_#qW_Kwv#qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi#',
'xBycBeCauBoF}}#qJioAww#gjHaPopA_NurAyJku#uGmi#cDs[eRaiBkQstAsQkcByNma',
'CsK_uBcJgbEw#gkB_#ypEqDoqSm#eZcDwjBoGw`BoMegBaU_`Ce_#_uBqb#ytBwkFqiT_',
'fAqfEwe#mfCka#_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o',
'~CfIewG|YibQxBssB?es#qGciA}RorAoVajA_nAodD{[y`AgPqp#mKwr#ms#umEaW{dAm',
'b#umAw|#ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux#}_Dui#_eB_u#guCuyAuiHukA_',
'lKszAu|OmaA{wKm}#clHs_A_rEahCssKo\\sgBsSglAqk#yvDcS_wAyTwpBmPc|BwZknF',
'oFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq#m~Hym#c`EuiBudIabB{hF{pWifx#snA',
'w`GkFyVqf#y~BkoAi}Lel#wtc#}`#oaXi_C}pZsi#eqGsSuqJ|Lqeb#e]kgPcaAu}SkDw',
'zGhn#gjYh\\qlNZovJieBqja#ed#siO{[ol\\kCmjMe\\isHorCmec#uLebB}EqiBaCg}',
'#m#qwHrT_vFps#kkI`uAszIrpHuzYxx#e{Crw#kpDhN{wBtQarDy#knFgP_yCu\\wyCwy',
'A{kHo~#omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm#_bAumFo}DgqA_uByi',
'#swC~AkzDlhA}xEvcBa}Cxk#ql#`rAo|#~bBq{#``Bye#djDww#z_C_cAtn#ye#nfC_eC',
'|gGahH~s#w}#``Fi~FpnAooC|u#wlEaEedRlYkrPvKerBfYs}Arg#m}AtrCkzElw#gjBb',
'h#woBhR{gCwGkgCc[wtCuOapAcFoh#uBy[yBgr#c#iq#o#wvEv#sp#`FajBfCaq#fIipA',
'dy#ewJlUc`ExGuaBdEmbBpBssArAuqBBg}#s#g{AkB{bBif#_bYmC}r#kDgm#sPq_BuJ_',
's#{X_{AsK_d#eM{d#wVgx#oWcu#??aDmOkNia#wFoSmDyMyCkPiBePwAob#XcQ|#oNdCo',
'SfFwXhEmOnLi\\lbAulB`X_d#|k#au#bc#oc#bqC}{BhwDgcD`l#ed#??bL{G|a#eTje#',
'oS~]cLr~Bgh#|b#}Jv}EieAlv#sPluD{z#nzA_]`|KchCtd#sPvb#wSb{#ko#f`RooQ~e',
'[upZbuIolI|gFafFzu#iq#nMmJ|OeJn^{Qjh#yQhc#uJ~j#iGdd#kAp~BkBxO{#|QsAfY',
'gEtYiGd]}Jpd#wRhVoNzNeK`j#ce#vgK}cJnSoSzQkVvUm^rSgc#`Uql#xIq\\vIgg#~k',
'Dyq[nIir#jNoq#xNwc#fYik#tk#su#neB}uBhqEesFjoGeyHtCoD|D}Ed|#ctAbIuOzqB',
'_}D~NgY`\\um#v[gm#v{Cw`G`w#o{AdjAwzBh{C}`Gpp#ypAxn#}mAfz#{bBbNia#??jI',
'ab#`CuOlC}YnAcV`#_^m#aeB}#yk#YuTuBg^uCkZiGk\\yGeY}Lu_#oOsZiTe[uWi[sl#',
'mo#soAauAsrBgzBqgAglAyd#ig#asAcyAklA}qAwHkGi{#s~#goAmsAyDeEirB_{B}IsJ',
'uEeFymAssAkdAmhAyTcVkFeEoKiH}l#kp#wg#sj#ku#ey#uh#kj#}EsFmG}Jk^_r#_f#m',
'~#ym#yjA??a#cFd#kBrCgDbAUnAcBhAyAdk#et#??kF}D??OL'
].join('');
var route = /** #type {module:ol/geom/LineString~LineString} */ (new ol.format.Polyline({
factor: 1e6
}).readGeometry(polyline, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}));
var routeCoords = route.getCoordinates();
var routeLength = routeCoords.length;
var routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
var geoMarker = new ol.Feature({
type: 'geoMarker',
geometry: new ol.geom.Point(routeCoords[0])
});
var startMarker = new ol.Feature({
type: 'icon',
geometry: new ol.geom.Point(routeCoords[0])
});
var endMarker = new ol.Feature({
type: 'icon',
geometry: new ol.geom.Point(routeCoords[routeLength - 1])
});
var styles = {
'route': new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6,
color: [237, 212, 0, 0.8]
})
}),
'icon': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'https://openlayers.org/en/v4.6.5/examples/data/icon.png'
})
}),
'geoMarker': new ol.style.Style({
image: new ol.style.Circle({ // CircleStyle({
radius: 7,
snapToPixel: false,
fill: new ol.style.Fill({
color: 'black'
}),
stroke: new ol.style.Stroke({
color: 'white',
width: 2
})
})
})
};
var animating = false;
var speed, now;
var speedInput = document.getElementById('speed');
var startButton = document.getElementById('start-animation');
var vectorLayer = new ol.layer.Vector({ // VectorLayer({
source: new ol.source.Vector({ // VectorSource({
features: [routeFeature, geoMarker, startMarker, endMarker]
}),
style: function(feature) {
// hide geoMarker if animation is active
if (animating && feature.get('type') === 'geoMarker') {
return null;
}
return styles[feature.get('type')];
}
});
var center = [-5639523.95, -3501274.52];
var map = new ol.Map({
target: document.getElementById('map'),
loadTilesWhileAnimating: true,
view: new ol.View({
center: center,
zoom: 9,
minZoom: 2,
maxZoom: 19
}),
layers: [
new ol.layer.Tile({ // TileLayer({
source: new ol.source.OSM()
}),
vectorLayer
]
});
var moveFeature = function(event) {
var vectorContext = event.vectorContext;
var frameState = event.frameState;
if (animating) {
var elapsedTime = frameState.time - now;
// here the trick to increase speed is to jump some indexes
// on lineString coordinates
var index = Math.round(speed * elapsedTime / 1000);
if (index >= routeLength) {
stopAnimation(true);
return;
}
var currentPoint = new ol.geom.Point(routeCoords[index]);
var feature = new ol.Feature(currentPoint);
vectorContext.drawFeature(feature, styles.geoMarker);
}
// tell OpenLayers to continue the postcompose animation
map.render();
};
function startAnimation() {
if (animating) {
stopAnimation(false);
} else {
animating = true;
now = new Date().getTime();
speed = speedInput.value;
startButton.textContent = 'Cancel Animation';
// hide geoMarker
geoMarker.setStyle(null);
// just in case you pan somewhere else
map.getView().setCenter(center);
map.on('postcompose', moveFeature);
map.render();
}
}
/**
* #param {boolean} ended end of animation.
*/
function stopAnimation(ended) {
animating = false;
startButton.textContent = 'Start Animation';
// if animation cancelled set the marker at the beginning
var coord = ended ? routeCoords[routeLength - 1] : routeCoords[0];
/** #type {module:ol/geom/Point~Point} */
(geoMarker.getGeometry())
.setCoordinates(coord);
//remove listener
map.un('postcompose', moveFeature);
}
startButton.addEventListener('click', startAnimation, false);
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 90%;
width: 100%;
}
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.1.3/build/ol.js"></script>
<div id="map" class="map"></div>
<label for="speed">
speed:
<input id="speed" type="range" min="10" max="999" step="10" value="60">
</label>
<button id="start-animation">Start Animation</button>
but I need to move marker smoothly between two point (or many)
See ol-ext : featureAnimation
example from that library's documentation
code snippet (example from the OpenLayers documentation using ol-ext):
// use window.onload so can move encoded polyline definition to bottom
window.onload = function() {
var route = /** #type {module:ol/geom/LineString~LineString} */ (new ol.format.Polyline({
factor: 1e6
}).readGeometry(polyline, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}));
var routeCoords = route.getCoordinates();
var routeLength = routeCoords.length;
var routePts = new ol.Feature({
type: 'route',
geometry: new ol.geom.MultiPoint(routeCoords)
});
var routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
var geoMarker = new ol.Feature({
type: 'geoMarker',
geometry: new ol.geom.Point(routeCoords[0])
});
var startMarker = new ol.Feature({
type: 'icon',
geometry: new ol.geom.Point(routeCoords[0])
});
var endMarker = new ol.Feature({
type: 'icon',
geometry: new ol.geom.Point(routeCoords[routeLength - 1])
});
var styles = {
'route': new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6,
color: [237, 212, 0, 0.8]
}),
image: new ol.style.Circle({
radius: 1,
snapToPixel: false,
fill: new ol.style.Fill({
color: 'red'
})
})
}),
'icon': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'https://openlayers.org/en/v4.6.5/examples/data/icon.png'
})
}),
'geoMarker': new ol.style.Style({
image: new ol.style.Circle({ // CircleStyle({
radius: 7,
snapToPixel: false,
fill: new ol.style.Fill({
color: 'black'
}),
stroke: new ol.style.Stroke({
color: 'white',
width: 2
})
})
})
};
var animating = false;
var speed, now;
var speedInput = document.getElementById('speed');
var startButton = document.getElementById('start-animation');
var vectorLayer = new ol.layer.Vector({ // VectorLayer({
source: new ol.source.Vector({ // VectorSource({
features: [routePts, routeFeature, geoMarker, startMarker, endMarker]
}),
style: function(feature) {
return styles[feature.get('type')];
}
});
var center = [-5639523.95, -3501274.52];
var map = new ol.Map({
target: document.getElementById('map'),
loadTilesWhileAnimating: true,
view: new ol.View({
center: center,
zoom: 9,
minZoom: 2,
maxZoom: 19
}),
layers: [
new ol.layer.Tile({ // TileLayer({
source: new ol.source.OSM()
}),
vectorLayer
]
});
console.log("init speed=" + speedInput.value / 100);
function startAnimation() {
if (animating) animating.stop();
console.log("update speed=" + Number(speedInput.value) / 100);
// anim.set("speed", Number(speedInput.value)/10);
var anim = new ol.featureAnimation.Path({
path: route,
easing: ol.easing.linear,
speed: Number(speedInput.value) / 100
});
animating = vectorLayer.animateFeature(geoMarker, anim);
}
geoMarker.on('change', function() {
map.getView().setCenter(geoMarker.getGeometry().getCoordinates());
});
startButton.addEventListener('click', startAnimation, false);
}
// This long string is placed here due to jsFiddle limitations.
// It is usually loaded with AJAX.
var polyline = [
'hldhx#lnau`BCG_EaC??cFjAwDjF??uBlKMd#}#z#??aC^yk#z_#se#b[wFdE??wFfE}N',
'fIoGxB_I\\gG}#eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^',
'aMyBiHOkFNoI`CcVvM??gG^gF_#iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_E',
'kUFmq#hBiOqBgTwS??iYse#gYq\\cp#ce#{vA}s#csJqaE}{#iRaqE{lBeRoIwd#_T{]_',
'Ngn#{PmhEwaA{SeF_u#kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs#',
'sPua#_OkXaMeT_Nwk#ob#gV}TiYs[uTwXoNmT{Uyb#wNg]{Nqa#oDgNeJu_#_G}YsFw]k',
'DuZyDmm#i_#uyIJe~#jCg|#nGiv#zUi_BfNqaAvIow#dEed#dCcf#r#qz#Egs#{Acu#mC',
'um#yIey#gGig#cK_m#aSku#qRil#we#{mAeTej#}Tkz#cLgr#aHko#qOmcEaJw~C{w#ka',
'i#qBchBq#kmBS{kDnBscBnFu_Dbc#_~QHeU`IuyDrC_}#bByp#fCyoA?qMbD}{AIkeAgB',
'k_A_A{UsDke#gFej#qH{o#qGgb#qH{`#mMgm#uQus#kL{_#yOmd#ymBgwE}x#ouBwtA__',
'DuhEgaKuWct#gp#cnBii#mlBa_#}|Asj#qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAw',
'Xyn#ywMyOyqD{_#cfIcDe}#y#aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrX',
'itAhT}x#bE}Z_#qW_Kwv#qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi#',
'xBycBeCauBoF}}#qJioAww#gjHaPopA_NurAyJku#uGmi#cDs[eRaiBkQstAsQkcByNma',
'CsK_uBcJgbEw#gkB_#ypEqDoqSm#eZcDwjBoGw`BoMegBaU_`Ce_#_uBqb#ytBwkFqiT_',
'fAqfEwe#mfCka#_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o',
'~CfIewG|YibQxBssB?es#qGciA}RorAoVajA_nAodD{[y`AgPqp#mKwr#ms#umEaW{dAm',
'b#umAw|#ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux#}_Dui#_eB_u#guCuyAuiHukA_',
'lKszAu|OmaA{wKm}#clHs_A_rEahCssKo\\sgBsSglAqk#yvDcS_wAyTwpBmPc|BwZknF',
'oFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq#m~Hym#c`EuiBudIabB{hF{pWifx#snA',
'w`GkFyVqf#y~BkoAi}Lel#wtc#}`#oaXi_C}pZsi#eqGsSuqJ|Lqeb#e]kgPcaAu}SkDw',
'zGhn#gjYh\\qlNZovJieBqja#ed#siO{[ol\\kCmjMe\\isHorCmec#uLebB}EqiBaCg}',
'#m#qwHrT_vFps#kkI`uAszIrpHuzYxx#e{Crw#kpDhN{wBtQarDy#knFgP_yCu\\wyCwy',
'A{kHo~#omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm#_bAumFo}DgqA_uByi',
'#swC~AkzDlhA}xEvcBa}Cxk#ql#`rAo|#~bBq{#``Bye#djDww#z_C_cAtn#ye#nfC_eC',
'|gGahH~s#w}#``Fi~FpnAooC|u#wlEaEedRlYkrPvKerBfYs}Arg#m}AtrCkzElw#gjBb',
'h#woBhR{gCwGkgCc[wtCuOapAcFoh#uBy[yBgr#c#iq#o#wvEv#sp#`FajBfCaq#fIipA',
'dy#ewJlUc`ExGuaBdEmbBpBssArAuqBBg}#s#g{AkB{bBif#_bYmC}r#kDgm#sPq_BuJ_',
's#{X_{AsK_d#eM{d#wVgx#oWcu#??aDmOkNia#wFoSmDyMyCkPiBePwAob#XcQ|#oNdCo',
'SfFwXhEmOnLi\\lbAulB`X_d#|k#au#bc#oc#bqC}{BhwDgcD`l#ed#??bL{G|a#eTje#',
'oS~]cLr~Bgh#|b#}Jv}EieAlv#sPluD{z#nzA_]`|KchCtd#sPvb#wSb{#ko#f`RooQ~e',
'[upZbuIolI|gFafFzu#iq#nMmJ|OeJn^{Qjh#yQhc#uJ~j#iGdd#kAp~BkBxO{#|QsAfY',
'gEtYiGd]}Jpd#wRhVoNzNeK`j#ce#vgK}cJnSoSzQkVvUm^rSgc#`Uql#xIq\\vIgg#~k',
'Dyq[nIir#jNoq#xNwc#fYik#tk#su#neB}uBhqEesFjoGeyHtCoD|D}Ed|#ctAbIuOzqB',
'_}D~NgY`\\um#v[gm#v{Cw`G`w#o{AdjAwzBh{C}`Gpp#ypAxn#}mAfz#{bBbNia#??jI',
'ab#`CuOlC}YnAcV`#_^m#aeB}#yk#YuTuBg^uCkZiGk\\yGeY}Lu_#oOsZiTe[uWi[sl#',
'mo#soAauAsrBgzBqgAglAyd#ig#asAcyAklA}qAwHkGi{#s~#goAmsAyDeEirB_{B}IsJ',
'uEeFymAssAkdAmhAyTcVkFeEoKiH}l#kp#wg#sj#ku#ey#uh#kj#}EsFmG}Jk^_r#_f#m',
'~#ym#yjA??a#cFd#kBrCgDbAUnAcBhAyAdk#et#??kF}D??OL'
].join('');
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 90%;
width: 100%;
}
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.1.3/build/ol.js"></script>
<script src="https://cdn.rawgit.com/Viglino/ol-ext/master/dist/ol-ext.js"></script>
<button id="start-animation">Start Animation</button>
<label for="speed">
speed:
<input id="speed" type="range" min="10" max="4999" step="10" value="500">
</label>
<div id="map" class="map"></div>
The OpenLayers example doesn't move smoothly as the only coordinates it uses are the points where the linestring changes direction. Therefore long straights are traversed much faster than the curved sections. The ol-ext method breaks the linestring into small equal length segments, but it seems to be animating the view to keep up with the marker instead of simply animating the marker. By reusing the splitLineString function from the second part of the answer to this question https://gis.stackexchange.com/questions/306976/add-image-along-the-linestring to finely divide the linestring and setting only one icon style based on a timer based index it is possible to achieve a smooth movement independently of the view (best seen in a full screen window) and also allows the icon to stay aligned with the direction of travel.
// This long string is placed here due to jsFiddle limitations.
// It is usually loaded with AJAX.
var polyline = [
'hldhx#lnau`BCG_EaC??cFjAwDjF??uBlKMd#}#z#??aC^yk#z_#se#b[wFdE??wFfE}N',
'fIoGxB_I\\gG}#eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^',
'aMyBiHOkFNoI`CcVvM??gG^gF_#iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_E',
'kUFmq#hBiOqBgTwS??iYse#gYq\\cp#ce#{vA}s#csJqaE}{#iRaqE{lBeRoIwd#_T{]_',
'Ngn#{PmhEwaA{SeF_u#kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs#',
'sPua#_OkXaMeT_Nwk#ob#gV}TiYs[uTwXoNmT{Uyb#wNg]{Nqa#oDgNeJu_#_G}YsFw]k',
'DuZyDmm#i_#uyIJe~#jCg|#nGiv#zUi_BfNqaAvIow#dEed#dCcf#r#qz#Egs#{Acu#mC',
'um#yIey#gGig#cK_m#aSku#qRil#we#{mAeTej#}Tkz#cLgr#aHko#qOmcEaJw~C{w#ka',
'i#qBchBq#kmBS{kDnBscBnFu_Dbc#_~QHeU`IuyDrC_}#bByp#fCyoA?qMbD}{AIkeAgB',
'k_A_A{UsDke#gFej#qH{o#qGgb#qH{`#mMgm#uQus#kL{_#yOmd#ymBgwE}x#ouBwtA__',
'DuhEgaKuWct#gp#cnBii#mlBa_#}|Asj#qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAw',
'Xyn#ywMyOyqD{_#cfIcDe}#y#aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrX',
'itAhT}x#bE}Z_#qW_Kwv#qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi#',
'xBycBeCauBoF}}#qJioAww#gjHaPopA_NurAyJku#uGmi#cDs[eRaiBkQstAsQkcByNma',
'CsK_uBcJgbEw#gkB_#ypEqDoqSm#eZcDwjBoGw`BoMegBaU_`Ce_#_uBqb#ytBwkFqiT_',
'fAqfEwe#mfCka#_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o',
'~CfIewG|YibQxBssB?es#qGciA}RorAoVajA_nAodD{[y`AgPqp#mKwr#ms#umEaW{dAm',
'b#umAw|#ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux#}_Dui#_eB_u#guCuyAuiHukA_',
'lKszAu|OmaA{wKm}#clHs_A_rEahCssKo\\sgBsSglAqk#yvDcS_wAyTwpBmPc|BwZknF',
'oFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq#m~Hym#c`EuiBudIabB{hF{pWifx#snA',
'w`GkFyVqf#y~BkoAi}Lel#wtc#}`#oaXi_C}pZsi#eqGsSuqJ|Lqeb#e]kgPcaAu}SkDw',
'zGhn#gjYh\\qlNZovJieBqja#ed#siO{[ol\\kCmjMe\\isHorCmec#uLebB}EqiBaCg}',
'#m#qwHrT_vFps#kkI`uAszIrpHuzYxx#e{Crw#kpDhN{wBtQarDy#knFgP_yCu\\wyCwy',
'A{kHo~#omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm#_bAumFo}DgqA_uByi',
'#swC~AkzDlhA}xEvcBa}Cxk#ql#`rAo|#~bBq{#``Bye#djDww#z_C_cAtn#ye#nfC_eC',
'|gGahH~s#w}#``Fi~FpnAooC|u#wlEaEedRlYkrPvKerBfYs}Arg#m}AtrCkzElw#gjBb',
'h#woBhR{gCwGkgCc[wtCuOapAcFoh#uBy[yBgr#c#iq#o#wvEv#sp#`FajBfCaq#fIipA',
'dy#ewJlUc`ExGuaBdEmbBpBssArAuqBBg}#s#g{AkB{bBif#_bYmC}r#kDgm#sPq_BuJ_',
's#{X_{AsK_d#eM{d#wVgx#oWcu#??aDmOkNia#wFoSmDyMyCkPiBePwAob#XcQ|#oNdCo',
'SfFwXhEmOnLi\\lbAulB`X_d#|k#au#bc#oc#bqC}{BhwDgcD`l#ed#??bL{G|a#eTje#',
'oS~]cLr~Bgh#|b#}Jv}EieAlv#sPluD{z#nzA_]`|KchCtd#sPvb#wSb{#ko#f`RooQ~e',
'[upZbuIolI|gFafFzu#iq#nMmJ|OeJn^{Qjh#yQhc#uJ~j#iGdd#kAp~BkBxO{#|QsAfY',
'gEtYiGd]}Jpd#wRhVoNzNeK`j#ce#vgK}cJnSoSzQkVvUm^rSgc#`Uql#xIq\\vIgg#~k',
'Dyq[nIir#jNoq#xNwc#fYik#tk#su#neB}uBhqEesFjoGeyHtCoD|D}Ed|#ctAbIuOzqB',
'_}D~NgY`\\um#v[gm#v{Cw`G`w#o{AdjAwzBh{C}`Gpp#ypAxn#}mAfz#{bBbNia#??jI',
'ab#`CuOlC}YnAcV`#_^m#aeB}#yk#YuTuBg^uCkZiGk\\yGeY}Lu_#oOsZiTe[uWi[sl#',
'mo#soAauAsrBgzBqgAglAyd#ig#asAcyAklA}qAwHkGi{#s~#goAmsAyDeEirB_{B}IsJ',
'uEeFymAssAkdAmhAyTcVkFeEoKiH}l#kp#wg#sj#ku#ey#uh#kj#}EsFmG}Jk^_r#_f#m',
'~#ym#yjA??a#cFd#kBrCgDbAUnAcBhAyAdk#et#??kF}D??OL'
].join('');
function splitLineString(geometry, minSegmentLength, options) {
function calculatePointsDistance(coord1, coord2) {
var dx = coord1[0] - coord2[0];
var dy = coord1[1] - coord2[1];
return Math.sqrt(dx * dx + dy * dy);
};
function calculateSplitPointCoords(startNode, nextNode, distanceBetweenNodes, distanceToSplitPoint) {
var d = distanceToSplitPoint / distanceBetweenNodes;
var x = nextNode[0] + (startNode[0] - nextNode[0]) * d;
var y = nextNode[1] + (startNode[1] - nextNode[1]) * d;
return [x, y];
};
function calculateAngle(startNode, nextNode, alwaysUp) {
var x = (startNode[0] - nextNode[0]);
var y = (startNode[1] - nextNode[1]);
var angle = Math.atan(x/y);
if (!alwaysUp) {
angle = y > 0 ? angle + Math.PI : x < 0 ? angle + Math.PI*2 : angle;
}
return angle;
};
var splitPoints = [];
var coords = geometry.getCoordinates();
var coordIndex = 0;
var startPoint = coords[coordIndex];
var nextPoint = coords[coordIndex + 1];
var angle = calculateAngle(startPoint, nextPoint, options.alwaysUp);
var n = Math.ceil(geometry.getLength()/minSegmentLength);
var segmentLength = geometry.getLength() / n;
var currentSegmentLength = options.midPoints ? segmentLength/2 : segmentLength;
for (var i = 0; i <= n; i++) {
var distanceBetweenPoints = calculatePointsDistance(startPoint, nextPoint);
currentSegmentLength += distanceBetweenPoints;
if (currentSegmentLength < segmentLength) {
coordIndex++;
if(coordIndex < coords.length - 1) {
startPoint = coords[coordIndex];
nextPoint = coords[coordIndex + 1];
angle = calculateAngle(startPoint, nextPoint, options.alwaysUp);
i--;
continue;
} else {
if (!options.midPoints) {
var splitPointCoords = nextPoint;
splitPointCoords.push(angle);
splitPoints.push(splitPointCoords);
}
break;
}
} else {
var distanceToSplitPoint = currentSegmentLength - segmentLength;
var splitPointCoords = calculateSplitPointCoords(startPoint, nextPoint, distanceBetweenPoints, distanceToSplitPoint);
startPoint = splitPointCoords.slice();
splitPointCoords.push(angle);
splitPoints.push(splitPointCoords);
currentSegmentLength = 0;
}
}
return splitPoints;
};
var route = new ol.format.Polyline({
factor: 1e6
}).readGeometry(polyline, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
});
var routeCoords = route.getCoordinates();
var routeLength = routeCoords.length;
var routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
var startMarker = new ol.Feature({
type: 'icon',
geometry: new ol.geom.Point(routeCoords[0])
});
var endMarker = new ol.Feature({
type: 'icon',
geometry: new ol.geom.Point(routeCoords[routeLength - 1])
});
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var repeat = false;
var timer = -1;
var style = function(feature, resolution) {
if (feature.get('type') == 'route') {
var styles = [
new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6,
color: [237, 212, 0, 0.8],
})
})
];
if (timer < 0) {
feature.unset('splitPoints', true);
} else {
var splitPoints = feature.get('splitPoints');
if (!splitPoints) {
splitPoints = splitLineString(feature.getGeometry(), 2 * resolution, {alwaysUp: false, midPoints: true});
feature.set('splitPoints', splitPoints, true);
}
if (!repeat && timer >= splitPoints.length) {
stopAnimation(true);
} else {
var index = timer % splitPoints.length;
var point = splitPoints[index];
styles.push(
new ol.style.Style({
geometry: new ol.geom.Point([point[0],point[1]]),
image: new ol.style.Icon({
src: 'https://cdn1.iconfinder.com/data/icons/basic-ui-elements-color-round/3/19-32.png',
rotation: point[2]
}),
zIndex: 1
})
);
}
}
return styles;
} else {
return [
new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'https://openlayers.org/en/v4.6.5/examples/data/icon.png',
})
})
];
}
}
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
features: [routeFeature, startMarker, endMarker]
}),
style: style
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [-5639523.95, -3501274.52],
zoom: 10
})
});
var animating = false;
var token;
var speedInput = document.getElementById('speed');
var startButton = document.getElementById('start-animation');
function startAnimation() {
if (animating) {
stopAnimation(false);
} else {
animating = true;
startButton.textContent = 'Cancel Animation';
token = setInterval( function(){
timer++;
vector.setStyle(style);
}, 6000/speedInput.value);
}
}
function stopAnimation(ended) {
animating = false;
startButton.textContent = 'Start Animation';
clearInterval(token);
timer = -1;
if (!ended) {
vector.setStyle(style);
}
}
startButton.addEventListener('click', startAnimation, false);
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 90%;
width: 100%;
}
<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>
<label for="speed">
speed:
<input id="speed" type="range" min="10" max="999" step="10" value="200">
</label>
<button id="start-animation">Start Animation</button>
fairly new person to Javascript here.
I have tried to get a toggle to work for busline stops coordinators from Google Fusion Table on my Google Maps but I can seem to fix it. Tried several solutions that I found here on stackoverflow.
Anyone that can shed some light on this?
var map;
var busLine3;
var busLine3Id = "1kc0F0rZl17KNJZCyrvFrDbPVyTtbWZm14nxABgBR";
function initialize() {
var map = new google.maps.Map(document.getElementById('googft-mapCanvas'), {
center: new google.maps.LatLng(59.327677777000000, 18.062950644241347),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var busLine3 = new google.maps.FusionTablesLayer({
map: map,
heatmap: { enabled: false },
query: {
select: "col2",
from: busLine3Id,
},
options: {
styleId: 2,
templateId: 2
}
});
busLine3.setMap(map);
}
// Toggle the layer to hide/show
function changeLayer(tableidselections) {
if (tableidselections == busLine3Id){
if (document.getElementById("show_hide_layer1").checked == true) {
if(busLine3.getMap() == null) { busLine3.setMap(map); }
}
if (document.getElementById("show_hide_layer1").checked == false) {
busLine3.setMap(null); /*layersetoff*/
}
}
My index.html:
<head>
<style type="text/css">
html, body, #googft-mapCanvas {
height: 600px;
margin: 0;
padding: 0;
width: 800px;
}
</style>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false&v=3"></script>
<script type="text/javascript" src="mapScript.js"></script>
</head>
<body onload="initialize()";>
<h2>Enabled with Google Maps API (HTML and Javascript)</h2>
<input type="checkbox" id="show_hide_layer1" onclick="changeLayer(this.value);" checked="checked">Bus Line 3</input>
<input type="checkbox" id="show_hide_layer2" onclick="changeLayer(this.value);" checked="checked">Locations</input>
<div id="googft-mapCanvas"></div>
<br/>
Your problem is this line:
if (tableidselections == busLine3Id)
tableidselections is "on"; busLine3Id is "1kc0F0rZl17KNJZCyrvFrDbPVyTtbWZm14nxABgBR"
Once I fix that (change busLine3Id to "on", I get Uncaught TypeError: Cannot read property 'setMap' of undefined because busLine3 is local to your initialize function (you declare it in the global scope, var buseLin3, but then re-declare it locally in initalize.
Same issue with your map variable.
Working code snippet:
var map;
var busLine3;
var busLine3Id = "1kc0F0rZl17KNJZCyrvFrDbPVyTtbWZm14nxABgBR";
function initialize() {
map = new google.maps.Map(document.getElementById('googft-mapCanvas'), {
center: new google.maps.LatLng(59.327677777000000, 18.062950644241347),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
busLine3 = new google.maps.FusionTablesLayer({
map: map,
heatmap: {
enabled: false
},
query: {
select: "col2",
from: busLine3Id
},
options: {
styleId: 2,
templateId: 2
}
});
busLine3.setMap(map);
}
// Toggle the layer to hide/show
function changeLayer(tableidselections) {
if (tableidselections == "on") {
if (document.getElementById("show_hide_layer1").checked == true) {
if (busLine3.getMap() == null) {
busLine3.setMap(map);
}
}
if (document.getElementById("show_hide_layer1").checked == false) {
busLine3.setMap(null); /*layersetoff*/
}
}
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#googft-mapCanvas {
height: 600px;
margin: 0;
padding: 0;
width: 800px;
}
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&ext=.js"></script>
<h2>Enabled with Google Maps API (HTML and Javascript)</h2>
<input type="checkbox" id="show_hide_layer1" onclick="changeLayer(this.value);" checked="checked">Bus Line 3</input>
<input type="checkbox" id="show_hide_layer2" onclick="changeLayer(this.value);" checked="checked">Locations</input>
<div id="googft-mapCanvas"></div>
<br/>
working fiddle