var chart; mapboxgl.accessToken = 'pk.eyJ1IjoidW5lcGdyaWQiLCJhIjoiY2lrd293Z3RhMDAzNHd4bTR4YjE4MHM0byJ9.9c-Yt3p0aKFSO2tX6CR26Q'; var map = new mapboxgl.Map({ container: 'map', // container id style: 'mapbox://styles/mapbox/dark-v9', //hosted style id center: [-77.38, 39], // starting position zoom: 3 // starting zoom }); map.on('load', function() { map.addLayer({ "id": "points", "type": "circle", "source": { "type": "geojson", "data": rPoints(1000) }, 'paint': { // make circles larger as the user zooms from z12 to z22 'circle-radius': { 'base': 10, 'stops': [ [12, 3], [22, 20] ] }, 'circle-opacity': 0.8, // color circles by ethnicity, using data-driven styles 'circle-color': { property: 'nHgKg', type: 'exponential', stops: [ [0, '#03c5f7'], [1000, '#b503f7'] ] } } }); chartInit() map.on("render", chartSetData); }); function getData() { var vals = []; var layer = "points" if (!map.getLayer(layer)) return vals; var test = map.queryRenderedFeatures({ layers: [layer] }); test.forEach(function(f) { vals.push([f.properties.date, f.properties.nHgKg]); }) vals = vals.sort(function(a, b) { return a[0] - b[0]; }) return (vals); } function chartSetData() { data = getData(); if (!data || data.length == 0) return; chart.series[0].update({ data: data }) } function chartInit(data) { data = data || getData() || []; Highcharts.createElement('link', { href: 'https://fonts.googleapis.com/css?family=Unica+One', rel: 'stylesheet', type: 'text/css' }, null, document.getElementsByTagName('head')[0]); Highcharts.theme = { colors: ['#2b908f', '#90ee7e', '#f45b5b', '#7798BF', '#aaeeee', '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee' ], chart: { backgroundColor: { linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, stops: [ [0, '#2a2a2b'], [1, '#3e3e40'] ] }, style: { fontFamily: '\'Unica One\', sans-serif' }, plotBorderColor: '#606063' }, title: { style: { color: '#E0E0E3', textTransform: 'uppercase', fontSize: '20px' } }, subtitle: { style: { color: '#E0E0E3', textTransform: 'uppercase' } }, xAxis: { gridLineColor: '#707073', labels: { style: { color: '#E0E0E3' } }, lineColor: '#707073', minorGridLineColor: '#505053', tickColor: '#707073', title: { style: { color: '#A0A0A3' } } }, yAxis: { gridLineColor: '#707073', labels: { style: { color: '#E0E0E3' } }, lineColor: '#707073', minorGridLineColor: '#505053', tickColor: '#707073', tickWidth: 1, title: { style: { color: '#A0A0A3' } } }, tooltip: { backgroundColor: 'rgba(0, 0, 0, 0.85)', style: { color: '#F0F0F0' } }, plotOptions: { series: { dataLabels: { color: '#B0B0B3' }, marker: { lineColor: '#333' } }, boxplot: { fillColor: '#505053' }, candlestick: { lineColor: 'white' }, errorbar: { color: 'white' } }, legend: { itemStyle: { color: '#E0E0E3' }, itemHoverStyle: { color: '#FFF' }, itemHiddenStyle: { color: '#606063' } }, credits: { style: { color: '#666' } }, labels: { style: { color: '#707073' } }, drilldown: { activeAxisLabelStyle: { color: '#F0F0F3' }, activeDataLabelStyle: { color: '#F0F0F3' } }, navigation: { buttonOptions: { symbolStroke: '#DDDDDD', theme: { fill: '#505053' } } }, // scroll charts rangeSelector: { buttonTheme: { fill: '#505053', stroke: '#000000', style: { color: '#CCC' }, states: { hover: { fill: '#707073', stroke: '#000000', style: { color: 'white' } }, select: { fill: '#000003', stroke: '#000000', style: { color: 'white' } } } }, inputBoxBorderColor: '#505053', inputStyle: { backgroundColor: '#333', color: 'silver' }, labelStyle: { color: 'silver' } }, navigator: { handles: { backgroundColor: '#666', borderColor: '#AAA' }, outlineColor: '#CCC', maskFill: 'rgba(255,255,255,0.1)', series: { color: '#7798BF', lineColor: '#A6C7ED' }, xAxis: { gridLineColor: '#505053' } }, scrollbar: { barBackgroundColor: '#808083', barBorderColor: '#808083', buttonArrowColor: '#CCC', buttonBackgroundColor: '#606063', buttonBorderColor: '#606063', rifleColor: '#FFF', trackBackgroundColor: '#404043', trackBorderColor: '#404043' }, // special colors for some of the legendBackgroundColor: 'rgba(0, 0, 0, 0.5)', background2: '#505053', dataLabelsColor: '#B0B0B3', textColor: '#C0C0C0', contrastTextColor: '#F0F0F3', maskColor: 'rgba(255,255,255,0.3)' }; // Apply the theme Highcharts.setOptions(Highcharts.theme); chart = Highcharts.chart('container', { chart: { zoomType: 'x', events: { selection: function(event) { var layer = "points"; if(event.resetSelection){ map.setFilter(layer,[ 'all' ]) }else{ var ext = event.xAxis[0]; map.setFilter(layer,[ 'all', ['<','date',ext.max], ['>','date',ext.min] ]) } } } }, title: { text: 'Mercury consumption Hg (kg)' }, subtitle: { text: 'Click and drag to filter date' }, xAxis: { type: 'datetime' }, yAxis: { title: { text: 'nHgKg' } }, legend: { enabled: false }, plotOptions: { area: { fillColor: { linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, stops: [ [0, Highcharts.getOptions().colors[0]], [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')] ] }, marker: { radius: 2 }, lineWidth: 1, states: { hover: { lineWidth: 1 } }, threshold: null } }, series: [{ type: 'area', name: 'Mercury KG', data: data }] }); } function rCoord() { var coord = [ (Math.random() * 360) - 180, (Math.random() * 180) - 90 ] return coord } function rDate(base) { base = base || 0; mx = new Date(); mn = new Date("2004/12/02"); dd = Math.round(mx - (Math.random() * (mx - mn - base))); return (dd) } function rProp(base) { base = base || [0]; var a = (base[0] + 180) / 360 || Math.random(); var prop = { date: rDate(a * 1000), nHgKg: Math.round(a * 1000) } return prop; } function rPoint() { var coord = rCoord() var point = { type: "Feature", geometry: { type: "Point", coordinates: coord }, properties: rProp(coord) } return point; } function rPoints(n) { var gJson = { type: "FeatureCollection", features: [] }; n = n || 100; for (var i = 0; i < n; i++) { gJson.features.push(rPoint()); } return gJson; } function cloneArray(arr) { var i = arr.length; var clone = []; while (i--) { clone[i] = arr[i]; } return (clone); }; function getArrayStat(o) { if ( o.arr === undefined || o.arr.constructor != Array || o.arr.length === 0 ) return []; if ( o.stat == "quantile" && o.percentile && o.percentile.constructor == Array ) o.stat = "quantiles"; var arr = cloneArray(o.arr); var stat = o.stat ? o.stat : "max"; var len_o = arr.length; var len = len_o; function sortNumber(a, b) { return a - b; } opt = { "max": function() { var max = -Infinity; var v = 0; while (len--) { v = arr.pop(); if (v > max) { max = v; } } return max; }, "min": function() { var min = Infinity; while (len--) { v = arr.pop(); if (v < min) { min = v; } } return min; }, "sum": function() { var sum = 0; while (len--) { sum += arr.pop(); } return sum; }, "mean": function() { var sum = getArrayStat({ stat: "sum", arr: arr }); return sum / len_o; }, "median": function() { var median = getArrayStat({ stat: "quantile", arr: arr, percentile: 50 }); return median; }, "quantile": function() { arr.sort(sortNumber); o.percentile = o.percentile ? o.percentile : 50; index = o.percentile / 100 * (arr.length - 1); if (Math.floor(index) == index) { result = arr[index]; } else { i = Math.floor(index); fraction = index - i; result = arr[i] + (arr[i + 1] - arr[i]) * fraction; } return result; }, "quantiles": function() { var quantiles = {}; o.percentile.forEach(function(x) { var res = getArrayStat({ stat: "quantile", arr: arr, percentile: x }); quantiles[x] = res; }); return quantiles; }, "distinct": function() { var n = {}, r = []; while (len--) { if (!n[arr[len]]) { n[arr[len]] = true; r.push(arr[len]); } } return r; } }; return (opt[stat](o)); }; function printLayerStat() { var s = getLayerStat(); var elN = document.getElementById("sN"); var elMin = document.getElementById("sMin"); var elMax = document.getElementById("sMax"); var elPtil = document.getElementById("sPtil"); elN.innerHTML = s.n; elMin.innerHTML = s.min; elMax.innerHTML = s.max; elPtil.innerHTML = JSON.stringify(s.ptil); } function getLayerStat() { var test = map.queryRenderedFeatures({ layers: ['points'] }); var vals = []; test.forEach(function(f) { vals.push([ f.properties.date, f.properties.nHgKg ]); }) var out = { n: test.length, max: getArrayStat({ arr: vals, stat: 'max' }), min: getArrayStat({ arr: vals, stat: 'min' }), ptil: getArrayStat({ arr: vals, stat: 'quantiles', percentile: [25, 50, 75] }) } return (out) }