1. 程式人生 > >OpenLayers官方示例詳解十六之偽造點(Synthetic Points)

OpenLayers官方示例詳解十六之偽造點(Synthetic Points)

目錄

一、示例簡介

二、程式碼詳解


一、示例簡介

    本示例首先隨機生成20000個點資料,並加入到地圖中,然後實現了將離滑鼠最近的點高亮顯示的功能。

二、程式碼詳解

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Synthetic Points</title>
    <link href="ol_v5.0.0/css/ol.css" rel="stylesheet" type="text/css" />
    <script src="ol_v5.0.0/build/ol.js" type="text/javascript"></script>
</head>
<body>
    <div id="map"></div>
    
    <script>
        var count = 20000;
        var features = new Array(count);
        var e = 18000000;
        // 隨機生成20000個點要素
        for(var i = 0; i < count; i++){
            features[i] = new ol.Feature({
                'geometry': new ol.geom.Point(
                    [2 * e * Math.random() - e, 2 * e * Math.random() - e]
                ),
                'i': i,     // 標記主碼
                'size': i % 2 ? 10 : 20    // 用於對應樣式的標記
            });
        }

        // 點樣式的名稱空間
        var styles = {
            '10': new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({
                        color: '#666'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#bada55',
                        width: 1
                    })
                })
            }),
            '20': new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 10,
                    fill: new ol.style.Fill({
                        color: '#666'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#bada55',
                        width: 1
                    })
                })
            })
        };

        var vectorSource = new ol.source.Vector({
            features: features,
            wrapX: false
        });

        var vector = new ol.layer.Vector({
            source: vectorSource,
            style: function(feature){                   // 對不同大小的要素賦予不同的樣式
                return styles[feature.get('size')]; 
            }
        });

        var map = new ol.Map({
            target: 'map',
            layers: [
                vector
            ],
            view: new ol.View({
                center: [0, 0],
                zoom: 2
            })
        });

        var point = null;
        var line = null;
        // 尋找離滑鼠游標最近的點要素,並使用一條線要素連線兩者
        var displaySnap = function(coordinate){
            var closestFeature = vectorSource.getClosestFeatureToCoordinate(coordinate);    // 獲取與傳入的座標點最接近的要素
            if(closestFeature === null){
                point = null;
                line = null;
            }else{
                var geometry = closestFeature.getGeometry();
                var closestPoint = geometry.getClosestPoint(coordinate);    // 獲取與傳入座標最接近的點座標
                if(point === null){
                    point = new ol.geom.Point(closestPoint);    // 初始化點幾何圖形
                }else{
                    point.setCoordinates(closestPoint);         // 重新設定點圖形的座標
                }
                if(line === null){
                    line = new ol.geom.LineString([coordinate, closestPoint]);  // 初始化線幾何圖形
                }else{  
                    line.setCoordinates([coordinate, closestPoint]);            // 重新設定線圖形的座標
                }
            }
            map.render();
        }

        map.on('pointermove', function(evt){
            if(evt.dragging){       // 如果滑鼠拖拽地圖,則不進行其餘操作
                return;
            }
            var coordinate = map.getEventCoordinate(evt.originalEvent); // 返回當前滑鼠的座標
            displaySnap(coordinate);        // 顯示捕捉

            var pixel = map.getEventPixel(evt.originalEvent);
            var hit = map.hasFeatureAtPixel(pixel);         // 判斷是否有要素點與滑鼠相交
            // 如果滑鼠游標與要素點相交,則改變滑鼠游標的樣式
            if(hit){
                map.getTargetElement().style.cursor = 'pointer';   
            }else{
                map.getTargetElement().style.cursor = '';
            }
        });

        map.on('click', function(evt){
            displaySnap(evt.coordinate);
        });

        var stroke = new ol.style.Stroke({
            color: 'rgba(255, 255, 0, 0.9)',
            width: 3
        });
        var style = new ol.style.Style({
            stroke: stroke,
            image: new ol.style.Circle({
                radius: 10,
                stroke: stroke
            })
        });

        map.on('postcompose', function(evt){
            var vectorContext = evt.vectorContext;  // 獲取canvas 2d繪圖上下文
            vectorContext.setStyle(style);          // 為繪圖上下文設定樣式
            if(point !== null){
                vectorContext.drawGeometry(point);  // 使用canvas繪製離滑鼠最近的點
            }
            if(line !== null){
                vectorContext.drawGeometry(line);   // 使用canvas繪製滑鼠與離滑鼠最近點之間的線
            }
        });
    </script>
</body>
</html>