JSFiddle - React, Tailwind, and code Playground

by Umar

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="container">
    <div class="people"></div>
    <canvas class="map" width="1024" height="160">
</div>

CSS

.container {
    position: relative;
    width: 1024px;
    height: 160px;
    overflow: hidden;
}

.people {
    position: absolute;
    top: 0; left: 0;
    width: 1024px;
    height: 160px;
}

.person {
    position: absolute;
    background: rgba(0, 0, 255, .7);
    width: 20px;
    height: 20px;
    margin-top: -10px;
    margin-left: -10px;
    
    border-radius: 50%;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
}

JavaScript

$(function(){
   var latlon = "40.7300694,-74.0024224"; // Sample Lat,Long (Manhattan NYC)
	var distance_between_people = 40; // Keep 40 pixels between people on map
	var max_map_people = 40; // Attempt to put 30 people on map

	var $people_layer = $('.people');

	// Create an in-memory canvas and store its 2d context
	var water_context = document.createElement('canvas');
	water_context.setAttribute('width', 1024);
	water_context.setAttribute('height', 160);
	water_context = water_context.getContext('2d');

	// Assumes <canvas> element already in DOM with class "map"
	var map_context = $('canvas.map')[0].getContext('2d');

	var map = new Image();
	map.crossOrigin = 'http://maps.googleapis.com/crossdomain.xml';
	map.src = "http://maps.googleapis.com/maps/api/staticmap?scale=2&center=" + latlon + "&zoom=13&size=1024x160&sensor=false&visual_refresh=true";

	map.onload = function(){
		// Put the map image inside the canvas once it loads
		map_context.drawImage(map, 0, 0, 1024, 256);

		water = new Image();
		water.crossOrigin = 'http://maps.googleapis.com/crossdomain.xml';
		water.src = "http://maps.googleapis.com/maps/api/staticmap?scale=2&center=" + latlon + "&zoom=13&size=1024x160&sensor=false&visual_refresh=true&style=element:labels|visibility:off&style=feature:water|color:0x00FF00&style=feature:transit|visibility:off&style=feature:poi|visibility:off&style=feature:road|visibility:off&style=feature:administrative|visibility:off";

		water.onload = function(){
			// Put the water image inside the water canvas
			water_context.drawImage(water, 0, 0, 1024, 256);
			render_random_people();
		}
	}

	function render_random_people(){
		$people_layer.empty();

		var tries = 0,
		drawn = [];

		// Give up after 2 * map_num_people tries in case it’s not possible to place map_num_people icons on the map
		while(tries < max_map_people * 2 && drawn.length < max_map_people){
			tries++;

			// 5px padding around edges (1024 x 160 pixel Map)
			x = _.random(5, 1019);
			y =...