我们如何使用样式而不使用地图将OpenLayers 3功能渲染到画布? [英] How can we render an OpenLayers 3 feature to a canvas using a style but not using a map?

查看:119
本文介绍了我们如何使用样式而不使用地图将OpenLayers 3功能渲染到画布?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

我们如何使用样式而不是使用地图将特征渲染到画布上?

How can we render a feature to a canvas using a style but not using a map?

背景:

我有一个示例,该示例将几何图形渲染到画布上以纪念ol3样式,但仅在未构建版本的openlayers(ol-debug.js)上运行,并且因为它利用了私有函数(ol.vec.Mat4)

I have a sample which renders a geometry to a canvas honoring the ol3 style but it only runs with the unbuilt version of openlayers (ol-debug.js) and because it makes use of private functions (ol.vec.Mat4).

在以下情况下有效使用ol-debug.js

在以下情况下失败使用ol.js

一种选择是创建地图,添加矢量层,在要素上设置样式,将要素添加到层并从地图上删除所有事件/控件,使其看起来像画布.

One alternative is to create a map, add a vector layer, set the style on the feature, add the feature to the layer and remove all the events/controls from the map so it looks like a 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之前将几何转换为像素坐标,如本

A third is similar to the second in that I take on the responsibility of transforming the geometry into pixel coordinates before using ol.render.toContext, as demonstrated in this example.

我认为这很累吗?还是有另一种方法?

I think that about exhausts it? Or is there another way?

推荐答案

Do!在openlayers网站上找到一个示例

Doh! Found an example right on the openlayers site!

在该示例坐标中已经有像素:

In that sample coordinates are already pixels:

<!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>

但是正如问题所示,翻译->缩放->翻译会转换数据:

But as the question indicates, translation -> scale -> translation transforms the data:

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]));
}

这篇关于我们如何使用样式而不使用地图将OpenLayers 3功能渲染到画布?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆