Skip to content

Instantly share code, notes, and snippets.

@acanimal
Last active August 29, 2015 14:04
Show Gist options
  • Save acanimal/b2f60367badb0b17a4d9 to your computer and use it in GitHub Desktop.
Save acanimal/b2f60367badb0b17a4d9 to your computer and use it in GitHub Desktop.
OL3 Canvas test

The pies are created in a loop:

for(i=0; i<1500; i++) {
  coordinates.push([-180+360*Math.random(), -90+180*Math.random()]);
  p = 100*Math.random();
  data.push([p, 100-p]);
  colors.push(['#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6), '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6)]);
}

and rendered in the canvasFunction like:

var canvasFunction = function(extent, resolution, pixelRatio, size, projection) {
  
  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');
  var canvasWidth = size[0], canvasHeight = size[1];
  canvas.setAttribute('width', canvasWidth);
  canvas.setAttribute('height', canvasHeight);
  
  // Canvas extent is different than map extent, so compute delta between 
  // left-top of map and canvas extent.
  var mapExtent = map.getView().calculateExtent(map.getSize())
  var canvasOrigin = map.getPixelFromCoordinate([extent[0], extent[3]]);
  var mapOrigin = map.getPixelFromCoordinate([mapExtent[0], mapExtent[3]]);
  var delta = [mapOrigin[0]-canvasOrigin[0], mapOrigin[1]-canvasOrigin[1]]

  var radius = 20;

  // track the accumulated arcs drawn so far
  var totalArc = -90*Math.PI / 180;
  var percentToRadians = 1 / 100*360 *Math.PI / 180;
  var wedgeRadians;

  // draw a wedge
  function drawWedge(coordinate, percent, color) {

    var point = ol.proj.transform(coordinate, 'EPSG:4326', 'EPSG:3857');
    var pixel = map.getPixelFromCoordinate(point);
    var cX = pixel[0] + delta[0], cY = pixel[1] + delta[1];

    // calc size of our wedge in radians
    wedgeRadians = percent * percentToRadians;

    // draw the wedge
    context.save();
    context.beginPath();
    context.moveTo(cX, cY);
    context.arc(cX, cY, radius, totalArc, totalArc + wedgeRadians, false);
    context.closePath();
    context.fillStyle = color;
    context.fill();
    context.lineWidth = 2;
    context.strokeStyle = '#999999';
    context.stroke();
    context.restore();

    // sum the size of all wedges so we will begin our next wedge at this sum
    totalArc += wedgeRadians;
  }

  var drawPie = function(coordinate, data, colors) {
    for(var i=0;i<data.length;i++){
      drawWedge(coordinate, data[i],colors[i]);
    }
  }

  for(var i=0; i<coordinates.length;i++){
    drawPie(coordinates[i], data[i], colors[i]);
  }

  return canvas;
};

and result has very good performance.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="http://ol3js.org/en/master/css/ol.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<title>ImageCanvas example</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="md-12">
<div id="map" class="map"></div>
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="http://ol3js.org/en/master/build/ol-debug.js"></script>
<script>
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: ol.proj.transform([0, 30], 'EPSG:4326', 'EPSG:3857'),
zoom: 3
})
});
// Creat random coordinates
var coordinates=[], data=[], colors=[];
var i, p;
for(i=0; i<1500; i++) {
coordinates.push([-180+360*Math.random(), -90+180*Math.random()]);
p = 100*Math.random();
data.push([p, 100-p]);
colors.push(['#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6), '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6)]);
}
var canvasFunction = function(extent, resolution, pixelRatio, size, projection) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var canvasWidth = size[0], canvasHeight = size[1];
canvas.setAttribute('width', canvasWidth);
canvas.setAttribute('height', canvasHeight);
// Canvas extent is different than map extent, so compute delta between
// left-top of map and canvas extent.
var mapExtent = map.getView().calculateExtent(map.getSize())
var canvasOrigin = map.getPixelFromCoordinate([extent[0], extent[3]]);
var mapOrigin = map.getPixelFromCoordinate([mapExtent[0], mapExtent[3]]);
var delta = [mapOrigin[0]-canvasOrigin[0], mapOrigin[1]-canvasOrigin[1]]
var radius = 20;
// track the accumulated arcs drawn so far
var totalArc = -90*Math.PI / 180;
var percentToRadians = 1 / 100*360 *Math.PI / 180;
var wedgeRadians;
// draw a wedge
function drawWedge(coordinate, percent, color) {
var point = ol.proj.transform(coordinate, 'EPSG:4326', 'EPSG:3857');
var pixel = map.getPixelFromCoordinate(point);
var cX = pixel[0] + delta[0], cY = pixel[1] + delta[1];
// calc size of our wedge in radians
wedgeRadians = percent * percentToRadians;
// draw the wedge
context.save();
context.beginPath();
context.moveTo(cX, cY);
context.arc(cX, cY, radius, totalArc, totalArc + wedgeRadians, false);
context.closePath();
context.fillStyle = color;
context.fill();
context.lineWidth = 2;
context.strokeStyle = '#999999';
context.stroke();
context.restore();
// sum the size of all wedges so we will begin our next wedge at this sum
totalArc += wedgeRadians;
}
var drawPie = function(coordinate, data, colors) {
for(var i=0;i<data.length;i++){
drawWedge(coordinate, data[i],colors[i]);
}
}
for(var i=0; i<coordinates.length;i++){
drawPie(coordinates[i], data[i], colors[i]);
}
return canvas;
};
var canvasLayer = new ol.layer.Image({
source: new ol.source.ImageCanvas({
canvasFunction: canvasFunction,
projection: 'EPSG:3857'
})
});
map.addLayer(canvasLayer);
</script>
</body>
</html>
@xlhomme
Copy link

xlhomme commented Oct 30, 2014

Hi
This script doesn't work if you rotate the map !
xav

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment