我们如何使用样式而不使用地图将 OpenLayers 3 功能渲染为 canvas?
How can we render an OpenLayers 3 feature to a canvas using a style but not using a map?
问题:
我们如何使用样式而不是使用地图将要素呈现为 canvas?
背景:
我有一个示例,它将几何图形渲染为 canvas 尊重 ol3 风格,但它只与未构建版本的 openlayers (ol-debug.js) 一起运行,因为它使用私有函数 (ol.vec.Mat4).
一种替代方法是创建一个地图,添加一个矢量图层,设置要素的样式,将要素添加到图层并从地图中删除所有 events/controls,使其看起来像 canvas.
第二种是使用goog.vec.Mat4。
let scale = Math.min(canvas.width / ol.extent.getWidth(extent), canvas.height / ol.extent.getHeight(extent));
console.log("scale", scale);
let transform = Mat4.makeTransform2D(identity,
canvas.width / 2, canvas.height / 2, // translate to origin
scale, -scale, //scale
0, // rotation
-center[0], -center[1] // translate back
);
console.log("transform", transform);
let renderer = new ol.render.canvas.Immediate(ctx, 1, extent, transform, 1);
renderer.drawFeature(feature, style);
第三个与第二个类似,我负责在使用 ol.render.toContext 之前将几何图形转换为像素坐标,如本 example 中所示。
我觉得差不多用完了吗?或者有别的办法吗?
呸!在 openlayers 网站上找到了 example!
其中样本坐标已经是像素:
<!DOCTYPE html>
<html>
<head>
<title>Render geometries to a canvas</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.17.1/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.17.1/build/ol.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var vectorContext = 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'});
var style = new ol.style.Style({
fill: fill,
stroke: stroke,
image: new ol.style.Circle({
radius: 10,
fill: fill,
stroke: stroke
})
});
vectorContext.setStyle(style);
vectorContext.drawGeometry(new ol.geom.LineString([[10, 10], [90, 90]]));
vectorContext.drawGeometry(new ol.geom.Polygon([[[2, 2], [98, 2], [2, 98], [2, 2]]]));
vectorContext.drawGeometry(new ol.geom.Point([88, 88]));
</script>
</body>
</html>
但如问题所示,平移 -> 缩放 -> 平移转换数据:
function render(canvas: HTMLCanvasElement, line: ol.Coordinate[], style: ol.style.Style) {
let extent = ol.extent.boundingExtent(line);
let [dx, dy] = ol.extent.getCenter(extent);
let [sx, sy] = [canvas.width / ol.extent.getWidth(extent), canvas.height / ol.extent.getHeight(extent)];
line= translate(line, [-dx, -dy]);
line= scale(line, [Math.min(sx, sy), -Math.min(sx, sy)]);
line= translate(line, [canvas.width / 2, canvas.height / 2]);
let feature = new ol.Feature({
geometry: new ol.geom.Polygon([line]),
style: style
});
let vtx = ol.render.toContext(canvas.getContext("2d"));
vtx.drawFeature(feature, style);
}
这是我的 TRS 逻辑:
function translate(points: number[][], vector: number[]) {
return points.map(p => vector.map((v, i) => v + p[i]));
}
function rotate(points: number[][], a: number) {
return points.map(p => {
let [x, y, cos, sin] = [p[0], p[1], Math.cos(a), Math.sin(a)];
return [
x * cos - y * sin,
x * sin + y * cos
];
});
}
function scale(points: number[][], vector: number[]) {
return points.map(p => vector.map((v, i) => v * p[i]));
}
问题:
我们如何使用样式而不是使用地图将要素呈现为 canvas?
背景:
我有一个示例,它将几何图形渲染为 canvas 尊重 ol3 风格,但它只与未构建版本的 openlayers (ol-debug.js) 一起运行,因为它使用私有函数 (ol.vec.Mat4).
一种替代方法是创建一个地图,添加一个矢量图层,设置要素的样式,将要素添加到图层并从地图中删除所有 events/controls,使其看起来像 canvas.
第二种是使用goog.vec.Mat4。
let scale = Math.min(canvas.width / ol.extent.getWidth(extent), canvas.height / ol.extent.getHeight(extent));
console.log("scale", scale);
let transform = Mat4.makeTransform2D(identity,
canvas.width / 2, canvas.height / 2, // translate to origin
scale, -scale, //scale
0, // rotation
-center[0], -center[1] // translate back
);
console.log("transform", transform);
let renderer = new ol.render.canvas.Immediate(ctx, 1, extent, transform, 1);
renderer.drawFeature(feature, style);
第三个与第二个类似,我负责在使用 ol.render.toContext 之前将几何图形转换为像素坐标,如本 example 中所示。
我觉得差不多用完了吗?或者有别的办法吗?
呸!在 openlayers 网站上找到了 example!
其中样本坐标已经是像素:
<!DOCTYPE html>
<html>
<head>
<title>Render geometries to a canvas</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.17.1/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.17.1/build/ol.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var vectorContext = 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'});
var style = new ol.style.Style({
fill: fill,
stroke: stroke,
image: new ol.style.Circle({
radius: 10,
fill: fill,
stroke: stroke
})
});
vectorContext.setStyle(style);
vectorContext.drawGeometry(new ol.geom.LineString([[10, 10], [90, 90]]));
vectorContext.drawGeometry(new ol.geom.Polygon([[[2, 2], [98, 2], [2, 98], [2, 2]]]));
vectorContext.drawGeometry(new ol.geom.Point([88, 88]));
</script>
</body>
</html>
但如问题所示,平移 -> 缩放 -> 平移转换数据:
function render(canvas: HTMLCanvasElement, line: ol.Coordinate[], style: ol.style.Style) {
let extent = ol.extent.boundingExtent(line);
let [dx, dy] = ol.extent.getCenter(extent);
let [sx, sy] = [canvas.width / ol.extent.getWidth(extent), canvas.height / ol.extent.getHeight(extent)];
line= translate(line, [-dx, -dy]);
line= scale(line, [Math.min(sx, sy), -Math.min(sx, sy)]);
line= translate(line, [canvas.width / 2, canvas.height / 2]);
let feature = new ol.Feature({
geometry: new ol.geom.Polygon([line]),
style: style
});
let vtx = ol.render.toContext(canvas.getContext("2d"));
vtx.drawFeature(feature, style);
}
这是我的 TRS 逻辑:
function translate(points: number[][], vector: number[]) {
return points.map(p => vector.map((v, i) => v + p[i]));
}
function rotate(points: number[][], a: number) {
return points.map(p => {
let [x, y, cos, sin] = [p[0], p[1], Math.cos(a), Math.sin(a)];
return [
x * cos - y * sin,
x * sin + y * cos
];
});
}
function scale(points: number[][], vector: number[]) {
return points.map(p => vector.map((v, i) => v * p[i]));
}