Create a gist now

Instantly share code, notes, and snippets.

@SaMnCo /Gemfile
Last active Oct 25, 2016

Dashing Dynamic Map

Preview

Description

This dynamap was inspired by an answer to the Dashing Contest that displayed information about recent earthquakes

However I needed something where it would be easy to add new dots based on dynamic/push information, hence this widget.

Dependencies

rest-client - convenient http client for retrieving quake data

Add to dashing's gemfile:

gem 'rest-client'

and run bundle install.

Usage

To use this widget, copy dynamap.html, dynamap.coffee, and dynamap.scss into the /widgets/dynamap directory.

You'll need to add the following line inside the header in the dashboards/layouts.erb file. Replace the '<YOUR_KEY>' with the free google api key you get from following the instructions on this page

<script src="https://maps.googleapis.com/maps/api/js?key=<YOUR_KEY>&sensor=false&libraries=visualization"></script>

To include the widget in a dashboard, add the following snippet to the dashboard layout file:

<li data-row="1" data-col="1" data-sizex="2" data-sizey="1">
  <div data-id="dynamap" data-view="dynamap" data-zoom=1 data-title="Dynamic Heat Map"></div>
</li>

On it is installed, you can push new points by doing

curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "Country": "Spain" }' \http://DASHING_HOST:DASHING_PORT/widgets/dynamap

You should see a new dot appear on the map.

Testing

You may or may not have a usecase right away but still want to see how this behaves. If that is the case put the dynamap.rb file in your /jobs folder and restart Dashing. Every 10s, a random number will be selected and if it matches a country, a dot will be added to the map.

Settings

Should you decide to use the dynamap widget for another source of data, you may find these configuration attributes helpful.

  • data-zoom => [0-15], 0 is global and 15 is street level, default is 2
  • data-center-lat and data-center-long => the map's centerpoint, default is centerish of US
  • data-map-type => [HYBRID | ROADMAP | SATELLITE | TERRAIN], default is SATELLITE

The full options for google Heatmap cam be seen here and can be configured in the coffeescript.

class Dashing.Dynamap extends Dashing.Widget
json_path = 'https://s3-us-west-2.amazonaws.com/samnco-static-files/country-maps/countries.jsonp'
json_countries = null
plots = []
jsonCountriesLoader = (url) ->
$.ajax
'jsonpCallback':"jsonCountriesLoader"
'contentType':"application/json"
'async': false
'global': false
'url': url
'dataType': "jsonp"
'success': (data) ->
json_countries = data
return json_countries
newCountry = (req_country) ->
json_countries = jsonCountriesLoader json_path
json_countries.countries.forEach( (country) ->
if country.name.common == req_country
name = country.name.common
coordinates = country.latlng
lat = coordinates[0]
long = coordinates[1]
plots.push { "name": name, "lat": lat, "long": long, "weight": 1 }
)
plotCountries = (plot_array) ->
for d in plot_array
location: new google.maps.LatLng(d.lat, d.long), weight: (d.weight)
ready: ->
mtype = switch @get('mapType')
when "TERRAIN" then google.maps.MapTypeId.TERRAIN
when "HYBRID" then google.maps.MapTypeId.HYBRID
when "ROADMAP" then google.maps.MapTypeId.ROADMAP
else google.maps.MapTypeId.ROADMAP
mapOptions = {
zoom: (@get('zoom') ? 1)
center: new google.maps.LatLng((@get('centerLat') ? 20), (@get('centerLong') ? -102.5))
mapTypeId: mtype
zoomControl: false
panControl: false
streetViewControl: false
scrollwheel: false
disableDoubleClickZoom: false
draggable: true
mapTypeControl: false
}
new_map = plotCountries(plots)
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions)
pointArray = new google.maps.MVCArray(new_map)
heatmap = new google.maps.visualization.HeatmapLayer({data: pointArray})
heatmap.setMap(map)
@onData(plots)
onData: (data) ->
if(!data)
data = plots
if(!data)
return
country = @get('country')
newCountry(country)
new_map = plotCountries(plots)
mtype = switch @get('mapType')
when "TERRAIN" then google.maps.MapTypeId.TERRAIN
when "HYBRID" then google.maps.MapTypeId.HYBRID
when "ROADMAP" then google.maps.MapTypeId.ROADMAP
else google.maps.MapTypeId.ROADMAP
mapOptions = {
zoom: (@get('zoom') ? 1)
center: new google.maps.LatLng((@get('centerLat') ? 20), (@get('centerLong') ? -102.5))
mapTypeId: mtype
zoomControl: false
panControl: false
streetViewControl: false
scrollwheel: false
disableDoubleClickZoom: false
draggable: true
mapTypeControl: false
}
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions)
pointArray = new google.maps.MVCArray(new_map)
heatmap = new google.maps.visualization.HeatmapLayer({data: pointArray})
heatmap.setMap(map)
$(@node).fadeOut().fadeIn()
<% content_for :title do %>Dynamic Map<% end %>
<div class="gridster">
<ul>
<li data-row="1" data-col="1" data-sizex="2" data-sizey="1">
<div data-id="dynamap" data-view="Dynamap" data-title="Dynamic Heat Map" data-zoom=1 data-map-type="ROADMAP"></div>
</li>
</ul>
<center><div style="font-size: 12px">Try this: curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "Country": "Spain" }' \http://<%=request.host%>:<%=request.port%>/widgets/dynamap</div></center>
</div>
<h1 class="title" data-bind="title"></h1>
<div id="map-canvas"></div>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require "rest-client"
COUNTRY_LOCATIONS_URL="https://s3-us-west-2.amazonaws.com/samnco-static-files/country-maps/countries.json"
COUNTRY_LOCATIONS = RestClient.get COUNTRY_LOCATIONS_URL
SCHEDULER.every '10s', :first_in => '0s' do |job|
index = rand(1000)
countries = JSON.parse(COUNTRY_LOCATIONS)
countries['countries'].each do |f|
if f['ccn3'].to_i == index
country_name = f['name']['common']
send_event('dynamap', { country: country_name } )
break
end
end
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #b4b4ff;
// ----------------------------------------------------------------------------
// Widget-dynamap styles
// ----------------------------------------------------------------------------
.widget-dynamap {
background-color: $background-color;
}
#map-canvas, #map_canvas {
height: 90%;
}
@media print {
html, body {
height: auto;
}
#map-canvas, #map_canvas {
height: 600px;
width:726px;
}
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
## This is for the Dynamic Map Widget
gem 'rest-client'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment