Mapboxgl 实现弧线功能

更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加VX:digital_twin123

image.png
代码如下:

const mapCenter = [-0.5, 51.8];

// please use your own token!
const map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/light-v11',
    center: [-10, 25],
    zoom: 2,
    maxZoom: 5
});

map.on('load', () => {
    map.setLight({
        intensity: 0
    });
    const points = turf.randomPoint(50, {
        bbox: [-100, 0, 100, 80]
    });
    const mergedArray = [];
    turf.featureEach(points, function (currentFeature, featureIndex) {
        const arcLine = generateLine([mapCenter, currentFeature.geometry.coordinates]);
        mergedArray.push(arcLine);
    });
    const flat = mergedArray.flat();
    const arcCollection = turf.featureCollection([]);
    arcCollection.features = flat;
    addLine(arcCollection);
});

function generateLine(coords) {
    const options = {
        units: 'miles'
    };
    const buffer = 10; // line width
    const line = turf.lineString(coords); // generate line with coords
    const length = turf.length(line, options); // line length
    const arcQuality = 4; // lower = more points to generate along arc and higher arcs
    const points = length / arcQuality; // number of points based on length and quality value
    const segment = length / points; // segment length based on number of points

    const pointArray = []; // empty array to hold each point
    const curve = 4; // value that determines when curve ends
    let heightVal = 1; // init height
    const maxHeight = points * points; // higher arcs based on distance/number of points

    for (let i = 0; i < points; i++) {
        const along = turf.along(line, segment * i, options);
        const maxSegment = maxHeight / points;
        const alongCoords = along.geometry.coordinates;
        const newVal = (points / 2) - i;
        if (i < (points / 2)) {
            const sq = (newVal * newVal) / (points / curve);
            heightVal = maxHeight - (maxSegment * sq);
        } else {
            const val = (points / 2) + (newVal - (points / 2));
            const sq = (val * val) / (points / curve);
            heightVal = maxHeight - (maxSegment * sq);
        }
        const circOptions = {
            steps: 10,
            units: 'miles',
            properties: {
                'heightVal': heightVal
            }
        };
        const circle = turf.circle([alongCoords[0], alongCoords[1]], buffer, circOptions);
        pointArray.push(circle);
    }
    return pointArray;
}

function addLine(arcs) {
    map.addSource('arcs', {
        'type': 'geojson',
        'data': arcs
    });

    map.addLayer({
        'id': 'arcLayer',
        'type': 'fill-extrusion',
        'source': 'arcs',
        'paint': {
            'fill-extrusion-color': [
                'interpolate',
                ['linear'],
                ['get', 'heightVal'],
                0,
                '#f768a1',
                200000,
                '#c51b8a',
                400000,
                '#7a0177'
            ],
            'fill-extrusion-opacity': 1,
            // 'fill-extrusion-base': 0,
            'fill-extrusion-base': [
                'case',
                ['<', ['get', 'heightVal'], 8000],
                8000,
                ['-', ['*', ['get', 'heightVal'], 1.5], 8000]
            ],
            'fill-extrusion-height': ['*', ['get', 'heightVal'], 1.5]
        }
    }, 'road-label-simple');
}
### 使用 Turf.js 绘制地理空间弧线 为了实现绘制地理空间中的弧线功能,可以利用 `turf.js` 结合其他库如 OpenLayers 或者 Mapbox GL JS 来完成。下面是一个基于 OpenLayers 和 Turf.js 的简单示例[^1]。 #### 创建平滑曲线交互 首先,在 HTML 文件中确保已经引入了必要的资源: ```html <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css"> <script src="https://cdn.jsdelivr.net/npm/turf/turf.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script> ``` 接着定义 JavaScript 代码来初始化地图并添加绘图工具: ```javascript // 初始化OpenLayers地图对象 const map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([0, 0]), zoom: 2 }) }); // 添加绘制交互 const drawInteraction = new ol.interaction.Draw({ type: 'LineString' }); drawInteraction.on('drawend', function (event) { const coordinates = event.feature.getGeometry().getCoordinates(); // 调用Turf函数生成中间点形成圆弧效果 let arcPoints = []; for(let i=0;i<coordinates.length-1;i++){ var line = turf.lineString(coordinates[i], coordinates[i+1]); var midpoint = turf.midpoint(line); arcPoints.push(midpoint.geometry.coordinates); } // 将原始坐标与新计算出的中间点组合成新的折线几何体 const smoothGeom = new ol.geom.LineString([...arcPoints,...coordinates]); // 替换原来的Feature为带有平滑路径的新Feature event.feature.setGeometry(smoothGeom); console.log(event.feature.getGeometry()); }); map.addInteraction(drawInteraction); ``` 此段脚本展示了如何监听用户的绘制结束事件,并通过调用 `turf.midpoint()` 方法找到每两个顶点之间的中心位置作为额外控制点加入到最终形成的多边形当中去,从而达到近似于弧度的效果。 需要注意的是上述方法只是模拟了一个简单的弯曲形态,并不是严格意义上的圆形或椭圆弧;如果需要更精确地表示特定半径下的真实弧,则可能需要用到更加复杂的算法或者第三方插件支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞GIS图形的sky.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值