像Google Maps for OpenLayers一样使用毕业测量工具

时间:2017-11-30 09:38:19

标签: javascript maps openlayers openlayers-3

我需要用OpenLayers实现一个测量工具,我想在段上显示距离,智能管理规模(每10米一段标记,然后每50米,100米,1公里,5公里,例如...),非常像GoogleMaps"测量距离"工具。

有没有图书馆这样做?实施它的好方法是什么?

enter image description here

1 个答案:

答案 0 :(得分:0)

简而言之:不,我不知道任何提供您想要的开箱即用的库或类。

选项1:自定义ScaleLine

ScaleLine(参见api docs)可以选择提供自己的渲染功能(参见code)。默认实现只计算距离并通过调用内部函数 @Override public void onTabTransaction(Fragment currentFragment, int i) { appBarLayout.setFitsSystemWindows(currentFragment instanceof SecondFragment); } 将其显示为{number} {scale},然后更新ScaleLine的innerHtml。

理论上你可以替换该方法并自己设置innerHTML。这种方法可能会限制您使用库的开发变体,因为生产代码已缩小,并且这些元素(updateElement_innerElement_)未标记为api。

element_

选项2:使用具有自定义LineString样式的绘图功能

因此可能过于复杂,我建议您使用new ol.control.ScaleLine({ render: function(mapEvent) { // do stuff } }); 功能。 Measure Example向我们展示了在用户绘制线条时如何绘制内容。您可以将它与自定义样式组合在一个LineString上。

ol.interaction.Draw
// TODO split the uses drawn line into segments, like this mockup
const line = new ol.geom.LineString([
    [20.0, 50.0],
    [30.0, 47.0],
    [40.0, 47.0],
    [50.0, 47.0]
]);

line.transform('EPSG:4326', 'EPSG:3857');

const lineFeature = new ol.Feature(line);
const lineSource = new ol.source.Vector({
    features: [lineFeature]
});


function segmentText(coord, coord2) {
    const coord_t = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
    let coordText = coord_t[1].toFixed(0) + '/' + coord_t[0].toFixed(0);
    
    if(coord2) {
      const length = ol.Sphere.getLength(new ol.geom.LineString([coord2, coord]));
      const distance = (Math.round(length / 1000 * 100) / 100) + ' km';
      coordText = coordText + '\n' + distance;
    } else {
      coordText = coordText + '\n0';
    }
    
    return new ol.style.Text({
        text: coordText,
        fill: new ol.style.Fill({
            color: "#00f"
        }),
        offsetY: 25,
        align: 'center',
        scale: 1,
    });
}

function styleFunction(feature) {
    var geometry = feature.getGeometry();
    var styles = [
        // linestring style
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#ff0000',
                width: 2
            })
        })
    ];

    function createSegmentStyle(coord, coord2, rotation) {
        return new ol.style.Style({
            geometry: new ol.geom.Point(coord),
            image: new ol.style.Icon({
                src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAIAAADdv/LVAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAUSURBVBhXY1Da6MPEwMDAxMDAAAALMAEkQYjH8gAAAABJRU5ErkJggg==',
                anchor: [0.75, 0.5],
                rotateWithView: true,
                rotation: -rotation,
                scale: 4
            }),
            text: segmentText(coord, coord2)
        })
    };
    
    const firstCoord = geometry.getFirstCoordinate();
    geometry.forEachSegment(function (start, end) {
        var dx = end[0] - start[0];
        var dy = end[1] - start[1];
        var rotation = Math.atan2(dy, dx);
        if (firstCoord[0] === start[0] && firstCoord[1] === start[1]) {
            styles.push(createSegmentStyle(start, null, rotation));
        }

        styles.push(createSegmentStyle(end, firstCoord, rotation));
    });

    return styles;
}


const map = new ol.Map({
    target: 'map',
    layers: [
        new ol.layer.Tile({
            source: new ol.source.Stamen({ layer:'toner-lite' })
        }),
        new ol.layer.Vector({
            source: lineSource,
            style: styleFunction
        })
    ],
    view: new ol.View({
        center: ol.proj.transform(
            [35, 45], 'EPSG:4326', 'EPSG:3857'),
        zoom: 4
    })
});