diff --git a/examples/render-geometry.html b/examples/render-geometry.html new file mode 100644 index 0000000000..0c0af68691 --- /dev/null +++ b/examples/render-geometry.html @@ -0,0 +1,9 @@ +--- +layout: example.html +title: Render geometries to a canvas +shortdesc: Example of rendering geometries to an arbitrary canvas. +docs: > + This example shows how to render geometries to an arbitrary canvas. +tags: "render, geometry, canvas" +--- + diff --git a/examples/render-geometry.js b/examples/render-geometry.js new file mode 100644 index 0000000000..7682fbf47e --- /dev/null +++ b/examples/render-geometry.js @@ -0,0 +1,25 @@ +goog.require('ol.geom.LineString'); +goog.require('ol.geom.Point'); +goog.require('ol.geom.Polygon'); +goog.require('ol.render'); +goog.require('ol.style.Circle'); +goog.require('ol.style.Fill'); +goog.require('ol.style.Stroke'); + + +var canvas = document.getElementById('canvas'); +var render = ol.render.toContext(canvas.getContext('2d'), {size: [100, 100]}); + +var fill = new ol.style.Fill({ color: 'blue' }); +var stroke = new ol.style.Stroke({ color: 'black' }); +render.setFillStrokeStyle(fill, stroke); +render.setImageStyle(new ol.style.Circle({ + radius: 10, + fill: fill, + stroke: stroke +})); + +render.drawLineStringGeometry(new ol.geom.LineString([[10, 10], [90, 90]])); +render.drawPolygonGeometry( + new ol.geom.Polygon([[[2, 2], [98, 2], [2, 98], [2, 2]]])); +render.drawPointGeometry(new ol.geom.Point([88, 88])); diff --git a/externs/olx.js b/externs/olx.js index 5ae51dc0f7..7b0ae01895 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -3796,6 +3796,40 @@ olx.layer.VectorTileOptions.prototype.updateWhileInteracting; olx.layer.VectorTileOptions.prototype.visible; +/** + * Namespace. + * @type {Object} + */ +olx.render; + + +/** + * @typedef {{size: (ol.Size|undefined), + * pixelRatio: (number|undefined)}} + * @api + */ +olx.render.ToContextOptions; + + +/** + * Desired size of the canvas in css pixels. When provided, both canvas and css + * size will be set according to the `pixelRatio`. If not provided, the current + * canvas and css sizes will not be altered. + * @type {ol.Size|undefined} + * @api + */ +olx.render.ToContextOptions.prototype.size; + + +/** + * Pixel ratio (canvas pixel to css pixel ratio) for the canvas. Default + * is the detected device pixel ratio. + * @type {ol.Size|undefined} + * @api + */ +olx.render.ToContextOptions.prototype.pixelRatio; + + /** * Namespace. * @type {Object} diff --git a/src/ol/render.js b/src/ol/render.js new file mode 100644 index 0000000000..3686dc178f --- /dev/null +++ b/src/ol/render.js @@ -0,0 +1,43 @@ +goog.provide('ol.render'); + +goog.require('goog.vec.Mat4'); +goog.require('ol.render.canvas.Immediate'); +goog.require('ol.vec.Mat4'); + + +/** + * Binds a Canvas Immediate API to a canvas context, to allow drawing geometries + * to the context's canvas. + * ```js + * var canvas = document.createElement('canvas'); + * var render = ol.render.toContext(canvas.getContext('2d'), + * { size: [100, 100] }); + * render.setFillStrokeStyle(new ol.style.Fill({ color: blue })); + * render.drawPolygonGeometry( + * new ol.geom.Polygon([[[0, 0], [100, 100], [100, 0], [0, 0]]])); + * ``` + * Note that {@link ol.render.canvas.Immediate#drawAsync} and + * {@link ol.render.canvas.Immediate#drawFeature} cannot be used. + * + * @param {CanvasRenderingContext2D} context Canvas context. + * @param {olx.render.ToContextOptions=} opt_options Options. + * @return {ol.render.canvas.Immediate} Canvas Immediate. + * @api + */ +ol.render.toContext = function(context, opt_options) { + var canvas = context.canvas; + var options = opt_options ? opt_options : {}; + var pixelRatio = options.pixelRatio || ol.has.DEVICE_PIXEL_RATIO; + var size = options.size; + if (size) { + canvas.width = size[0] * pixelRatio; + canvas.height = size[1] * pixelRatio; + canvas.style.width = size[0] + 'px'; + canvas.style.height = size[1] + 'px'; + } + var extent = [0, 0, canvas.width, canvas.height]; + var transform = ol.vec.Mat4.makeTransform2D(goog.vec.Mat4.createNumber(), + 0, 0, pixelRatio, pixelRatio, 0, 0, 0); + return new ol.render.canvas.Immediate(context, pixelRatio, extent, transform, + 0); +}; diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index 2821b2c8fe..9d0a156e55 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -429,11 +429,10 @@ ol.render.canvas.Immediate.prototype.drawAsync = function(zIndex, callback) { * the current fill and stroke styles. * * @param {ol.geom.Circle} circleGeometry Circle geometry. - * @param {ol.Feature} feature Feature, * @api */ ol.render.canvas.Immediate.prototype.drawCircleGeometry = - function(circleGeometry, feature) { + function(circleGeometry) { if (!ol.extent.intersects(this.extent_, circleGeometry.getExtent())) { return; } @@ -528,11 +527,10 @@ ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry = * the current style. * * @param {ol.geom.Point|ol.render.Feature} pointGeometry Point geometry. - * @param {ol.Feature|ol.render.Feature} feature Feature. * @api */ ol.render.canvas.Immediate.prototype.drawPointGeometry = - function(pointGeometry, feature) { + function(pointGeometry) { var flatCoordinates = pointGeometry.getFlatCoordinates(); var stride = pointGeometry.getStride(); if (this.image_) { @@ -550,11 +548,10 @@ ol.render.canvas.Immediate.prototype.drawPointGeometry = * * @param {ol.geom.MultiPoint|ol.render.Feature} multiPointGeometry MultiPoint * geometry. - * @param {ol.Feature|ol.render.Feature} feature Feature. * @api */ ol.render.canvas.Immediate.prototype.drawMultiPointGeometry = - function(multiPointGeometry, feature) { + function(multiPointGeometry) { var flatCoordinates = multiPointGeometry.getFlatCoordinates(); var stride = multiPointGeometry.getStride(); if (this.image_) { @@ -572,11 +569,10 @@ ol.render.canvas.Immediate.prototype.drawMultiPointGeometry = * * @param {ol.geom.LineString|ol.render.Feature} lineStringGeometry Line * string geometry. - * @param {ol.Feature|ol.render.Feature} feature Feature. * @api */ ol.render.canvas.Immediate.prototype.drawLineStringGeometry = - function(lineStringGeometry, feature) { + function(lineStringGeometry) { if (!ol.extent.intersects(this.extent_, lineStringGeometry.getExtent())) { return; } @@ -602,11 +598,10 @@ ol.render.canvas.Immediate.prototype.drawLineStringGeometry = * * @param {ol.geom.MultiLineString|ol.render.Feature} multiLineStringGeometry * MultiLineString geometry. - * @param {ol.Feature|ol.render.Feature} feature Feature. * @api */ ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry = - function(multiLineStringGeometry, feature) { + function(multiLineStringGeometry) { var geometryExtent = multiLineStringGeometry.getExtent(); if (!ol.extent.intersects(this.extent_, geometryExtent)) { return; @@ -639,11 +634,10 @@ ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry = * * @param {ol.geom.Polygon|ol.render.Feature} polygonGeometry Polygon * geometry. - * @param {ol.Feature|ol.render.Feature} feature Feature. * @api */ ol.render.canvas.Immediate.prototype.drawPolygonGeometry = - function(polygonGeometry, feature) { + function(polygonGeometry) { if (!ol.extent.intersects(this.extent_, polygonGeometry.getExtent())) { return; } @@ -676,11 +670,10 @@ ol.render.canvas.Immediate.prototype.drawPolygonGeometry = * Render MultiPolygon geometry into the canvas. Rendering is immediate and * uses the current style. * @param {ol.geom.MultiPolygon} multiPolygonGeometry MultiPolygon geometry. - * @param {ol.Feature} feature Feature. * @api */ ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry = - function(multiPolygonGeometry, feature) { + function(multiPolygonGeometry) { if (!ol.extent.intersects(this.extent_, multiPolygonGeometry.getExtent())) { return; } diff --git a/test/spec/ol/render.test.js b/test/spec/ol/render.test.js new file mode 100644 index 0000000000..662ad0fb4c --- /dev/null +++ b/test/spec/ol/render.test.js @@ -0,0 +1,37 @@ +goog.provide('ol.test.render'); + +describe('ol.render', function() { + + describe('toContext', function() { + + it('creates an ol.render.canvas.Immediate and sets defaults', function() { + var canvas = document.createElement('canvas'); + var render = ol.render.toContext(canvas.getContext('2d')); + expect(render).to.be.a(ol.render.canvas.Immediate); + expect(render.pixelRatio_).to.be(ol.has.DEVICE_PIXEL_RATIO); + }); + + it('sets size and pixel ratio from options', function() { + var canvas = document.createElement('canvas'); + var pixelRatio = 1.5; + var size = [100, 50]; + var render = ol.render.toContext(canvas.getContext('2d'), + {pixelRatio: pixelRatio, size: size}); + expect(render.pixelRatio_).to.be(pixelRatio); + expect(render.extent_).to.eql( + [0, 0, size[0] * pixelRatio, size[1] * pixelRatio]); + expect(canvas.style.width).to.be(size[0] + 'px'); + expect(canvas.style.height).to.be(size[1] + 'px'); + var transform = ol.vec.Mat4.makeTransform2D(goog.vec.Mat4.createNumber(), + 0, 0, pixelRatio, pixelRatio, 0, 0, 0); + expect(ol.vec.Mat4.equals2D(render.transform_, transform)).to.be.ok(); + }); + }); + +}); + + +goog.require('goog.vec.Mat4'); +goog.require('ol.render'); +goog.require('ol.render.canvas.Immediate'); +goog.require('ol.vec.Mat4');