龙空技术网

Openlayers 聚合图、权重聚合图以及聚合图点击事件

Southejor 155

前言:

此刻朋友们对“气泡框html”都比较重视,你们都需要分析一些“气泡框html”的相关文章。那么小编同时在网络上网罗了一些关于“气泡框html””的相关知识,希望咱们能喜欢,各位老铁们快快来了解一下吧!

OpenLayers 教程

在实际工作中,Openlayers 渲染数据的方式有很多种(WMS、瓦片、矢量数据等),一次性渲染较大数据量的情况下,需要做成静态切片,比如WMTS、TMS;或者矢量切片,比如 Geojson、mvt 等。

对于数据量不是很大的数据,常常使用 热力图、聚合图 的方式在前端渲染,能够更好的体现数据特征。

本示例基于实际项目中的应用,介绍: 加载聚合图、权重聚合图、聚合图参数、聚合图点击事件 等功能的用法。

PS:如果数据量很大的话,建议数据入库,使用数据库的聚合函数来实现。

Openlayers 聚合图、权重聚合图、聚合图事件

<html lang="en"><head>    <meta charSet="utf-8">    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->    <link rel="stylesheet" href="; type="text/css">    <style>        /* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */        .map {            height: 700px;            width: 100%;            float: left;        }    </style>    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->    <script src=";></script>    <script src=";></script>    <script src="./tiandituLayers.js"></script>    <title>OpenLayers example</title></head><body><h2>OpenLayers Cluster</h2><!--地图容器,需要指定 id --><div id="map" class="map"></div><script type="text/javascript">    var map = new ol.Map({        // 地图容器        target: 'map',        // 地图图层,比如底图、矢量图等        layers: [            getIMG_CLayer(),            getIBO_CLayer(),            getCIA_CLayer(),        ],        // 地图视野        view: new ol.View({            projection: "EPSG:4326",            // 定位            center: [115.67724700667199, 37.73879478106912],            // 缩放            zoom: 6,            maxZoom: 18,            minZoom: 1,        })    });    /**     * @todo wkt格式数据转化成图形对象     * @param {string} wkt   "POINT(112.7197265625,39.18164062499999)" 格式数据     * @param {string|Projection} sourceCode 源投影坐标系     * @param {string|Projection} targetCode 目标投影坐标系     * @returns {Feature}     */    function getFeatureByWKT(wkt, sourceCode, targetCode) {        try {            let view = map.getView();            if (!wkt) {                return null;            }            let format = new ol.format.WKT();            let feature;            feature = format.readFeature(wkt, {                featureProjection: targetCode || view.getProjection(),                dataProjection: sourceCode || view.getProjection(),            });            return feature;        } catch (e) {            console.log(e);            return null;        }    }    /**     * @todo 颜色十六进制转为 rgba     * @param sColor 格式数据     * @param opacity     * @returns rgba颜色字符串     */    function colorToRgb(sColor, opacity) {        //用于十六进制颜色和rgb转换的正则        var REG = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;        sColor = sColor.toLowerCase();        if (/^[A-Za-z]+$/.test(sColor))            return sColor;        if (sColor && REG.test(sColor)) {            if (sColor.length === 4) {                let sColorNew = "#";                for (let i = 1; i < 4; i += 1) {                    sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));                }                sColor = sColorNew;            }            //处理六位的颜色值            let sColorChange = [];            for (let i = 1; i < 7; i += 2) {                sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));            }            if (opacity)                sColorChange.push(opacity);            return "rgba(" + sColorChange.join(",") + ")";            // return sColorChange;        } else {            return sColor;        }    };    // 地图事件    function clickFunction(evt) {        let feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layerVetor) {            return feature.getProperties().features;        });        // 图形要素的点击事件        // 这里可以使用气泡框展示信息        if (feature && feature.length == 1) {            console.log(feature[0]);            alert('点击了:' + feature[0].get('name'));        } else {            feature && console.log(feature);            feature && alert('点击了包含:' + feature.length + ' 个图形要素的聚合图!');        }    }    // 初始化点击事件标记    var initClickFlag = false;    // 点击事件    function activateClickFunc() {        initClickFlag && alert('已开启点击事件!');        map.on('click', clickFunction);        initClickFlag = true;    }    // 关闭点击事件    function shutDownClick() {        alert('已关闭点击事件!');        map.un('click', clickFunction);    }    // 点线面数组    var features = undefined;    // 聚合图图层对象    var clusterLayer = undefined;    // 资源对象    var vectorSource = undefined;    // 聚合图对象    var clusterSource = undefined;    // 初始化聚合图    function initCluster() {        features = [];        // 模拟数据        for (var i = 1; i <= 15; i++) {            var feature = getFeatureByWKT(                "POINT(" + (113 + (i / 10)) + " " + (35 + (i / 10)) + ")"            );            var feature2 = getFeatureByWKT(                "POINT(" + (113 + ((i + 5) / 10)) + " " + (35 + (i / 10)) + ")"            );            var feature3 = getFeatureByWKT(                "POINT(" + (113 + ((i + 9) / 10)) + " " + (35 + (i / 10)) + ")"            );            var point = new ol.style.Style({                // 点样式                image: new ol.style.Icon({                    // 允许跨域,如果不设置,打印地图不会打印                    crossOrigin: 'anonymous',                    // 标注图片和文字之间的距离                    anchor: [0.5, 0],                    // 图片的偏移                    offset: [0.2, 0],                    // 图片的锚点,一般来说,都是右下角                    anchorOrigin: 'bottom-right',                    //图标的url                    src: ";,                    scale: 1,                })            });            feature.setStyle(point);            feature.set('name', 'feature1-' + i);            feature.set('capability', i / 15);            feature2.setStyle(point);            feature2.set('name', 'feature2-' + i);            feature2.set('capability', i / 15);            feature3.setStyle(point);            feature3.set('name', 'feature3-' + i);            feature3.set('capability', i / 15);            features.push(feature)            features.push(feature2)            features.push(feature3)        }        /**         * 资源         */        vectorSource = new ol.source.Vector({});        // 聚合图        clusterSource = new ol.source.Cluster({            wrapX: false,            source: vectorSource,        });        // 图层        clusterLayer = new ol.layer.Vector({            source: clusterSource,            zIndex: 1,        });        map.addLayer(clusterLayer);    }    /**     * todo 增加聚合图     * @param dynamicData (参数是features)     */    function addData(dynamicData, distance, original) {        // 最大图形要素数量        var maxFeatureCount;        // 当前分辨率        var currentResolution;        // 普通样式,普通小圆圈        var originalStyle = function (feature) {            var features = feature.get('features');            var size = features.length;            return new ol.style.Style({                image: new ol.style.Circle({                    radius: 30,                    stroke: new ol.style.Stroke({                        color: '#fff'                    }),                    fill: new ol.style.Fill({                        color: '#969696'                    })                }),                text: new ol.style.Text({                    text: size.toString(),                    fill: new ol.style.Fill({                        color: '#fff'                    })                })            });        }        // 动态样式样式,根据权重和数量计算        var varyStyle = function (feature) {            var originalFeatures = feature.get('features');            var size = feature.get('features').length;            var capability_avg = 0;            var textName = "";            var j = (void 0), jj = (void 0);            for (j = 0, jj = originalFeatures.length; j < jj; ++j) {                capability_avg += (originalFeatures[j].get("capability") || 1)                textName = originalFeatures[j].get("name") || "";            }            capability_avg = (capability_avg / size).toFixed(2);            var round = getPointArray(capability_avg);            var opacity = Math.min(0.8, 0.4 + (size / maxFeatureCount));            var style = new ol.style.Style({                image: new ol.style.Circle({                    radius: feature.get('radius'),                    fill: new ol.style.Fill({                        color: colorToRgb(round.split(",")[1], opacity)                    })                }),                text: new ol.style.Text({                    // text: textName ? (textName + ":" + capability_avg) : feature.get('radius'),                    text: "权重平均值:" + capability_avg,                    font: 'normal bold  14px  Arial,sans-serif',                    fill: new ol.style.Fill({                        color: '#fff'                    }),                    stroke: new ol.style.Stroke({                        color: 'rgba(0, 0, 0, 0.6)',                        width: 3                    })                })            });            return style;        }        // 单体 feature 样式        var featureStyle = function (feature) {            var originalFeatures = feature.get('features');            if (originalFeatures.length != 1) {                return;            }            var originalFeature = originalFeatures[0];            var style = originalFeature.getStyle();            style && style.setText(                new ol.style.Text({                    text: originalFeature.get("name"),                    // 偏移                    offsetX: 0,                    offsetY: -54,                    // 居中                    textAlign: 'center',                    // 比例                    scale: 1,                    textBaseline: 'middle',                    // 边距                    padding: [2, 2, 2, 2],                    // 覆盖显示:即文字超过多边形也会显示                    overflow: true,                    // 字体颜色                    fill: new ol.style.Fill({                        color: 'rgba(51,51,51, 1)'                    }),                    // 字体边框,可以配合 fill 是文字高亮                    stroke: new ol.style.Stroke({                        color: 'rgba(0, 255, 255, 0.8)',                        width: 2,                    }),                    // 背景色                    backgroundFill: new ol.style.Fill({                        color: 'rgba(252,254,255, 1)'                    }),                })            )            return style;        }        // 样式方法        function styleFunction(feature, resolution) {            // 如果是拖动地图,则不重新渲染样式            if (resolution != currentResolution) {                calculateClusterInfo(resolution);                currentResolution = resolution;            }            var style;            var size = feature.get('features').length || 0;            // size大于1,则表示是聚合状态            if (size > 1) {                if (original == true) {                    style = originalStyle(feature);                } else {                    style = varyStyle(feature);                }                // size 等于1,表示是单体 feature            } else if (size == 1) {                style = featureStyle(feature);            }            return style;        }        // 计算聚合图样式信息        var calculateClusterInfo = function () {            if (!clusterLayer) {                return;            }            maxFeatureCount = 0;            var features = clusterLayer.getSource().getFeatures();            var feature, radius;            for (var i = features.length - 1; i >= 0; --i) {                feature = features[i];                var originalFeatures = feature.get('features');                // 计算权重                var capability = 0;                var j = (void 0), jj = (void 0);                for (j = 0, jj = originalFeatures.length; j < jj; ++j) {                    // 这是使用 capability 自定义属性的值计算权重                    capability += (originalFeatures[j].get("capability") || 1)                }                // 根据实际的数据量,调整聚合显示半径的大小                // PS:这个需要更新项目实际调整                if (originalFeatures.length < 10) {                    radius = capability + originalFeatures.length;                    while (radius > 100) {                        radius = radius / 10;                    }                    radius = radius + 10;                } else if (originalFeatures.length >= 10 && originalFeatures.length <= 50) {                    radius = capability + originalFeatures.length;                    while (radius > 100) {                        radius = radius / 10;                    }                    radius = radius + 20;                } else if (originalFeatures.length > 100 && originalFeatures.length <= 5000) {                    radius = capability + originalFeatures.length;                    while (radius > 100) {                        radius = radius / 10;                    }                } else if (originalFeatures.length > 5000 && originalFeatures.length <= 10000) {                    radius = capability + originalFeatures.length;                    while (radius > 100) {                        radius = radius / 10;                    }                } else if (originalFeatures.length > 10000) {                    radius = capability + originalFeatures.length;                    while (radius > 100) {                        radius = radius / 10;                    }                    radius = radius;                }                // 取二者最大值                maxFeatureCount = Math.max(maxFeatureCount, jj);                feature.set('radius', radius);            }        };        // 获取聚合图颜色        // 自定义颜色(图例和颜色以逗号拼接)        var getPointArray = function (v) {            if (v >= 0.8 && v <= 1) return '0.8-1.0,#FF0000'            else if (v >= 0.6 && v < 0.8) return '0.6-0.8,#FFFF00'            else if (v >= 0.4 && v < 0.6) return '0.4-0.6,#DAA520'            else if (v >= 0.2 && v < 0.4) return '0.2-0.4,#0000FF'            else if (v >= 0 && v < 0.2) return '0-0.2,#228B22'        }        // 设置聚合距离,也就是半径范围内聚合        clusterSource.setDistance(distance);        // 添加数据        vectorSource.addFeatures(features);        // 设置样式        clusterLayer && clusterLayer.setStyle(styleFunction)    }    // 添加聚合图    // flag, true 为加载原始样式,其他为加载权重样式    function addCluster(flag) {        closeCluster();        initCluster();        flag ? addData(features, 60, flag) : addData(features, 40);    }    // 关闭聚合图    function closeCluster() {        clusterLayer && map.removeLayer(clusterLayer);        clusterLayer = undefined;    }    // 默认加载原始聚合图    addCluster(true);    // 默认开始点击事件    activateClickFunc();</script><button id="addCluster" onClick="addCluster(true)">添加聚合图</button><button id="addWeightCluster" onClick="addCluster()">添加权重聚合图</button><button id="closeCluster" onClick="closeCluster()">关闭聚合图</button><button id="activateClickFunc" onClick="activateClickFunc()">开启点击事件</button><button id="shutDownClick" onClick="shutDownClick()">关闭点击事件</button></body></html>

PS:点击弹出气泡框可参考 Openlayers 自定义气泡框以及定位到气泡框_Southejor的博客-CSDN博客_openlayers 气泡

在线示例

Openlayers 聚合图:OpenLayers example

标签: #气泡框html #jquery悬浮气泡文字 #jquery锚点