Openlayer绘制点与线

1,187 阅读2分钟

前置工作

var vecSource = new ol.source.Vector();
var vecLayer = new ol.layer.Vector({
    source: vecSource
});
vecSource.clear();
map.addLayer(vecLayer);

1.画点

map.getOverlays().clear(); //清空之前画的点
let lonlatArr = [110,45];
const latlon = TransformUtil.gcj_decrypt_exact(lonlatArr[1], lonlatArr[0]);
const marker = new ol.Feature(new ol.geom.Point([latlon.lon, latlon.lat]));
const markerStyle = new ol.style.Style({
    image: new ol.style.Icon({
        src: 'images/location.png',
    })
});
marker.setStyle(markerStyle);
const vectorSource = new ol.source.Vector({
    features: [marker]
});

const vectorLayer = new ol.layer.Vector({
    source: vectorSource
});
map.addOverlay(vectorLayer); // 将标注添加到地图中
map.getView().setCenter([latlon.lon, latlon.lat]);//设置选中井到地图中心

2.画线

const lineStyle = new ol.style.Style({
    stroke: new ol.style.Stroke({
        width: 3,
        color: [255, 0, 0, 1]
    })
});
const line_feature = new ol.Feature({
    geometry: new ol.geom.LineString(coordDrawLineArr)
});
line_feature.setStyle(lineStyle);
const line_source = new ol.source.Vector({
    features: [line_feature],
    projection: 'EPSG:4326'
});
const line_layer = new ol.layer.Vector({
    source: line_source
});
map.addLayer(line_layer);

3.绘制导航线完整代码(包含起点、终点、出行方式、方向箭头、线条描边)

drawTrace([[119.5,37.5],[120.5,38.5],[121.5,38.5],[122.5,37.5]]);

function drawTrace(coordDrawLineArr){
    if (line_layer) {
        map.removeLayer(line_layer); //清空之前画的线
    }
    map.getOverlays().clear(); //清空之前画的标志物
    const line_feature = new ol.Feature({
        geometry: new ol.geom.LineString(coordDrawLineArr)
    });
    const source = new ol.source.Vector({
        features: [line_feature],
        projection: 'EPSG:4326'
    });
    line_layer = new ol.layer.Vector({
        source,
        style: lineArrowStyles
    });
    map.addLayer(line_layer);
    setPointMark(coordDrawLineArr[0],'start');
    setPointMark(coordDrawLineArr.at(-1),'end');
    setPointMark(coordDrawLineArr.at(-1),'car');
}

/**
 * 内部箭头样式
 * 用于每次渲染集合体的时候,OL 均会调用此函数以获得自定义样式
 * @param feature
 * @param res
 * @returns {undefined[]}
 */
const lineArrowStyles = function (feature, res) {
    let geometry = feature.getGeometry();
    let styles = [
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: [30, 150, 250, 1],
                width: 15
            })
        }),
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: [250, 100, 100, 1],
                width: 10
            })
        })
    ];
    // 如果几何体不是线条,这返回默认样式
    if (!(geometry instanceof ol.geom.LineString)) return styles;
    // 得到线条长度
    const length = geometry.getLength();
    // 内部箭头间隔距离(像素)
    const step = 50;
    // 将间隔像素距离转换成地图的真实距离
    // res 是 OL 自动传入的地图比例系数
    const geoStep = step * res;
    // 得到一共需要绘制多少个 箭头
    const arrowNum = Math.floor(length / geoStep);
    const rotations = [];
    const distances = [0];
    // 分割线条,将折线根据坐标进行分割,并遍历
    // 回调函数将传入开始坐标和结束坐标
    // 利用开始距离和结束距离,得到每段线条的距离和方向信息
    geometry.forEachSegment(function (start, end) {
        let dx = end[0] - start[0];
        let dy = end[1] - start[1];
        let rotation = Math.atan2(dy, dx);
        distances.unshift(Math.sqrt(dx ** 2 + dy ** 2) + distances[0])
        rotations.push(rotation);
    });
    // 利用之前计算得到的线段矢量信息,生成对应的点样式塞入默认样式中
    // 从而绘制内部箭头
    for (let i = 1; i < arrowNum; ++i) {
        const arrowCoord = geometry.getCoordinateAt(i / arrowNum);
        const d = i * geoStep;
        const grid = distances.findIndex(x => x <= d);

        styles.push(
            new ol.style.Style({
                geometry: new ol.geom.Point(arrowCoord),
                image: new ol.style.Icon({
                    src: 'images/arrow-right.png',
                    opacity: 1,
                    anchor: [.5, .5],
                    rotateWithView: true,
                    // 读取 rotations 中计算存放的方向信息
                    rotation: -rotations[distances.length - grid - 1],
                    scale: .05
                }),
            })
        );
    }
    return styles;
}

function setPointMark(point,name){
    const marker = new ol.Feature(new ol.geom.Point(point));
    const iconStyle = new ol.style.Style({
            image: new ol.style.Icon({
                src: `images/${name}.png`
            })
        });
    }
    marker.setStyle(iconStyle);
    const vectorSource = new ol.source.Vector({
        features: [marker]
    });
    const vectorLayer = new ol.layer.Vector({
        source: vectorSource
    });
    map.addOverlay(vectorLayer); 
}

效果图:

image.png