leaflet可視化平台搭建

來源:互聯網
上載者:User
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'; //echartsLegendimport 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等開源庫結合起來,能得到很多豐富多彩的可視化圖,姑且留下點神秘,這裡就不再探究兩者結合的神奇魅力了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.