leaflet可视化平台搭建

2023-11-12

leaflet-viz

Leaflet可视化平台

https://github.com/zrysmt/leaflet-viz

leaflet是一个开源的前端地图交互类库,比较轻量级,支持移动端。而且有丰富的插件资源可供我们使用。

Echarts是百度开源的前端可视化类库,提供丰富的前端可视化图表,平台中重要的一部分是我们要将leaflet和Echarts结合在一起。

该平台是基于leaflet及其插件搭建的一个方便可用的可视化平台。详细参见[示例Demo]。(https://zrysmt.github.io/demo/leaflet-demo/)

1. 安装与编译

  • 安装
npm install
  • 编译

debug模式

npm run dev

输出

npm run build

2.示例简介

示例地址:https://zrysmt.github.io/demo/leaflet-demo/

示例包含最基本的GIS功能和可视化Demo

3.基础的GIS功能

  • 拖放、全图、定位、打印出图片、打印出PDF功能。
  • 地图缩放、比例尺显示功能
  • 测量面积和距离功能
  • 图层切换,提供丰富的图层切换
  • 地图搜索功能
  • 基础绘图功能

4.可视化示例


- 热力图

引入:

import '../common/leaflet-plugin/HeatLayer.js';

使用:

var heat = L.heatLayer([
    [50.5, 30.5, 0.2], // lat, lng, intensity
    [50.6, 30.4, 0.5],
...
], {radius: 25}).addTo(map)

效果图

- 结合Echarts

let overlay = new L.echartsLayer3(map, echarts);
let chartsContainer = overlay.getEchartsContainer();
let myChart = overlay.initECharts(chartsContainer);
window.onresize = myChart.onresize;
console.log("chartsContainer:", chartsContainer);
if (type == "qianxi") {
    overlay.setOption(ecOption);
} else if (type == "scatter") {
    overlay.setOption(scatterOption);
}

迁徙图(选择了高德卫星底图)

散点图(选择了Geoq午夜蓝底图)

- DivIcon结合Echarts

这个方案不太适合大数据量的渲染。
我写了两个简单的功能函数,一个用来渲染可视化图(echartsIcon),一个专门用来渲染图例(echartsLegend)。
效果图(底图选择了为google底图)

import echartsIcon from '../common/plugin/echartsIcon.js'; //echartsLegend
import echartsLegend from '../common/plugin/echartsLegend.js'; //echartsLegend
let option = {
    tooltip: {
        trigger: 'item',
        formatter: "{a} <br/>{b} : {c} ({d}%)"
    },
    series: [{
        name: '访问来源',
        type: 'pie',
        radius: '55%',
        center: ['50%', '50%'],
        label: {
            normal: {
                show: false
            },
            emphasis: {
                show: false
            }
        },
        lableLine: {
            normal: {
                show: false
            },
            emphasis: {
                show: false
            }
        },
        itemStyle: {
            emphasis: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
        }
    }]
};
//经纬度不能相同
let latlngs = [
    [30, 104],
    [31, 110],
    [34, 120]
];
option.datas = [
    [
        { value: 335, name: '直接访问' },
        { value: 310, name: '邮件营销' },
        { value: 234, name: '联盟广告' },
        { value: 135, name: '视频广告' },
        { value: 1548, name: '搜索引擎' }
    ],
    [
        { value: 345, name: '直接访问' },
        { value: 410, name: '邮件营销' },
        { value: 244, name: '联盟广告' },
        { value: 145, name: '视频广告' },
        { value: 548, name: '搜索引擎' }
    ],
    [
        { value: 445, name: '直接访问' },
        { value: 410, name: '邮件营销' },
        { value: 244, name: '联盟广告' },
        { value: 145, name: '视频广告' },
        { value: 148, name: '搜索引擎' }
    ],
];
echartsIcon(map, latlngs, option);
//图例
let legendOption = {
    orient: 'vertical',
    left: 'left',
    width: "90px",
    height: "140px",
    data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
};
echartsLegend(map, legendOption);
  • leaflet-dvf

leaflet-dvf是一个基于leaflet的数据可视化框架,提供有比较多的可视化图形。

import "../common/leaflet-plugin/Leaflet.dvf/css/dvf.css";
import "leaflet-dvf";

地震图:

收入水平图:

需要的数据

import earthquakesData from '../data/earthquakes.json';
import countryData from '../data/countryData.js';

地震图代码:

 let lastLayer;

 let eqfeed_callback = function(data) {

     // Initialize framework linear functions for mapping earthquake data properties to Leaflet style properties
     // Color scale - green to red using the basic HSLHueFunction
     let magnitudeColorFunction = new L.HSLHueFunction(new L.Point(0, 90), new L.Point(10, 0), { outputSaturation: '100%', outputLuminosity: '25%', postProcess: null });
     let magnitudeFillColorFunction = new L.HSLHueFunction(new L.Point(0, 90), new L.Point(10, 0), { outputSaturation: '100%', outputLuminosity: '50%', postProcess: null });
     let magnitudeRadiusFunction = new L.LinearFunction(new L.Point(0, 10), new L.Point(10, 30), { postProcess: null });

     let now = Math.round((new Date()).getTime());
     let start = now - 86400000;

     // Initialize a linear function to map earthquake time to opacity
     let timeOpacityFunction = new L.LinearFunction(new L.Point(start, 0.3), new L.Point(now, 1));
     let fontSizeFunction = new L.LinearFunction(new L.Point(0, 8), new L.Point(10, 24));

     let textFunction = function(value) {
         return {
             text: value,
             style: {
                 'font-size': fontSizeFunction.evaluate(value)
             }
         };
     };

     // Setup a new data layer
     let dataLayer = new L.DataLayer(data, {
         recordsField: 'features',
         latitudeField: 'geometry.coordinates.1',
         longitudeField: 'geometry.coordinates.0',
         locationMode: L.LocationModes.LATLNG,
         displayOptions: {
             'properties.mag': {
                 displayName: '震级',
                 color: magnitudeColorFunction,
                 fillColor: magnitudeFillColorFunction,
                 radius: magnitudeRadiusFunction,
                 text: textFunction
             },
             'properties.time': {
                 displayName: '时间',
                 opacity: timeOpacityFunction,
                 fillOpacity: timeOpacityFunction,
                 displayText: function(value) {
                     return moment.unix(value / 1000).format('MM/DD/YY HH:mm');
                 }
             }
         },
         layerOptions: {
             numberOfSides: 4,
             radius: 10,
             weight: 1,
             color: '#000',
             opacity: 0.2,
             stroke: true,
             fillOpacity: 0.7,
             dropShadow: true,
             gradient: true
         },
         tooltipOptions: {
             iconSize: new L.Point(90, 90), //hover框大小
             iconAnchor: new L.Point(-4, 76)
         },
         onEachRecord: function(layer, record, location) {
             let $html = $(L.HTMLUtils.buildTable(record));

             layer.bindPopup($html.wrap('<div/>').parent().html(), {
                 minWidth: 400,
                 maxWidth: 400
             });
         }
     });

     // Add the data layer to the map
     map.addLayer(dataLayer);

     lastLayer = dataLayer;
 };

 this.mapSetting();

 if (lastLayer) {
     map.removeLayer(lastLayer);
 }

 console.log("earthquakesData:", earthquakesData);
 eqfeed_callback(earthquakesData)

收入水平图代码:

let incomeLevelTypes = ['OEC', 'NOC', 'UMC', 'MIC', 'LMC', 'LIC', 'HPC'];
let valueArray = [{ "id": "HIC", "value": "高收入(HIC)" },
    { "id": "HPC", "value": "收入严重不足(HIPC)" }, { "id": "INX", "value": "未分类(INX)" },
    { "id": "LIC", "value": "低收入(LIC)" }, { "id": "LMC", "value": "中等偏下(LMC)" },
    { "id": "LMY", "value": "中低等收入" }, { "id": "MIC", "value": "中等收入(MIC)" },
    { "id": "NOC", "value": "高收入:nonOECD(NOC)" }, { "id": "OEC", "value": "高收入: OECD(OEC)" },
    { "id": "UMC", "value": "中等偏上(UMC)" }
];
let getMap = function(valueArray) {
    let map = {};
    for (let index = 0; index < valueArray.length; ++index) {
        let value = valueArray[index];

        map[value['id']] = value['value'];
    }
    return map;
};

let valueMap = getMap(valueArray);

let incomeLevelToText = function(value) {
    return valueMap[incomeLevelTypes[value]];
};

let colorFunction1 = new L.HSLLuminosityFunction(new L.Point(0, 0.2), new L.Point(incomeLevelTypes.length - 1, 0.75), { outputHue: 0, outputLuminosity: '100%' });
let fillColorFunction1 = new L.HSLLuminosityFunction(new L.Point(0, 0.5), new L.Point(incomeLevelTypes.length - 1, 1), { outputHue: 0, outputLuminosity: '100%' });

let styles = new L.StylesBuilder(incomeLevelTypes, {
    displayName: incomeLevelToText,
    color: colorFunction1,
    fillColor: fillColorFunction1
});

let options = {
    recordsField: '1',
    locationMode: L.LocationModes.COUNTRY,
    codeField: 'id',
    displayOptions: {
        'incomeLevel.id': {
            displayName: '收入水平',
            styles: styles.getStyles()
        }
    },
    layerOptions: {
        fillOpacity: 0.7,
        opacity: 1,
        weight: 1
    },
    tooltipOptions: {
        iconSize: new L.Point(100, 65),
        iconAnchor: new L.Point(-5, 65)
    },

    onEachRecord: function(layer, record) {
        let $html = $(L.HTMLUtils.buildTable(record));

        layer.bindPopup($html.wrap('<div/>').parent().html(), {
            maxWidth: 400,
            minWidth: 400
        });
    }
};

let incomeLayer = new L.ChoroplethDataLayer(incomeLevels, options);

let legendControl = new L.Control.Legend();

legendControl.addTo(map);
map.addLayer(incomeLayer);

5.GeoJSON

假设我们需要自己做个地图,然后加载到平台中。这个时候可以使用我们提供了编辑栏,编辑后会得到坐标,把坐标转成GeoJSON数据存到数据库中,下次加载的时候解析即可。
还可以使用GIS工具,做成GeoJSON的数据,然后使用下面的方法加载,详细说明的传送门在这,当然这包括MapServer的东西,我们将在第六部分有简要说明。
示例图:

引入数据:

import { json_china } from '../data/china.js';
function pop_0(feature, layer) {//部分有省略
    let popupContent = '<table>\
                    <tr>\
                        <td colspan="2">面积:' + (feature.properties['AREA'] !== null ? Autolinker.link(String(feature.properties['AREA'])) : '') + '</td>\
                    </tr>\
                    <tr>\
                        <td colspan="2">周长:' + (feature.properties['PERIMETER'] !== null ? Autolinker.link(String(feature.properties['PERIMETER'])) : '') + '</td>\
                    </tr>\
                    <tr>\
                        <td colspan="2">名称:' + (feature.properties['NAME'] !== null ? Autolinker.link(String(feature.properties['NAME'])) : '') + '</td>\
                    </tr>\
                </table>';
    layer.bindPopup(popupContent);
}

function style_0() {
    return {
        pane: 'pane_0',
        opacity: 1,
        color: 'rgba(0,0,0,0.494117647059)',
        dashArray: '',
        lineCap: 'butt',
        lineJoin: 'miter',
        weight: 1.0,
        fillOpacity: 1,
        fillColor: 'rgba(64,98,210,0.494117647059)',
    }
}
map.createPane('pane_0');
map.getPane('pane_0').style.zIndex = 400;
map.getPane('pane_0').style['mix-blend-mode'] = 'normal';
let layer_0 = new L.geoJson(json_china, {
    attribution: '<a href=""></a>',
    pane: 'pane_0',
    onEachFeature: pop_0,
    style: style_0
});

6.MapServer

再进一步,如果我们想要自己的地图服务器,这个时候就需要使用到了MapServer,具体的说明见传送门

有个示例在test文件夹下:leaflet-mapserver.html。注意这个是需要配置好服务器的,在这里直接预览是不能成功的。
示例得到我们的世界地图的地图服务器。

其实leaflet和D3等开源库结合起来,能得到很多丰富多彩的可视化图,姑且留下点神秘,这里就不再探究两者结合的神奇魅力了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

leaflet可视化平台搭建 的相关文章

  • 使用 sf 列调整 Leaflet (R) 中的边界

    我正在 Shiny 中制作一个小应用程序 它保存国家和地区的数据 用户可以在其中选择一个区域 然后的想法是 我在应用程序中拥有的传单地图将放大并聚焦于所选区域 即用户单击 欧洲 地图会放大到欧洲 我不知道应该如何使用这些简单的功能geome
  • 如何检查 svg 路径是否具有与数组中的值匹配的类,如果是,则添加一个新类

    我有一个数组和一些svg path元素 我正在使用传单地图 https leafletjs com 我需要检查路径的类是否与数组中的值之一匹配 如果是则添加一个类fadeIn to it var foundNations usa Franc
  • 使用 R 中的传单库绘制跨越国际日期变更线的路线

    我有兴趣使用 R 的传单库绘制从滑铁卢到台湾的路线 路线的坐标是使用 geosphere 中的 gcIntermediate 函数获得的 然而 该路线涉及穿越国际日期变更线 因此该路线在地图边缘被切断 并在顶部与直线连接 我得到的情节 错误
  • Postgis - ST_within 没有做我想做的事。如何在空心区域中找到一个点?

    请参阅丝网印刷 我在 Postgis 中运行了一个空间查询 以返回地图上某个点所在的选区 区域 该查询使用ST within函数 其中点位于多边形内 正如您从打印中看到的 该点实际上并不在 York Outer 的多边形区域 内 尽管从技术
  • 如何在react 16.4.1中使用leaflet-polylinedecorator

    我正在尝试在react 16 4 1中使用传单插件polylinedecorator 所以没有钩子 然而 我能找到的关于如何在 React 中使用此插件的唯一示例是使用钩子 请参阅 如何将 Polylinedac orator 与 Reac
  • R传单和闪亮如何清除地图点击数据

    下面的例子摘自RStudio 教程 http rstudio github io leaflet shiny html传单上 我稍微修改了一下以适应我的问题 我有一张地图 这里是地震 我使用它在地图上绘制addCircleMarkers单击
  • Leaflet.label 未显示在标记上

    我有一组 geoJSON 点 它们附加了相应的标签 var points L geoJson null onEachFeature function feature layer layer options riseOnHover true
  • 传单:同一页上有多个地图

    我搜索过类似的问题 但没有找到适合我的情况的答案 我想使用 3 张传单地图 每张都有不同的内容 出现两个问题 仅显示第一个 比例和缩放控件仅显示在第三个中 我附上了一个 jsfiddle 以防你能帮忙 const mapbox L tile
  • Leaflet Map - 第二个多边形使第一层不可点击

    我正在制作美国社区调查数据地图 目前我有一个主要层 如下所示plotMerge incomePerCapita 它运作良好 有一个完全充实的弹出窗口 图像等等 当我添加第二层以提供县和地区边界时 区域边界变得不可单击 似乎被新层掩盖了 如果
  • leaflet.draw 垃圾按钮删除所有多边形并保存

    使用javascript 如何更改leaflet draw 垃圾桶 按钮以删除所有已绘制并自动保存的多边形 下面是我实现的代码 但它是一个完整的黑客 它会删除活动多边形 但是在删除对象后 当我单击 垃圾箱 图标时 控制台中开始出现错误Not
  • 是否可以将自定义 HTML 添加到传单图层组和图层控件

    有什么方法可以将自定义 HTML 注入图层组和图层控件中吗 在我们的应用程序中 我们实现了滑块 输入 范围 来调整不透明度设置 并且很明显 在其控制容器内部的基础层上使用专用滑块是有意义的 没有选项或参数可以修改此控件 理想情况下 我们希望
  • R Leaflet Legend:colorBin-删除中断之间的小数

    我正在使用 Leaflet 库在 R 中创建交互式 HTML 地图 传说中采用的是colorBin用于创建将数据分为 6 个类别的方法 使用min values and max values 我已经定义了美国社区调查收入数据的特定范围可能落
  • 使用文本字段同时过滤react-table和react-leaflet标记(在表中显示过滤数据并在地图中显示标记)

    我是反应传单的新手 需要一点帮助来解决我的问题 跟进上一篇文章 https stackoverflow com questions 52557802 how to get the number of map markers per coun
  • Leaflet js虚构地图

    我是 Leaflet 的新手 我想了解如何创建完全交互式的虚构地图 我有一张图像想要转换为传单地图 该图像基本上像图表一样具有许多连接和点 我想首先将该图像转换为地图 能够将鼠标悬停在这些点上 突出显示它们并显示有关它们的信息 并且还可以在
  • 闪亮的传单添加大量分离的折线

    我有一个 200k 行数据集 其中包含出发地和目的地的坐标 我有一个 R 闪亮的应用程序 带有传单地图 可以在这些坐标上显示圆圈 尽管坐标数量很大 但效果很好 这是数据的简化示例 每行包含出行id 出发地经纬度 目的地经纬度 id lat
  • Mapbox 打字稿

    通过关注这个项目 我成功地让 Leaflet 与 Angular 2 和 Webpack 一起工作 Angular 2 传单启动器 https github com haoliangyu angular2 leaflet starter 我
  • 网络上的等角柱状图

    我计划为游戏的标记 图钉 构建在线地图 但我无法设置标记的正确纬度 原始地图是一个2048 2048px 的正方形 然后我得到了标记 数千个 地图坐标使用 0 到 100 之间的 x y 表示法设置 0 0 是top left角和100 1
  • 使用shinyjs通过javascript在闪亮的应用程序中操作现有的Leaflet地图

    我有一个闪亮的应用程序 其中包含现有的传单地图 我希望能够在渲染后使用自定义 javascript 通过shinyjs包裹 一个最小的例子如下 app R packages library dplyr library leaflet lib
  • 基于内部图标的传单簇颜色

    我的 leaflet js 地图上有图钉 其中图像由它们所代表的对象的状态确定 例如 在线和离线用户 在线为绿色 离线为红色 我通过向 divIcon 添加一个类 然后使用 css 控制图像来实现此目的 我现在已将标记聚类添加到我的地图中
  • 如何强制传单更新地图?

    当我将 Leaflet 与 React 一起使用时 我遇到了问题 据我研究 问题是 Leaflet 也想控制 DOM 渲染 现在 国家将使用与后端信息相对应的特定颜色代码 范围为1 gt 100 正确着色 但是 它每分钟更新一次 更新后 国

随机推荐

  • 后谷歌时代:谁能笑到最后?

    后谷歌时代 谁能笑到最后 自从谷歌把 g cn转向 www google com hk那天起 后谷歌时代已经来临 早在谷歌退出中国市场仅仅是传言时 搜狗 有道 搜搜纷纷叫嚣着抢夺谷歌在中国的市场份额 现在看来 抢夺谷歌中国市场份额的绝非搜狗
  • Cypress vs Playwright——哪个 JavaScript 测试框架更好?

    10 年前 自动化测试人员如果要编写 E2E 测试 主要使用 Selenium 每个有机会使用该解决方案的人都应该会记得设置 编写和调试是多么不愉快 在此过程中还创建了一些更有趣的自动化工具 例如 Webdriver io TestCafe
  • SonarLint(代码质量检测工具+案例+好习惯养成器)

    文章目录 参考文章 一 SonarLint是什么 代码质量检测器 SonarQube 和SonarCloud 二 代码质量问题案例 1 异常应该被记录或重新抛出 但不能同时被记录和重新抛出 2 局部变量不应该声明后立即返回或抛出 3 不使用
  • [carla]通过Twist指令控制carla中的车辆

    0 背景 通过carla ros bridge with example ego vehicle launch可以启动carla ros bridge 并在carla中生成一台可以遥控的车 roslaunch carla ros bridg
  • 前端js读取本地md或txt文件内容

  • mysql数据库日志查询

    Mysql数据库日志 日志分类 MySql日志类型 解析说明 错误日志 error log 当数据库启动 运行 停止时产生该日志 普通查询日志 general query log 客户端连接数据库执行语句时产生该日志 二进制日志 binar
  • 前端js拼接Json串

    前端js拼接json串 示例1 数组里面含对象 组成的json串 group
  • 带样式的HTML节点深拷贝

    引用自 摸鱼wiki 1 思路 使用 cloneNode true 深拷贝节点及其子节点的结构 利用 computedStyle 获取当前节点的样式 遍历获取的样式结构体 赋值给复制节点 递归子节点 循环进行2 3步 2 代码示例 func
  • 汽车保养项注意-2

    基本信息 大众朗逸刹车油每4万公里可更换一次 价格在200元左右 这应该定期更换 5万换一次即可 刹车片6 8万公里换一次 刹车盘7万公里 发动机内部养护 燃油系统养护 四轮定位是对整车行车轨迹的检查修正 包括悬挂 底盘 零部件等的调整 动
  • OAuth2四种模式

    OAuth2四种模式 一 隐式授权模式 Implicit Grant 流程图 步骤 优缺点及适用场景 二 授权码授权模式 Authorization code Grant 流程图 步骤 优缺点及适用场景 三 密码模式 Resource Ow
  • 计算机操作系统中常用算法总结

    计算机操作系统中常用算法总结 一 动态分区分配算法 1 首次适应算法 最先适应算法 按照分区的先后次序 从头开始查找 找到符合要求的第一个分区 2 循环首次适应算法 下次适应算法 按照分区的先后次序 从上次已分配的分区起查找 到达最后一个分
  • 上知天文,下知地理,还能替人写脚本!人工智能的进阶ChatGPT

    ChatGPT是OpenAI在11月30日推出的聊天机器人 于12月1日起对公众免费开放 自从这东西出来之后 大家对此的讨论热情越发浓烈 ChatGPT具体可以干些什么 帮你写论文 检讨书 情书 甚至情诗也能信手拈来 以上都是网友测试它写出
  • python numpy数组

    1 数组创建 import numpy arr numpy array 11 22 33 44 55 print arr 输出 11 22 33 44 55 数组属性查看 print type arr 输出
  • java 注解 @Retention @interface 元数据

    java注解 即是注释了 百度解释 也叫元数据 一种代码级别的说明 个人理解 就是内容可以被代码理解的注释 一般是一个类 元数据 也叫元注解 是放在被定义的一个注解类的前面 是对注解一种限制 只有两个 Retention 和 Target
  • 程序员常见系统错误代码大全:1到15841

    程序员常见系统错误代码大全 1到15841 提示 使用浏览器的Ctrl F键盘组合来搜索错误代码 要么搜索错误消息本身 要么只搜索错误代码 例如 错误代码635 系统错误代码大全 1到15841 错误代码1 功能不正确 ERROR INVA
  • IDEA获取gitee仓库的数据时,发生错误

    以本人遇到的情况为例 以上错误与本地的代码没有关系 主要原因是gitee仓库上的application yml配置文件的格式编写有误所导致 修改正确之后即可成功获取
  • DTO与Entity相互转化

    import java lang reflect Method import java util concurrent ConcurrentHashMap import org slf4j Logger import org slf4j L
  • 关于path用变量的问题思考

    1 用go解析路由时 中间件里相对路由做统一处理 或者是对于一组路由做处理 只能挨个正则去匹配 要不就多写代码 侵入业务 2 路由不可读 命名再不规范的话 抓包也痛苦 需要看代码才能理解这个接口是做什么的 和前端对接口时 前端 接口名字是什
  • 微服务回归单体,代码行数减少75%,性能提升1300%

    关注并星标腾讯云开发者 每周3 谈谈我在腾讯的架构设计经验 第5期 李浩津 13倍性能重构 搜索内容架构 C 微服务群改造 内容架构是 QQ 浏览器搜索的内容接入和计算层 主要负责腾讯域内的内容接入和处理 当前接入了多个合作方的上千类内容
  • leaflet可视化平台搭建

    leaflet viz Leaflet可视化平台 https github com zrysmt leaflet viz leaflet是一个开源的前端地图交互类库 比较轻量级 支持移动端 而且有丰富的插件资源可供我们使用 Echarts是