Last active
May 9, 2017 19:03
-
-
Save deldersveld/4b9d8f50af8fdf9651175c6200544a57 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
double #map required for map to appear in FF,Edge,IE (and I have no idea why) | |
final map should appear as fixed 60% width | |
fixed for scrolling story pane | |
top 55px because it covers up the Export button in DevTools... | |
*/ | |
#map { | |
position:absolute; | |
top:20px; | |
bottom:0; | |
width:100%; | |
} | |
/*BlueGranite Logo*/ | |
div.blue-granite-logo { | |
position:fixed; | |
bottom:0; | |
width:25px; | |
height:25px; | |
z-index:1; | |
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuOWwzfk4AAAUBSURBVEhLnVbrTxRXFN8P7szOa5fHAiK7CLjaVAJIeYiPRq22NHatom3sQ1YtCYkxtWgFyc4OUxW/tE18lDZFgWqbFGUB15Ui9KsmpkkfISaNG6IfRP6JCv567swsO6OG2J7kZO6eOff3u+d3z9y7rpexjWduVBadiO9bGk3o3o6knh8d1ZdGhyJrz/xcaaX8PwvrvWIglmz3qeMp5Wgc0gdfQmw8CnHrIQjsSb+VtjiyYxMPC7VEZw3lW1NfzkqiVxtztIlZZd/XkFdtAOeRwXMi3JxA7sES3gOOxhzvhXfleng/+grZ6vhsSI+HLYjFLaiOdiqfJyBXvGUCkjNABszGy4qCqKyqhJvnKMYZOW5egFK+Bd624blSffyUBfViC8SutXs/HYSnIGRMZuAGiM3/+PMvPHnyBFVV1Zk4kXAcD6GgFL7DV1DyRUK3IJ1WfvJmo3IsMScuXekAfdYvXurDvXv3UBQIPveOI5fyQ/AdG0ZZ7Op2C9q0TfoPnuzo+EOpcjutyjkxPXlNdTVycvNoH8xVZ97xFLOPeSgV2+BTx2bCejLTDEF1+JB04DwRiKT78xLVr23AzMwMduzY6Yi/9/5ePHr0CLuamgzydJynsbzvPILRoTaLwuXK1San5PJtlPACgvp6gyASiRgV2d+dPHUa8/PzUGOaI85cfHUTcqKTKYOgXh8JeDsS8Ai5jiQGWFe/Fo8fP0Zzc/MzEnkgy16IkoL1GzbSU16ILyxE8EE5nkCD/mPItTI2uFuKfAvBnSFgXltXlyEgne3vdF3H5ctXHBLJig+nu7uxZ88eI84TnvzxWQTU0Q9dhdr1NmFnjBJ52g8TrLa2LiORrRFYNYzg/v37KC1dsRBnvmXLVsw/fYoHDx4YJJxbgBjuQFC7GXUFupI6/85xs9cJsGHdeqOCSGQ//WbdwuKmmwQplJWVGbnpONtoieSLaRo1x7tmnIilN4/A3zmku4o7bx3x7I5RUMS6dQ2YnZ11VGCCeNDV1WVUwAjsFeTl5eHChW/gy8oxctNx9iHL4RMIqslOIomHpU96oNBKpqamsH//gQUCM5mHZhGUljGJ0vvDw08Ed+7cQV9fP3gPO9ts80guqfksStTBvS46rgt8HWPgpFz4c/3O1dCYVZBKmRLZQRjB7du30d/fT535fOu7xSx4qbuq1Z7lRhtnxX65q1S+bVRg6GmTaHp6GqGQedQY7+jp9/ttBNLCHOZsb5lLqzcjJzYxZRAwC3UNtvhaLlIS63dzVcfb220EpkQGQV7+4hVQ7hKPBPlAD/KjQ60WhcvV2vu7O1ubSHlr6HiwkmtqaonAPI3T7vfbJXLuwYKTAnJ1GFnq5HRNa6/bojBteXSkwdd+fU4oroDbk5Yt82RdxAgGBgYMArtEaWcSi8vKwXBWnx55w4J2Wol2o9Xbdg1CoMK6rMzVZSoYgCA6K2B56QrEIBF8dhXLukYOW5AvtuV0IsvtiX+Uut0Q6NplK6xaU41z584RgeQgMElov6h9pdeaQGfgXLGaWJwgbatODm/Iio7/7W25BLmqEbycbUjB0VVg3O30DbCPl5f9dE1vhdzyPSg/9Yoe32xBvJyxZgioiYPZ6q27vhNjkA9+B6lJo6+4A9IuDeLBHtL+Jv1b+fW3YnW4pab3mU3+r9bYPVJYGhsNF0UTR0KnknqBmjy8QovvfL37p0IrZRFzuf4FEuABqE86e1MAAAAASUVORK5CYII='); | |
} | |
/*mapbox-gl.css (v0.20.1)*/ | |
.mapboxgl-map { | |
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; | |
overflow: hidden; | |
position: relative; | |
-webkit-tap-highlight-color: rgba(0,0,0,0); | |
} | |
.mapboxgl-canvas-container.mapboxgl-interactive, | |
.mapboxgl-ctrl-nav-compass { | |
cursor: -webkit-grab; | |
cursor: -moz-grab; | |
cursor: grab; | |
} | |
.mapboxgl-canvas-container.mapboxgl-interactive:active, | |
.mapboxgl-ctrl-nav-compass:active { | |
cursor: -webkit-grabbing; | |
cursor: -moz-grabbing; | |
cursor: grabbing; | |
} | |
.mapboxgl-ctrl-top-left, | |
.mapboxgl-ctrl-top-right, | |
.mapboxgl-ctrl-bottom-left, | |
.mapboxgl-ctrl-bottom-right { position:absolute; } | |
.mapboxgl-ctrl-top-left { top:0; left:0; } | |
.mapboxgl-ctrl-top-right { top:0; right:0; } | |
.mapboxgl-ctrl-bottom-left { bottom:0; left:0; } | |
.mapboxgl-ctrl-bottom-right { right:0; bottom:0; } | |
.mapboxgl-ctrl { clear:both; } | |
.mapboxgl-ctrl-top-left .mapboxgl-ctrl { margin:10px 0 0 10px; float:left; } | |
.mapboxgl-ctrl-top-right .mapboxgl-ctrl{ margin:10px 10px 0 0; float:right; } | |
.mapboxgl-ctrl-bottom-left .mapboxgl-ctrl { margin:0 0 10px 10px; float:left; } | |
.mapboxgl-ctrl-bottom-right .mapboxgl-ctrl { margin:0 10px 10px 0; float:right; } | |
.mapboxgl-ctrl-group { | |
border-radius: 4px; | |
-moz-box-shadow: 0px 0px 2px rgba(0,0,0,0.1); | |
-webkit-box-shadow: 0px 0px 2px rgba(0,0,0,0.1); | |
box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.1); | |
overflow: hidden; | |
background: #fff; | |
} | |
.mapboxgl-ctrl-group > button { | |
width: 30px; | |
height: 30px; | |
display: block; | |
padding: 0; | |
outline: none; | |
border: none; | |
border-bottom: 1px solid #ddd; | |
box-sizing: border-box; | |
background-color: rgba(0,0,0,0); | |
cursor: pointer; | |
} | |
/* https://bugzilla.mozilla.org/show_bug.cgi?id=140562 */ | |
.mapboxgl-ctrl > button::-moz-focus-inner { | |
border: 0; | |
padding: 0; | |
} | |
.mapboxgl-ctrl > button:last-child { | |
border-bottom: 0; | |
} | |
.mapboxgl-ctrl > button:hover { | |
background-color: rgba(0,0,0,0.05); | |
} | |
.mapboxgl-ctrl-icon, | |
.mapboxgl-ctrl-icon > div.arrow { | |
speak: none; | |
-webkit-font-smoothing: antialiased; | |
-moz-osx-font-smoothing: grayscale; | |
} | |
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out { | |
padding: 5px; | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27m%207%2C9%20c%20-0.554%2C0%20-1%2C0.446%20-1%2C1%200%2C0.554%200.446%2C1%201%2C1%20l%206%2C0%20c%200.554%2C0%201%2C-0.446%201%2C-1%200%2C-0.554%20-0.446%2C-1%20-1%2C-1%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); | |
} | |
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in { | |
padding: 5px; | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); | |
} | |
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate { | |
padding: 5px; | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M13%2C7%20L10.5%2C11.75%20L10.25%2C10%20z%20M13.888%2C6.112%20C13.615%2C5.84%2013.382%2C6.076%2012.5%2C6.5%20C10.14%2C7.634%206%2C10%206%2C10%20L9.5%2C10.5%20L10%2C14%20C10%2C14%2012.366%2C9.86%2013.5%2C7.5%20C13.924%2C6.617%2014.16%2C6.385%2013.888%2C6.112%27%2F%3E%3C%2Fsvg%3E"); | |
} | |
.mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > div.arrow { | |
width: 20px; | |
height: 20px; | |
margin: 5px; | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%0A%09%3Cpolygon%20fill%3D%27%23333333%27%20points%3D%276%2C9%2010%2C1%2014%2C9%27%2F%3E%0A%09%3Cpolygon%20fill%3D%27%23CCCCCC%27%20points%3D%276%2C11%2010%2C19%2014%2C11%20%27%2F%3E%0A%3C%2Fsvg%3E"); | |
background-repeat: no-repeat; | |
} | |
.mapboxgl-ctrl.mapboxgl-ctrl-attrib { | |
padding: 0 5px; | |
background-color: rgba(255,255,255,0.5); | |
margin: 0; | |
} | |
.mapboxgl-ctrl-attrib a { | |
color: rgba(0,0,0,0.75); | |
text-decoration: none; | |
} | |
.mapboxgl-ctrl-attrib a:hover { | |
color: inherit; | |
text-decoration: underline; | |
} | |
.mapboxgl-ctrl-attrib .mapbox-improve-map { | |
font-weight: bold; | |
margin-left: 2px; | |
} | |
.mapboxgl-popup { | |
position: absolute; | |
top: 0; | |
left: 0; | |
display: -webkit-flex; | |
display: flex; | |
will-change: transform; | |
pointer-events: none; | |
} | |
.mapboxgl-popup-anchor-top, | |
.mapboxgl-popup-anchor-top-left, | |
.mapboxgl-popup-anchor-top-right { | |
-webkit-flex-direction: column; | |
flex-direction: column; | |
} | |
.mapboxgl-popup-anchor-bottom, | |
.mapboxgl-popup-anchor-bottom-left, | |
.mapboxgl-popup-anchor-bottom-right { | |
-webkit-flex-direction: column-reverse; | |
flex-direction: column-reverse; | |
} | |
.mapboxgl-popup-anchor-left { | |
-webkit-flex-direction: row; | |
flex-direction: row; | |
} | |
.mapboxgl-popup-anchor-right { | |
-webkit-flex-direction: row-reverse; | |
flex-direction: row-reverse; | |
} | |
.mapboxgl-popup-tip { | |
width: 0; | |
height: 0; | |
border: 10px solid transparent; | |
z-index: 1; | |
} | |
.mapboxgl-popup-anchor-top .mapboxgl-popup-tip { | |
-webkit-align-self: center; | |
align-self: center; | |
border-top: none; | |
border-bottom-color: #fff; | |
} | |
.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip { | |
-webkit-align-self: flex-start; | |
align-self: flex-start; | |
border-top: none; | |
border-left: none; | |
border-bottom-color: #fff; | |
} | |
.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip { | |
-webkit-align-self: flex-end; | |
align-self: flex-end; | |
border-top: none; | |
border-right: none; | |
border-bottom-color: #fff; | |
} | |
.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { | |
-webkit-align-self: center; | |
align-self: center; | |
border-bottom: none; | |
border-top-color: #fff; | |
} | |
.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip { | |
-webkit-align-self: flex-start; | |
align-self: flex-start; | |
border-bottom: none; | |
border-left: none; | |
border-top-color: #fff; | |
} | |
.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip { | |
-webkit-align-self: flex-end; | |
align-self: flex-end; | |
border-bottom: none; | |
border-right: none; | |
border-top-color: #fff; | |
} | |
.mapboxgl-popup-anchor-left .mapboxgl-popup-tip { | |
-webkit-align-self: center; | |
align-self: center; | |
border-left: none; | |
border-right-color: #fff; | |
} | |
.mapboxgl-popup-anchor-right .mapboxgl-popup-tip { | |
-webkit-align-self: center; | |
align-self: center; | |
border-right: none; | |
border-left-color: #fff; | |
} | |
.mapboxgl-popup-close-button { | |
position: absolute; | |
right: 0; | |
top: 0; | |
border: none; | |
border-radius: 0 3px 0 0; | |
cursor: pointer; | |
background-color: rgba(0,0,0,0); | |
} | |
.mapboxgl-popup-close-button:hover { | |
background-color: rgba(0,0,0,0.05); | |
} | |
.mapboxgl-popup-content { | |
position: relative; | |
background: #fff; | |
border-radius: 3px; | |
box-shadow: 0 1px 2px rgba(0,0,0,0.10); | |
padding: 10px 10px 15px; | |
pointer-events: auto; | |
} | |
.mapboxgl-popup-anchor-top-left .mapboxgl-popup-content { | |
border-top-left-radius: 0; | |
} | |
.mapboxgl-popup-anchor-top-right .mapboxgl-popup-content { | |
border-top-right-radius: 0; | |
} | |
.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-content { | |
border-bottom-left-radius: 0; | |
} | |
.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-content { | |
border-bottom-right-radius: 0; | |
} | |
.mapboxgl-crosshair, | |
.mapboxgl-crosshair .mapboxgl-interactive, | |
.mapboxgl-crosshair .mapboxgl-interactive:active { | |
cursor: crosshair; | |
} | |
.mapboxgl-boxzoom { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 0; | |
height: 0; | |
background: #fff; | |
border: 2px dotted #202020; | |
opacity: 0.5; | |
} | |
@media print { | |
.mapbox-improve-map { | |
display:none; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module powerbi.visuals { | |
import DataRoleHelper = powerbi.data.DataRoleHelper; | |
export class ScriptDependency { | |
private _timeoutHandle : number; | |
public addScript(alias: string, uri: string, callback?:()=>boolean) { | |
var deferred = $.Deferred(); | |
$.getScript(uri, (d, status, jqxhr)=>{ | |
if (jqxhr.status == 200) | |
{ | |
if (!callback){ | |
deferred.resolve(); | |
} | |
else { | |
this._timeoutHandle = setTimeout(()=>{this.doLoadedCallback(deferred, callback);}, 500); | |
} | |
} | |
else { | |
deferred.reject(); | |
} | |
}); | |
return deferred; | |
} | |
private doLoadedCallback(deferred : JQueryDeferred<any>, callback: ()=>boolean) : void | |
{ | |
if (callback()) | |
{ | |
clearTimeout(this._timeoutHandle); | |
deferred.resolve(); | |
} | |
else | |
{ | |
console.log("all kinds of having to retry"); | |
this._timeoutHandle = setTimeout(()=>{this.doLoadedCallback(deferred, callback);}, 500); | |
} | |
} | |
} | |
export interface CategoryViewModel { | |
value: string; | |
identity: string; | |
location: string; | |
} | |
export interface ValueViewModel { | |
values: any[]; | |
} | |
export interface RoleViewModel { | |
longitude: number; | |
latitude: number; | |
size: number; | |
icon: number; | |
} | |
export interface ViewModel { | |
categories: CategoryViewModel[]; | |
values: ValueViewModel[]; | |
} | |
export class BlueGraniteMapboxGLClusterMap implements IVisual { | |
public static capabilities: VisualCapabilities = { | |
dataRoles: [ | |
{ | |
name: 'Category', | |
kind: VisualDataRoleKind.Grouping, | |
displayName: 'Entity' | |
}, | |
{ | |
name: 'Latitude', | |
kind: powerbi.VisualDataRoleKind.Measure, | |
displayName: 'Latitude', | |
preferredTypes: [ | |
{ geography: { latitude: true } } | |
] | |
}, | |
{ | |
name: 'Longitude', | |
kind: powerbi.VisualDataRoleKind.Measure, | |
displayName: 'Longitude', | |
preferredTypes: [ | |
{ geography: { longitude: true } } | |
] | |
}, | |
{ | |
name: 'Size', | |
kind: powerbi.VisualDataRoleKind.Measure, | |
displayName: 'Heading (should be unique)' | |
}, | |
{ | |
name: 'Icon', | |
kind: powerbi.VisualDataRoleKind.Measure, | |
displayName: 'Body' | |
}, | |
], | |
dataViewMappings: [{ | |
conditions: [ | |
{ 'Category': { min: 1, max: 1 }, 'Latitude': { max: 1, kind: VisualDataRoleKind.Measure }, 'Longitude': { max: 1, kind: VisualDataRoleKind.Measure }, 'Size': { max: 1 }, 'Icon': { max: 0 } }, | |
{ 'Category': { min: 1, max: 1 }, 'Latitude': { max: 1, kind: VisualDataRoleKind.Measure }, 'Longitude': { max: 1, kind: VisualDataRoleKind.Measure }, 'Size': { max: 1 }, 'Icon': { max: 1 } }, | |
], | |
categorical: { | |
categories: { | |
for: { in: 'Category' }, | |
dataReductionAlgorithm: { top: {} } | |
}, | |
values: { | |
select: [ | |
{ bind: { to: 'Latitude' } }, | |
{ bind: { to: 'Longitude' } }, | |
{ bind: { to: 'Size' } }, | |
{ bind: { to: 'Icon' } }, | |
], | |
dataReductionAlgorithm: { top: {} } | |
}, | |
rowCount: { preferred: { min: 2 } }, | |
dataVolume: 4, | |
} | |
}, { | |
conditions: [ | |
{ 'Category': { max: 0 }, 'Latitude': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Longitude': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Size': { max: 1 }, 'Icon': { max: 0 } }, | |
{ 'Category': { max: 0 }, 'Latitude': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Longitude': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Size': { max: 1 }, 'Icon': { max: 1 } } | |
], | |
categorical: { | |
categories: { | |
select: [ | |
{ bind: { to: 'Latitude' } }, | |
{ bind: { to: 'Longitude' } }, | |
], | |
dataReductionAlgorithm: { top: {} } | |
}, | |
values: { | |
select: [ | |
{ bind: { to: 'Size' } }, | |
{ bind: { to: 'Icon' } }, | |
], | |
dataReductionAlgorithm: { top: {} } | |
}, | |
rowCount: { preferred: { min: 2 } }, | |
dataVolume: 4, | |
}, | |
}], | |
objects: { | |
general: { | |
displayName: data.createDisplayNameGetter('Visual_General'), | |
properties: { | |
formatString: { | |
type: { formatting: { formatString: true } }, | |
}, | |
}, | |
}, | |
} | |
}; | |
public static converter(dataView: DataView, colors: IDataColorPalette): ViewModel { | |
var viewModel: ViewModel = { | |
categories: [], | |
values: [] | |
} | |
//console.log("converter"); | |
//console.log(dataView); | |
var categorical = dataView.categorical; | |
if (categorical) { | |
var categories = categorical.categories; | |
var series = categorical.values; | |
var formatString = dataView.metadata.columns[0].format; | |
if (categories && categories.length > 0 && series.length > 0) { | |
for (var i = 0, catLength = categories[0].values.length; i < catLength; i++) { | |
viewModel.categories.push({ | |
location: categories[0].values[i], | |
value: categories[0].values[i], | |
identity: '' | |
}) | |
for (var k = 0, seriesLength = series.length; k < seriesLength; k++) { | |
var value = series[k].values[i]; | |
if (k == 0) { | |
viewModel.values.push({ values: [] }); | |
} | |
viewModel.values[i].values.push(value); | |
} | |
} | |
} | |
} | |
//console.log(viewModel); | |
return viewModel; | |
} | |
private hostContainer: JQuery; | |
private colorPalette: IDataColorPalette; | |
private dataView: DataView; | |
private map: D3.Selection; | |
private notification: D3.Selection; | |
private logo: D3.Selection; | |
public init(options: VisualInitOptions): void { | |
var deps = new ScriptDependency(); | |
deps.addScript("mapboxgl", "https://api.mapbox.com/mapbox-gl-js/v0.20.1/mapbox-gl.js", | |
():boolean=>{ return (typeof mapboxgl)!=undefined; }) | |
.done(()=>{ | |
console.log("done loading"); | |
}) | |
.fail(()=>{ | |
console.log("error loading dependency"); | |
}); | |
this.colorPalette = options.style.colorPalette.dataColors; | |
this.hostContainer = options.element.css('overflow-x', 'hidden'); | |
//add BlueGranite logo | |
var logo = this.logo = d3.select(options.element.get(0)) | |
.append("div") | |
.attr("class", "blue-granite-logo") | |
.on("click", function() { window.open("http://www.blue-granite.com"); }); | |
//add map div | |
var map = this.map = d3.select(options.element.get(0)) | |
.append("div") | |
.attr("id", "map") | |
.attr("height", options.viewport.height) | |
.attr("width", options.viewport.width); | |
//add story pane div | |
var notification = this.notification = d3.select(options.element.get(0)) | |
.append("div") | |
.attr("id", "notification") | |
.attr("height", options.viewport.height) | |
.attr("width", options.viewport.width); | |
} | |
public update(options: VisualUpdateOptions) { | |
var dataViews = this.dataView = options.dataViews; | |
if (!dataViews) return; | |
this.updateContainerViewports(options.viewport); | |
var viewModel = BlueGraniteMapboxGLClusterMap.converter(dataViews[0], this.colorPalette); | |
//get index values for roles | |
//console.log("data role helper"); | |
var lngIndex = -1; | |
var latIndex = -1; | |
var sizeIndex = -1; | |
var iconIndex = -1; | |
lngIndex = DataRoleHelper.getMeasureIndexOfRole(dataViews[0].categorical.values.grouped(), "Longitude"); | |
latIndex = DataRoleHelper.getMeasureIndexOfRole(dataViews[0].categorical.values.grouped(), "Latitude"); | |
sizeIndex = DataRoleHelper.getMeasureIndexOfRole(dataViews[0].categorical.values.grouped(), "Size"); | |
iconIndex = DataRoleHelper.getMeasureIndexOfRole(dataViews[0].categorical.values.grouped(), "Icon"); | |
//console.log("longitude: " + lngIndex); | |
//console.log("latitude: " + latIndex); | |
//console.log("size: " + sizeIndex); | |
//console.log("icon: " + iconIndex); | |
var roleModel = { | |
longitude: lngIndex, | |
latitude: latIndex, | |
size: sizeIndex, | |
icon: iconIndex | |
} | |
//console.log(roleModel); | |
//console.log(dataViews); | |
//console.log(viewModel); | |
//console.log(dataViews[0].metadata.columns); | |
//if exists, empty map and story to avoid duplicates on update | |
//$("#map").empty(); //disables flyto | |
$('#notification').children().remove(); | |
//field check prior to rendering map | |
if(viewModel.categories[0].value == null || roleModel.longitude == -1 || roleModel.latitude == -1 || roleModel.size == -1 || roleModel.icon == -1){ | |
var noteDiv = d3.select("#notification") | |
noteDiv.append("p") | |
.text("Map will load when Longitude, Latitude, Heading and Body have been added"); | |
return; | |
} | |
//create map | |
mapboxgl.accessToken = 'pk.eyJ1IjoiZGVsZGVyc3ZlbGQiLCJhIjoiY2lxZ2w2ZmE0MDN3amZvbnA1Z2E5a2IwMyJ9.v60RBnYtK9ajw88xFrZLJg'; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
//style: 'mapbox://styles/mapbox/streets-v9', | |
//style: 'mapbox://styles/mapbox/satellite-v9', | |
//style: 'mapbox://styles/mapbox/light-v9', | |
//style: 'mapbox://styles/mapbox/dark-v9', | |
style: 'mapbox://styles/mapbox/bright-v9', | |
//style: 'mapbox://styles/mapbox/outdoors-v9', | |
//style: 'mapbox://styles/mapbox/emerald-v8', | |
//style: 'mapbox://styles/mapbox/satellite-hybrid-v8', | |
//style: 'mapbox://styles/mapbox/empty-v9', | |
//style: 'mapbox://styles/deldersveld/ciqeooas3000bc9nnzkg2iivg', | |
//center: [-84.50, 42], | |
zoom: 7, | |
pitch: 0, // pitch in degrees (3d angle) | |
bearing: 0, // bearing in degrees (rotation) | |
attributionControl: { | |
position: 'top-right' | |
} | |
}); | |
//zoom and rotation controls | |
map.addControl(new mapboxgl.Navigation()); | |
//urban area polygons | |
/*map.on('load', function () { | |
map.addSource('urban-areas', { | |
'type': 'geojson', | |
'data': 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_urban_areas.geojson' | |
}); | |
map.addLayer({ | |
'id': 'urban-areas-fill', | |
'type': 'fill', | |
'source': 'urban-areas', | |
'layout': {}, | |
'paint': { | |
'fill-color': '#587abc', | |
'fill-opacity': 0.4 | |
} | |
}, 'urban'); | |
});*/ | |
AddPoints(viewModel, roleModel); | |
function AddPoints(data, roles){ | |
//structure PBI data as GeoJSON | |
var collection = {}; | |
var features = []; | |
for(var i in data.categories){ | |
//console.log(data.categories[i].value); | |
//console.log(data.values[i].values[0]); | |
//console.log(data.values[i].values[1]); | |
var feature = {}; | |
var geometry = {"type":"Point", "coordinates":[data.values[i].values[roles.longitude], data.values[i].values[roles.latitude]]}; | |
var properties = {"title":data.categories[i].value, "size": data.values[i].values[roles.size], "icon":data.values[i].values[roles.icon]} | |
feature["type"] = "Feature"; | |
feature["geometry"] = geometry; | |
feature["properties"] = properties; | |
features.push(feature); | |
} | |
collection["type"] = "FeatureCollection"; | |
collection["features"] = features; | |
map.on('load', function () { | |
//point clusters | |
if(1==1){ | |
map.addSource("points", { | |
"type": "geojson", | |
"data": collection, | |
cluster: true, | |
clusterMaxZoom: 14, | |
clusterRadius: 50 | |
}); | |
} | |
//dense points | |
else{ | |
map.addSource("points", { | |
"type": "geojson", | |
"data": collection | |
}); | |
} | |
//circles | |
map.addLayer({ | |
"id": "points", | |
"type": "circle", | |
"source": "points", | |
"paint": { | |
"circle-radius": 10, | |
"circle-color": "#007cbf" | |
} | |
}); | |
//begin clusters | |
var layers = [ | |
[150, '#fd625e', 30, 0, 0.9], | |
[50, '#f2c80f', 24, 0, 0.9], | |
[0, '#01b8aa', 18, 0, 0.9] | |
]; | |
layers.forEach(function (layer, i) { | |
map.addLayer({ | |
"id": "cluster-" + i, | |
"type": "circle", | |
"source": "points", | |
"paint": { | |
"circle-color": layer[1], | |
"circle-radius": layer[2], //100 for heat map //18 | |
"circle-blur": layer[3], //1 for heat map //.5 | |
"circle-opacity": layer[4] | |
}, | |
"filter": i === 0 ? | |
[">=", "point_count", layer[0]] : | |
["all", | |
[">=", "point_count", layer[0]], | |
["<", "point_count", layers[i - 1][0]]] | |
}); | |
}); | |
// Add a layer for the clusters' count labels | |
map.addLayer({ | |
"id": "cluster-count", | |
"type": "symbol", | |
"source": "points", | |
"layout": { | |
"text-field": "{point_count}", | |
"text-font": [ | |
"DIN Offc Pro Medium", | |
"Arial Unicode MS Bold" | |
], | |
"text-size": 14, | |
}, | |
"paint": { | |
"text-color": "#111111", | |
"text-halo-color": "#eeeeee", | |
"text-halo-width": 1 | |
}, | |
}); | |
//end clusters | |
}); | |
//fit bounds to data | |
var bounds = new mapboxgl.LngLatBounds(); | |
collection["features"].forEach(function(feature) { | |
bounds.extend(feature.geometry.coordinates); | |
}); | |
console.log(bounds); | |
map.fitBounds(bounds); | |
} | |
} | |
private updateContainerViewports(viewport: IViewport) { | |
var width = viewport.width; | |
var height = viewport.height; | |
var sandboxPadding = 10; | |
this.hostContainer.css({ | |
'height': height, | |
'width': width | |
}); | |
} | |
public destroy(): void { | |
this.logo = null; | |
this.map = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment