googlemaps-v3-utility-library
Version:
Google Maps API V3 Utility Library
213 lines (174 loc) • 6.76 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>Hello CanvasLayer - WebGL</title>
<style>
html, body, #map-div {
margin: 0;
padding: 0;
height: 100%;
}
</style>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="../src/CanvasLayer.js"></script>
<script>
var map;
var canvasLayer;
var gl;
var pointProgram;
var pointArrayBuffer;
var POINT_COUNT = 2000;
var MIN_X = 40;
var MAX_X = 80;
var MIN_Y = 88;
var MAX_Y = 109;
var pixelsToWebGLMatrix = new Float32Array(16);
var mapMatrix = new Float32Array(16);
function init() {
// initialize the map
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(39.3, -95.8),
mapTypeId: google.maps.MapTypeId.ROADMAP,
styles: [
{
featureType: 'water',
stylers: [{ color: '#c3cfdd'}]
},
{
featureType: 'poi',
stylers: [{visibility: 'off'}]
}
]
};
var mapDiv = document.getElementById('map-div');
map = new google.maps.Map(mapDiv, mapOptions);
// initialize the canvasLayer
var canvasLayerOptions = {
map: map,
resizeHandler: resize,
animate: false,
updateHandler: update
};
canvasLayer = new CanvasLayer(canvasLayerOptions);
// initialize WebGL
gl = canvasLayer.canvas.getContext('experimental-webgl');
createShaderProgram();
loadData();
}
function createShaderProgram() {
// create vertex shader
var vertexSrc = document.getElementById('pointVertexShader').text;
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSrc);
gl.compileShader(vertexShader);
// create fragment shader
var fragmentSrc = document.getElementById('pointFragmentShader').text;
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSrc);
gl.compileShader(fragmentShader);
// link shaders to create our program
pointProgram = gl.createProgram();
gl.attachShader(pointProgram, vertexShader);
gl.attachShader(pointProgram, fragmentShader);
gl.linkProgram(pointProgram);
gl.useProgram(pointProgram);
}
// linear interpolate between a and b
function lerp(a, b, t) {
return a + t * (b - a);
}
function loadData() {
// this data could be loaded from anywhere, but in this case we'll
// generate some random x,y coords in a world coordinate bounding box
var rawData = new Float32Array(2 * POINT_COUNT);
for (var i = 0; i < rawData.length; i += 2) {
rawData[i] = lerp(MIN_X, MAX_X, Math.random());
rawData[i + 1] = lerp(MIN_Y, MAX_Y, Math.random());
}
// create webgl buffer, bind it, and load rawData into it
pointArrayBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointArrayBuffer);
gl.bufferData(gl.ARRAY_BUFFER, rawData, gl.STATIC_DRAW);
// enable the 'worldCoord' attribute in the shader to receive buffer
var attributeLoc = gl.getAttribLocation(pointProgram, 'worldCoord');
gl.enableVertexAttribArray(attributeLoc);
// tell webgl how buffer is laid out (pairs of x,y coords)
gl.vertexAttribPointer(attributeLoc, 2, gl.FLOAT, false, 0, 0);
}
function resize() {
var width = canvasLayer.canvas.width;
var height = canvasLayer.canvas.height;
gl.viewport(0, 0, width, height);
// matrix which maps pixel coordinates to WebGL coordinates
pixelsToWebGLMatrix.set([2/width, 0, 0, 0, 0, -2/height, 0, 0,
0, 0, 0, 0, -1, 1, 0, 1]);
}
function scaleMatrix(matrix, scaleX, scaleY) {
// scaling x and y, which is just scaling first two columns of matrix
matrix[0] *= scaleX;
matrix[1] *= scaleX;
matrix[2] *= scaleX;
matrix[3] *= scaleX;
matrix[4] *= scaleY;
matrix[5] *= scaleY;
matrix[6] *= scaleY;
matrix[7] *= scaleY;
}
function translateMatrix(matrix, tx, ty) {
// translation is in last column of matrix
matrix[12] += matrix[0]*tx + matrix[4]*ty;
matrix[13] += matrix[1]*tx + matrix[5]*ty;
matrix[14] += matrix[2]*tx + matrix[6]*ty;
matrix[15] += matrix[3]*tx + matrix[7]*ty;
}
function update() {
gl.clear(gl.COLOR_BUFFER_BIT);
var mapProjection = map.getProjection();
/**
* We need to create a transformation that takes world coordinate
* points in the pointArrayBuffer to the coodinates WebGL expects.
* 1. Start with second half in pixelsToWebGLMatrix, which takes pixel
* coordinates to WebGL coordinates.
* 2. Scale and translate to take world coordinates to pixel coords
* see https://developers.google.com/maps/documentation/javascript/maptypes#MapCoordinate
*/
// copy pixel->webgl matrix
mapMatrix.set(pixelsToWebGLMatrix);
// Scale to current zoom (worldCoords * 2^zoom)
var scale = Math.pow(2, map.zoom);
scaleMatrix(mapMatrix, scale, scale);
// translate to current view (vector from topLeft to 0,0)
var offset = mapProjection.fromLatLngToPoint(canvasLayer.getTopLeft());
translateMatrix(mapMatrix, -offset.x, -offset.y);
// attach matrix value to 'mapMatrix' uniform in shader
var matrixLoc = gl.getUniformLocation(pointProgram, 'mapMatrix');
gl.uniformMatrix4fv(matrixLoc, false, mapMatrix);
// draw!
gl.drawArrays(gl.POINTS, 0, POINT_COUNT);
}
document.addEventListener('DOMContentLoaded', init, false);
</script>
<script id="pointVertexShader" type="x-shader/x-vertex">
attribute vec4 worldCoord;
uniform mat4 mapMatrix;
void main() {
// transform world coordinate by matrix uniform variable
gl_Position = mapMatrix * worldCoord;
// a constant size for points, regardless of zoom level
gl_PointSize = 10.;
}
</script>
<script id="pointFragmentShader" type="x-shader/x-fragment">
precision mediump float;
void main() {
// set pixels in points to green
gl_FragColor = vec4(.1, .8, 0.08, 1.);
}
</script>
</head>
<body>
<div id="map-div"></div>
</body>
</html>