精华内容
下载资源
问答
  • 地图渲染国际化
    2017-12-20 11:40:07

    地图操作关于放大缩小定位搜索等功能,其中最重要的是不管哪个操作,都是对echart的设置,具体函数如下:

    function localizeMap(center,zoom){
        var option = echartMap.getOption()
        if(center&&center.length==2)
            option.series[0].center=center
    
        if(zoom>=4.4)
            option.series[0].zoom=zoom
    
        echartMap.setOption(option)
        setTimeout("keepHighlight()",100)
    }

    首页点击放大

    function mapAmplification(center){
        var option = echartMap.getOption()
        var zoom=option.series[0].zoom+SCALE
        localizeMap(center?center:undefined,zoom)
    }

    首页点击缩小

    function mapNarrow(center){
    var option = echartMap.getOption()
    var zoom=option.series[0].zoom-SCALE
    if(zoom>=4.4)
    localizeMap(center?center:undefined,zoom)
    }

    首页点击定位

    function mapLocalizeInit(){
        var defCenter=[104, 37]
        var defZoom=4.4
        var option = echartMap.getOption()
        if(option.series[0].center[0]!=defCenter[0]||option.series[0].center[1]!=defCenter[1]||option.series[0].zoom!=defZoom)
            localizeMap(defCenter,defZoom)
    }

    首页点击搜索

    实现功能:
    1.默认不显示搜索栏,点击按钮自动缩放弹出搜索栏
    2.模糊匹配,输入单个字母或文字即可出现下拉框进行查询
    3.点击查询的省份即可在地图定位坐标
    以下是实现点击按钮出现搜索栏

     $("#left_bottom_options_search").on("click", function () {
           // $(".top_search").width("10rem")
           if ($(".top_search").attr("data-open")=="no") {
    
                $("#search_con").val($.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_inputvalue'))
            $(".top_search").animate({width:'11rem'},300);
            $(".top_search").attr("data-open","open")
        }else{
            $(".top_search").animate({width:'0rem'},300);
            $(".top_search").attr("data-open","no")
        }
        })

    以下是模糊搜索

        //搜索
        $("#search_con").on("focus", function () {//获得焦点清空值
            $("#search_con").val("")
            $(".ui-helper-hidden-accessible").hide();
            //模糊匹配控件跟时间控件冲突,会导致每次选择时间后无法执行选中搜索功能,所以使用及时加载的方式
            try{
                if(autoComplete)
                    $( "#search_con" ).autocomplete( "destroy" )
    
            }catch (e){
                console.log(e)
            }
             autoComplete = $("#search_con").autocomplete({//模糊匹配
                autoFocus: true,
                messages: {
                    noResults: $.i18n.prop('com_zte_lte_processingpoorqualitregion_cellsum_homepage_noresult'),
                    results: function() {return ""}
                },
                response: function () {
                    $(".ui-helper-hidden-accessible").show();
                },
                source: allProvinceNames,
                select:function(params1,params2){//选中搜索
                    provinceSearch(params2.item.value);
                    $(".ui-helper-hidden-accessible").hide();
                }
            })
            $(".ui-helper-hidden-accessible").hide();
        })
        $("#search_con").on("blur", function () {//空值恢复
            if ($("#search_con").val() == "") {
                $("#search_con").val($.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_inputvalue'))
            }
        })

    以下点击搜索名称直接可定位

     $("#search_con").bind('keypress',function(event){//回车搜索
            if(event.keyCode == 13)
                provinceSearch($("#search_con").val())
        })
        $(".search_btn").on("click", function () {//点击搜索
            provinceSearch($("#search_con").val())
        })

    搜索函数:

    function provinceSearch(key){
        provinceHighlight(key)
        if(highlightProvinceParams){
            if("pro".indexOf(thisPage)==0)
                myExports.showProvince(highlightProvinceParams.name)
            else
                detaillDataQuery(highlightProvinceParams.code)
        }
    
    }

    地图高亮效果

    function provinceHighlight(key){
        echartMap.dispatchAction({type: 'downplay'})//取消所有高亮
        highlightProvinceParams=undefined
        var provinceParams=getProvinceParams(key)
        //高亮指定的省
        if(provinceParams){
            highlightProvinceParams=provinceParams
            //省份定位
            var option = echartMap.getOption()
            option.series[1].data=[highlightProvinceParams.offset]
            echartMap.setOption(option)
    
            echartMap.dispatchAction({type: 'highlight',
                seriesIndex: 0,
                name: highlightProvinceParams.name})
        }
    }

    首页地图渲染的值可配置

    调用后端接口服务获取颜色的值,直接在初始化函数调用这个函数getConfigData即可,然后在地图初始化用保存过来的变量

     //得到配置
        var configData=[];
        var colorArry = [];
        var AreaNum;
        SCALE=0.3
    function getConfigData(){
             $.ajax({
                type: "get",
                async: true,
                url: '/rdk/service/app/vmax_r_poorqualityarea/server/poorQualityOfArea/giscolor',
                async: true,
                data: {modelname:'poorQualityOfArea'},
                success: function (result) {
                    if(result){
                        configData = result.value;
                        colorArry = [configData[4],configData[5],configData[6]];
                        AreaNum={
                            name:$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_sorttype'),
                            key:"countAreaId",
                            unit:"",
                            start:Number(configData[0]),
                            min:Number(configData[1]),
                            max:Number(configData[2]),
                            end:Number(configData[3])
                        }
                    }
                }
            })
        }
    更多相关内容
  • 一、初始全国各省份对象1.定义对象 省份名称—国际化名称变量var Langualarmap={ "安徽":"AH", "北京":"BJ", "福建":"FJ", "甘肃":"GS", "广东":"GD", "广西":"GX", "贵州":"GZ", "海南":"HI",

    一、初始全国各省份对象

    1.定义对象
    省份名称—国际化名称变量

    var Langualarmap={
            "安徽":"AH",
            "北京":"BJ",
            "福建":"FJ",
            "甘肃":"GS",
            "广东":"GD",
            "广西":"GX",
            "贵州":"GZ",
            "海南":"HI",
            "河北":"HE",
            "河南":"HA",
            "黑龙江":"HL",
            "湖北":"HB",
            "湖南":"HN",
            "吉林":"JL",
            "江苏":"JS",
            "江西":"JX",
            "辽宁":"LN",
            "内蒙古":"IM",
            "宁夏":"NX",
            "青海":"QH",
            "山东":"SD",
            "山西":"SX",
            "陕西":"SN",
            "上海":"SH",
            "四川":"SC",
            "天津":"TJ",
            "西藏":"XZ",
            "新疆":"XJ",
            "云南":"YN",
            "浙江":"ZJ",
            "重庆":"CQ",
            "澳门":"MO",
            "香港":"HK",
            "台湾":"TW",
        }

    2.获得地图对象并按照是英文还是中文初始地图省份

     allProvinceInfo = {100000: {
            //name: "全国",国际化中替换
            data: {}}}
             var allFeatures = echarts.getMap("world").geoJson.features;
             var language = showLanguage();
        for (var i = 0; i < 34; i++) {
            var name=allFeatures[i + 216].properties.name
             name=language.indexOf("en")>=0? $.i18n.prop(Langualarmap[name]):name
            allFeatures[i + 216].properties.name=name
            allProvinceInfo[allFeatures[i + 216].properties.id] = {
                index: (i + 216),
                name: name,
                offset:(
                    language.indexOf("en")>=0?
                        (
                            "810000".indexOf(allFeatures[i + 216].properties.id)>=0?
                                [114.252,22.345]
                                :"820000".indexOf(allFeatures[i + 216].properties.id)>=0? [113.565,22.17]
                                :"120000".indexOf(allFeatures[i + 216].properties.id)>=0?[116.8,39.6]
                                :allFeatures[i + 216].properties.cp
                        ):allFeatures[i + 216].properties.cp
                ),
                data: {}
            }
            allProvinceNames.push(name)
        }

    二、正式加载地图

    1.地图按照中英文来渲染
    2.单击地图点击事件
    3.触屏或双击地图点击事件

    function mapInit(rankType, data) {
        $(".left_bottom_options").fadeIn()
        var rankInfo = {
            name: "--",
            start:0,
            min: 100,
            max: 200,
            end: 300
        }
        if (rankType && rankType.name)
            rankInfo = rankType
    
        var effectScatterData=[]
        var regionDataArray=[]
        var rankData;
        for(var i in allProvinceInfo){
            if (data) {
                rankData=data[allProvinceInfo[i].name]
            }
            var regionData={
                name: allProvinceInfo[i].name,
                label:{
                    normal: {
                        show:true,
                        color:'#96D6FF',
                    }
                },
                itemStyle: {normal: {borderColor: '#005C97'}}
            }
            if(rankData)
                regionData.value=rankData
                regionDataArray.push(regionData)
        }
    
        var mapDom = $("#myMap")
        if(!echartMap){
            echartMap = echarts.init(mapDom[0])
            echartMap.on("mouseover", function (params) {//禁止外国高亮)
                if (allProvinceNames.indexOf(params.name) < 0)
                    echartMap.dispatchAction({
                        type: 'downplay',
                        name:params.name
                    })
            })
            var TimeFn = null;
            echartMap.on("click", function (params) {
                var provinceParams=getProvinceParams(params.name)
                if(provinceParams){
                    highlightProvinceParams=provinceParams
                    provinceHighlight(provinceParams.code)
                    clearTimeout(TimeFn);
                  //执行延时
                    TimeFn = setTimeout(function(){
                             //do function在此处写单击事件要执行的代码
                              myExports.showProvince(highlightProvinceParams.name)
                    },300);
    
                   // detaillDataQuery(provinceParams.code)//展开详情页
                }
                var i = function(para) {
                    if(para.name===params.name) {
                        //myExports.showProvince(params.name);
                        myExports.goToAnalysis(params.name);
                    }
                };
                echartMap.on("click", i)
                setTimeout(function(){echartMap.off("click", i)}, 300)
            })
            window.onresize = function () {//地图自适应宽高
                var receptacle=$(".echart_box")
                mapDom.width(receptacle.width())
                mapDom.height(receptacle.height())
                echartMap.resize()
                /*详情echart*/
                var graphic = $('#graphic'),listPageObj = $('#listPage');
                $('.echartDiv').width(listPageObj.width() ? listPageObj.width() : graphic.width());
                $('.echartDiv').height(graphic.height());
                if(typeof(myChart) != "undefined")
                    myChart.resize();
                //保持高亮
                keepHighlight()
            }
        }
        echartMap.setOption({
            tooltip:{
                show:true,
                trigger: 'item',
                extraCssText:'border:0;padding:0;background-color:rgba(0,0,0,0)',
                formatter:function(params){
                    var tooltipFormatter="<div class='tooltip_head'>"+params.name+$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_statistics')+"</div><div class='tooltip_center'>"
    
                    if (allProvinceNames.indexOf(params.name) < 0)//禁止国外弹出
                        tooltipFormatter=null
                    else{
                        var provinceData=getRightBoxListData(params.name)
                        if(provinceData){
                            tooltipFormatter+=$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_sorttype')+":"+provinceData.SORT+"<br/>";
                            tooltipFormatter+=$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_dealingorder')+":"+provinceData.dealingNumber+"<br/>";
                            tooltipFormatter+=$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_overtimeorder')+":"+provinceData.willNumber+"</div>";
    
                        }else{
                            tooltipFormatter+=$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_sorttype')+":--<br/>";
                            tooltipFormatter+=$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_dealingorder')+":--<br/>";
                            tooltipFormatter+=$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_overtimeorder')+":--</div>";
    
                        }
                    }
    
                    return tooltipFormatter
                }
            },
            visualMap: [{//地图标点颜色
                type: 'piecewise',
                //splitNumber:3,//颜色区间,跟下面的pieces冲突
                pieces: [
                    {min: rankInfo.max, label: '(' + rankInfo.max +  ',+∞)'},
                    {min: rankInfo.min, max: rankInfo.max, label: '(' + rankInfo.min + ',' + rankInfo.max + ']'},
                    {max: rankInfo.min, label: '(' + rankInfo.start + ',' + rankInfo.min + ']'}
                ],
               // seriesIndex: 1,
                text: [rankInfo.name],
                showLabel: true,//设置了text后,label会默认不显示
                hoverLink: false,
                orient: 'horizontal',//横放指标
                ///dimension: 2,//数据的维度
                color: colorArry,
                textStyle: {
                    color: 'rgba(94, 202, 252, 0.8)'
                },
                left:20
            }],
            series: [
                {
                    type: 'map',
                    //geoIndex: 0,
                    mapType: 'world',
                    roam: true,//鼠标放大
                    zoom: 4.4,
                    center: [104, 37],
                    label:{
                        emphasis: {
                            show:true,
                            color:'#96D6FF',
                        },
                    },
                    itemStyle: {//默认地图颜色
                        normal: {
                            areaColor: '#041A34',
                            borderWidth: 2,
                            borderColor: '#171717'
                        }
                        ,
                        emphasis:{
                            areaColor: '#274E9D',
                            borderColor:'#96D6FF',
                            borderWidth: 3
    
                        }
                    },
                    data: regionDataArray,
                },
                {//地图定位
                    type: 'scatter',
                    coordinateSystem: 'geo',
                    data: [],
                    symbolSize: [25.7,25.7],
                    symbolOffset: [0, '-15px'],
                    silent:true,//禁止鼠标触发图标事件
                    symbol: 'image://img/top1.svg'
                },
            ]
        })
    }
    展开全文
  • 本论文详细介绍了如何基于QGIS进行地图瓦片的渲染,并基于此开发出了一款切图工具。除此之外,本论文还详细研究了QGIS的工程体系结构,源码组成结构,重点对核心渲染层进行了详细剖析。阐明了基于QGIS进行瓦片渲染的...
  • 国际地图制图协会于1995年成立了一个地图可视委员会,并与计算机图形学会开始了“Carto-Project”,研究项目,该项目使图形学技术有效地应用在地理学及地图学领域,为空间信息可视提供了良好的技术支撑。
  • 国际地图制图协会于1995年成立了一个地图可视委员会,并与计算机图形学会开始了“Carto-Project”,研究项目,该项目使图形学技术有效地应用在地理学及地图学领域,为空间信息可视提供了良好的技术支撑。
  • 实现效果1.三个趋势图一起联动显示var myChart = echarts.init(document.getElementById('main'), 'infographic'); myChart.setOption(option = { tooltip:{ trigger: 'axis

    实现效果

    1.三个趋势图一起联动显示

    var myChart = echarts.init(document.getElementById('main'), 'infographic');       
                myChart.setOption(option = {
                    tooltip:{
                        trigger: 'axis',
                        formatter: function (params, ticket, callback) {
                            var titleData1;
                            var titleData2;
                            var titleData3;
                            var color1;
                            var color2;
                            var color3;
                            var time= params[0].name;
                            var titleHTML;
                            for (var i = 0; i < params.length; i++) {
                                titleData = params[i].data;
                               if ( params[i].seriesName==($.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_poorareacount'))){
                                    titleData1=(isNaN(String(titleData))?"--":(titleData));
                                    color1 = params[i].color;
                                }else if ( params[i].seriesName==($.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_dealingorder'))){
                                    titleData2=(isNaN(String(titleData))?"--":(titleData));
                                    color2 = params[i].color;
                                }else if ( params[i].seriesName==($.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_overtimeorder'))){
                                    titleData3=(isNaN(String(titleData))?"--":(titleData));
                                    color3 = params[i].color;
                                }
    
                            }
                            titleHTML=time+'<br><div style="display:inline-block;height:10px;width:10px;border-radius:5px;background-color:' + color1 + '"></div>&nbsp;&nbsp'
                                    + $.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_poorareacount')+' : ' +  titleData1+'<br><br>'
                                    +time+'<br><div style="display:inline-block;height:10px;width:10px;border-radius:5px;background-color:' + color2 + '"></div>&nbsp;&nbsp'
                                    +$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_dealingorder')+ ':' +  titleData2+'<br><br>'
                                    +time+'<br><div style="display:inline-block;height:10px;width:10px;border-radius:5px;background-color:' + color3 + '"></div>&nbsp;&nbsp'
                                    +$.i18n.prop('com_zte_lte_processingpoorqualitregion_header_poorqualitregion_overtimeorder')+ ':' +  titleData3;
                            return titleHTML;
                        }
    /*position: function (pos, params, dom, rect, size) {
          // 鼠标在左侧时 tooltip 显示到右侧,鼠标在右侧时 tooltip 显示到左侧。
                 var obj = {top: 60};
                       obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 5;
                             return obj;
                               } */
    //position: ['50%', '50%']   
                    }, 
    
                    axisPointer: {
                        link: {xAxisIndex: 'all'},
                        label: {
                            backgroundColor: '#777'
                        }
                    },
    
                    grid: [
                    {               
                        height: '20%',
                        top:'16%'
                    }, {                
                        top: '49%',   //44
                        height: '20%'  //20
                     },
                     {              
                        top: '80%',   //44
                        height: '20%'  //20
                     }
    
                    ],  
    
                    xAxis:[{
                        gridIndex: 0,//定义图标所在位置,不给默认为0,即第一个,而且必须按照从小到大的
                        type : 'category',
                        position:'bottom',
                        axisLine:{
                            lineStyle:{//坐标轴颜色
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },  
                        splitLine:{
                            show:false,//网格是否显示
                            interval: 0,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        axisLabel: {
                            show: true,
                            interval: 2,
                            textStyle: {
                                color: '#fff'
                            }
                        },
                        data : chartData.data1.x
                    },{
                        gridIndex: 1,
                        type : 'category',  
                        position:'bottom',
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },  
                        splitLine:{
                            show:false,//网格是否显示
                            interval: 0,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        axisLabel: {
                            show: true,
                            interval: 2,
                            textStyle: {
                                color: '#fff'
                            }
                        },
                        data : chartData.data2.x
                    },{
                        gridIndex: 2,
                        type : 'category',  
                        position:'bottom',
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },  
                        splitLine:{
                            show:false,//网格是否显示
                            interval: 0,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        axisLabel: {
                            show: true,
                            interval: 2,
                            textStyle: {
                                color: '#fff'
                            }
                        },
                        data : chartData.data3.x
                    },
                    {
                        gridIndex: 0,//定义图标所在位置,不给默认为0,即第一个,而且必须按照从小到大的
                        type : 'category',
                        position:'top',
                        axisLine:{
                            lineStyle:{//坐标轴颜色
                                type:'dashed',
                            }
                        },  
                        splitLine:{
                            show:false,//网格是否显示
                            interval: 0,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        // axisLabel: {
         //                    show: true,
         //                    textStyle: {
         //                        color: '#fff'
         //                    }
         //                },
                        // data : chartData.data1.x
                    },{
                        gridIndex: 1,
                        type : 'category',  
                        position:'top',
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },  
                        splitLine:{
                            show:false,//网格是否显示
                            interval: 0,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        // axisLabel: {
         //                    show: true,
         //                    textStyle: {
         //                        color: '#fff'
         //                    }
         //                },
                        // data : chartData.data2.x
                    },{
                        gridIndex: 2,
                        type : 'category',  
                        position:'top',
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },  
                        splitLine:{
                            show:false,//网格是否显示
                            interval: 0,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        // axisLabel: {
         //                    show: true,
         //                    textStyle: {
         //                        color: '#fff'
         //                    }
         //                },
                        // data : chartData.data3.x
                    }],
    
    
                    yAxis : [{
                        type : 'value', 
                        axisLabel:{
                            formatter:'{value}',
                            show: true,
                                textStyle: {
                                    color: '#fff'
                                }
                        },  
                        axisLine:{
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        splitNumber:5,  
                        splitLine:{
                            show:true,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        yAxisIndex:0,
                        min:0,
                        max:getMax(chartData.data1.y)
                    },
                    {
                        gridIndex: 1,
                        type : 'value', 
                        axisLabel:{
                            formatter:'{value}',
                            show: true,
                                textStyle: {
                                    color: '#fff'
                                }
                        },   
    
                        axisLine:{
                            lineStyle:{
                                type:'dashed'
                            }
                        },  
                        splitNumber:5,
                        splitLine:{
                            show:true,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        min:0,
                        max:getMax(chartData.data2.y)
                     },
                    {
                        gridIndex: 2,
                        type : 'value', 
                        axisLabel:{
                            formatter:'{value}',
                            show: true,
                                textStyle: {
                                    color: '#fff'
                                }
                        },   
    
                        axisLine:{
                            lineStyle:{
                                type:'dashed'
                            }
                        },  
                        splitNumber:5,
                        splitLine:{
                            show:true,
                            lineStyle:{
                                type:'dashed'
                            }
                        },
                        min:0,
                        max:getMax(chartData.data3.y)
                     }
                     ,{
                        type : 'value',
                        gridIndex: 0,
                        position:'right',   
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },
                    },
                    {
                        gridIndex: 1,
                        type : 'value', 
                        position:'right',
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },
                    },{
                        gridIndex: 2,
                        type : 'value', 
                        position:'right',
                        axisLine:{
                            lineStyle:{
                                type:'dashed',
                                color:"#FFFFFF"
                            }
                        },
                    }
    
                    ],  
    
                    series : [
                    {
                        name:chartData.data1.name,
                        type:'line',                         
                        smooth:true,
                        showAllSymbol: true,
                        data:chartData.data1.y
                    },                  
                    {
                        name:chartData.data2.name,
                        type:'line',                         
                        smooth:true, 
                        yAxisIndex:1,
                        xAxisIndex:1,
                        showAllSymbol: true,
                        data:chartData.data2.y
                    },                  
                    {
                        name:chartData.data3.name,
                        type:'line',                         
                        smooth:true, 
                        yAxisIndex:2,
                        xAxisIndex:2,
                        showAllSymbol: true,
                        data:chartData.data3.y
                    }
                    ]
                });
                if(allProvinceNames[0].indexOf(chartData.titleData.province)==-1){
                    analysis_type = 'province'
                    choseProvince=chartData.titleData.province
                    $('.right_info_box_button').removeClass('notAllowed').removeClass('analysisBackgroundNot')
                }
                return myChart;
            }
    展开全文
  • 这是我自己做的一套疫情实时数据项目,有地图、折线图、表格,该项目涵盖了大部分springboot项目实际开发所必需的技术,目前已经上线,公号【步尔斯特】获取源码,可直接拿走学习或复用,不谢。.........

    这是我自己做的一套实时数据项目,有地图、折线图、表格

    该项目涵盖了大部分springboot项目实际开发所必需的技术

    目前已经上线,🔍公号【步尔斯特】回复「疫情项目」获取源码,可直接拿走学习或复用,不谢。

    因为爬取的页面官网做了变更,所以会有一些小问题,需要自行处理。

    一、效果图

    请添加图片描述

    请添加图片描述

    在这里插入图片描述

    在这里插入图片描述

    二、技术栈

    1. 基础框架(springboot + mybatis + mybatis-plus)
    2. 缓存数据(redis)
    3. 国际化(一键切换不同语种)
    4. 定时任务(定时更新数据)
    5. 爬虫
    6. 加密
    7. 感知数据变更,进行通知推送
    8. 日志监控
    9. 数据计算和二次存储(为图表服务 - 比如趋势图)
    10. 数据展示和渲染 Thymeleaf Echarts
    11. 模拟http请求

    三、项目背景

    模拟疫情数据展示网站,做出一个完整的数据采集、数据存储、数据计算、数据展示的疫情数据系统。

    四、搜索引擎原理

    链接人和内容

    网页爬取 -》 网页去重 -》 网页分析 -》 内容保存(倒排索引)

    关键字查询 -》 关键字分析 -》 去匹配内容 -》 筛选出比如100条数据 -》 数据排序 (可口可乐的秘方)

    分类:
    通用型爬虫 和 垂直型爬虫

    疫情数据系统:
    数据采集 -》 数据存储 -》 数据计算 -》 数据展示

    五、数据分析

    5.1 分析数据源

    确认能够通过代码 获取到数据 (定位到具体的http请求)

    5.2 获取疫情数据

    1. 国内各省份表格数据-对应请求

    2. 对应的数据格式:json

    3. 国外表格数据-对应请求

    4. 国内趋势数据

    六、数据处理

    6.1 初识json

    json = javascript object notation (js对象表示法)
    独立于语言,具有自我描述性

    请添加图片描述

    Gson -> From Google

    new Gson().toJson(Object obj) 将对象转化为json字符串
    new Gson().fromJson(String jsonStr, T.class) 将json字符串转化为对象

    6.2 数据展示

    controller - service - handler

    数据加载到model中 返回给html渲染

    @Controller
    public class DataController {
    
        @Autowired
        private DataService dataService;
    
        @GetMapping("/")
        public String list(Model model) {
            List<DataBean> beanList = dataService.list();
            model.addAttribute("beanList", beanList);
            return "list";
        }
    }
    
    public interface DataService {
        
        List<DataBean> list();
    }
    
    
    @Service
    public class DataServiceImpl implements DataService {
    
        @Override
        public List<DataBean> list() {
            return MyDataHandler.getData();
        }
    }
    
    
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    
    <h2> 国内疫情情况如下 </h2>
    <br>
    
    <table>
        <thead>
        <tr>
            <th>地区</th>
            <th>现有</th>
            <th>累计</th>
            <th>治愈</th>
            <th>死亡</th>
        </tr>
        </thead>
    
        <tbody>
        <tr th:each="bean:${beanList}">
            <td th:text="${bean.area}">name</td>
            <td th:text="${bean.nowConfirm}">nowConfirm</td>
            <td th:text="${bean.confirm}">confirm</td>
            <td th:text="${bean.heal}">heal</td>
            <td th:text="${bean.dead}">dead</td>
        </tr>
        </tbody>
    </table>
    
    </body>
    </html>
    

    七、网络请求

    HTTP

    1. “应用层协议”
    2. 了解HTTP不同版本的演进
    3. 了解GET和POST请求的区别
        // 需要的参数url
        // 创建一个远程的连接对象  设置方法类型 GET
        // 设置相关参数    发送请求
        // 通过io接收数据后返回
    
        public static String doGet(String urlStr) {
            HttpURLConnection conn = null;
            InputStream is = null;
            BufferedReader br = null;
            StringBuilder result = new StringBuilder();
    
            try {
                // 创建远程url连接对象
                URL url = new URL(urlStr);
                // 打开一个连接
                conn = (HttpURLConnection) url.openConnection();
                // 设置为GET请求
                conn.setRequestMethod("GET");
                // 设置重要的参数  连接超时时间 和 读取超时时间
                // 超时时间  更多被距离影响   读取时间  更多被数据量影响
                conn.setConnectTimeout(15000);
                conn.setReadTimeout(60000);
    
                // header参数设置  可以不设置
                conn.setRequestProperty("Accept", "application/json");
    
                // 发送请求
                conn.connect();
    
                // 状态码  200  302  404  500 ?
                // 如果比较时  可能出现空指针  把确定的值放在前面  可以避免
                if (200 == conn.getResponseCode()) {
                    is = conn.getInputStream();
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    String line;
                    while ((line = br.readLine()) != null) {
                        result.append(line);
                    }
                } else {
                    System.out.println("error responseCode :"
                            + conn.getResponseCode());
                }
    
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
    
                    if (is != null) {
                        is.close();
                    }
    
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                conn.disconnect();
            }
    
            return result.toString();
        }
    

    八、数据存储

    8.1 Mybatis整合

    SSM的整合 -> 入门课的整合 -> mybatis-plus的整合

    明确数据结构 -> 创建mapper文件夹 -> 调用getData方法 将数据据存储到数据库中 -> 查询时从数据库中读取

    a) 引入依赖

            <!-- mybatis整合
                 mybatis-spring-boot-starter
                 mybatis-plus -boot-starter
                 mysql驱动-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.1</version>
            </dependency>
    
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.2.0</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
    
    

    b) 配置数据库连接参数

    spring.datasource.url=jdbc:mysql://localhost:3306/illness?characterEncoding=utf8
    spring.datasource.username=root
    spring.datasource.password=123456
    
    

    c) 创建数据库

    CREATE DATABASE /*!32312 IF NOT EXISTS*/`illness` /*!40100 DEFAULT CHARACTER SET utf8 */;
    
    USE `illness`;
    
    /*Table structure for table `epidemic` */
    
    DROP TABLE IF EXISTS `epidemic`;
    
    CREATE TABLE `epidemic` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `area` varchar(100) DEFAULT NULL,
      `confirm` int(11) DEFAULT NULL,
      `now_confirm` int(11) DEFAULT NULL,
      `dead` int(11) DEFAULT NULL,
      `heal` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=308 DEFAULT CHARSET=utf8;
    

    d) 编写类及文件夹

    将实体类对应到数据库的表中 属性和字段也需对应

    需注意 属性的命名为驼峰命名法

    如 nowConfirm 字段的命名是下划线分隔 如 now_confirm

    可以使用@TableName和@TableField等注解指定对应关系

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @TableName("epidemic")
    public class DataBean implements Serializable {
    
        // Alt + Insert 调用   安装插件
        private static final long serialVersionUID
                = 4938260405189292371L;
    
        // Alt + 7 查看类的方法
    
        // 地区  累计确诊人数  现有确诊人数   死亡人数  治愈人数
        private long id;
        private String area;
    //    @TableField("all_confirm")
        // 如果属性名和表中字段名  不一致  可以通过 TableField注解指定
        private int confirm;
        private int nowConfirm;
        private int dead;
        private int heal;
    }
    

    在主程序类上 增加@MapperScan注解 指定mapper类所在文件夹

    在此文件夹下 创建mapper类 实战中 如表名叫user mapper会命名为UserMapper

    @SpringBootApplication
    @MapperScan("com.duing.mapper")
    public class DataHandlerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DataHandlerApplication.class, args);
        }
    
    }
    
    
    public interface DataMapper extends BaseMapper<DataBean> {
    }
    
    

    创建service接口及其实现类

    整合mybatis-plus,用其提供的IService父接口 和 ServiceImpl实现父类

    public interface DataService extends IService<DataBean> {
    
    }
    
    
    @Service
    public class DataServiceImpl
            extends ServiceImpl<DataMapper,DataBean>
            implements DataService {
    
    }
    

    在controller中调用mybatis-plus实现的CRUD方法

    @Controller
    public class DataController {
    
        @Autowired
        private DataService dataService;
    
        @GetMapping("/")
        public String list(Model model) {
            List<DataBean> beanList = dataService.list();
            model.addAttribute("beanList", beanList);
            return "list";
        }
    }
    
    

    8.2 数据初始化及定时更新

    在数据查询前,先将数据存储到数据库中,我们称之为数据初始化

    可以在项目启动时,先采集一次数据存储到数据库中,然后再进行定期更新

    而项目启动时执行且只执行一次的逻辑,可以使用注解 @PostConstruct

    //  先将DataHandler托管到spring容器中  使用@Component
    //  以便于获取到 dataService对象
    @Component
    public class DataHandler {
    
        @Autowired
        private DataService dataService;
    
        // 数据初始化
        //   在服务器加载Servlet时运行  且 只运行一次
        @PostConstruct
        public void saveData() {
            List<DataBean> dataBeans = getData();
            // mybatis-plus提供了可用的方法
            // 删除全部数据  批量新增数据
            dataService.remove(null);
            dataService.saveBatch(dataBeans);
        }
    ...
    }
    

    定时更新其实也是定时任务

    可以通过注解@Scheduled + cron表达式来实现

    Scheduled 英文原意是调度的意思 意思是我们将某段逻辑 按照指定的时间间隔 进行调度 即为定时处理

    使用方式如下:

    首先在入口类上 打开定时任务开关 使用注解 @EnableScheduling

    @SpringBootApplication
    @MapperScan("com.duing.mapper")
    @EnableScheduling
    public class DataHandlerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DataHandlerApplication.class, args);
        }
    
    }
    

    然后在方法上 使用 @Scheduled 搭配cron表达式 决定方法多久执行一次

        // 定时更新
        @Scheduled(cron = "0 0 0/1 * * ? ")
        public void updateData(){
            System.out.println("要更新数据啦");
            System.out.println("当前时间:" + dateFormat.format(new Date()));
    
            List<DataBean> dataBeans = getData();
            dataService.remove(null);
            dataService.saveBatch(dataBeans);
        }
    

    其中cron表达式,是由6个表达不同时间单位的字段拼接而成

    可以通过在线cron表达式生成器来生成
    请添加图片描述
    cron表达式几乎可以满足所有定时执行的需求

    可以生成各类需求对应的表达式熟悉一下

    除此之外,@Scheduled还支持固定时间间隔的参数设置

    分别为 fixedRate 和 fixedDelay

    // 固定频率任务   以ms为单位  10000代表每10s执行一次
    //   使用时要注意间隔时间  和  任务消耗时间的  大小关系      
    //   如设置间隔10s  而方法需执行20s   那么方法会等待上一次执行完成才会执行  
    //   唤起方法真正的时间间隔为20s
    @Scheduled(fixedRate = 10000)
    public void updateData1(){}
    
    // 固定间隔任务   上一次执行结束后   再隔10s进行下一次执行
    // 如设置间隔10s  而方法需执行20s   那么会从上一次执行完成后开始计算  10s后开始下一次执行
    // 唤起方法真正的时间间隔为30s
    @Scheduled(fixedDelay = 10000)
    public void updateData2(){}
    

    九、图形化数据处理

    9.1 折线图

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script type="text/javascript" src="js/echarts.min.js"></script>
    </head>
    <body>
    
    <!--ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script th:inline="javascript">
    
        var dateStr = [[${dateList}]];
        var confirmStr = [[${confirmList}]];
        var suspectStr = [[${suspectList}]];
    
        // 基于准备好的dom  初始化实例
        var mychart = echarts.init(document.getElementById("main"));
        var option = {
            // 标题
            title:{
                text: '全国疫情新增趋势'
            },
            legend:{
                data:['新增确诊','新增疑似']
            },
            // x轴的数据
            xAxis:{
                data: dateStr
            },
            // y轴的数据类型
            yAxis:{
                type:'value'
            },
            series:[
                {
                    name: '新增确诊',
                    type: 'line',
                    data: confirmStr
                },
                {
                    name: '新增疑似',
                    type: 'line',
                    data: suspectStr
                }
            ]
        };
        // 将参数设置进去
        mychart.setOption(option);
    
    </script>
    
    </body>
    </html>
    

    9.2 地图

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script type="text/javascript" src="js/echarts.min.js"></script>
        <script type="text/javascript" src="js/china.js"></script>
    </head>
    <body>
    
    
    <!--ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 1000px;height:700px;"></div>
    <script th:inline="javascript">
    
        var dataStr1 = [[${mapData1}]];
        var dataStr2 = [[${mapData2}]];
        // 基于准备好的dom  初始化实例
        var mychart = echarts.init(document.getElementById("main"));
        var option = {
            title: {
                text: '疫情地图',
                subtext: '仅供参考',
                x: 'center'
            },
            tooltip: {
                trigger: 'item'
            },
            legend: {
                orient: 'vertical',
                left: 'left',
                data: ['现有确诊', '累计确诊']
            },
            visualMap: {
                type: 'piecewise',
                pieces: [
                    {min: 10000, max: 1000000, label: '10000人及以上', color: '#de1f05'},
                    {min: 1000, max: 9999, label: '1000-9999人', color: '#ff2736'},
                    {min: 500, max: 999, label: '500-999人', color: '#ff6341'},
                    {min: 100, max: 499, label: '100-499人', color: '#ffa577'},
                    {min: 10, max: 99, label: '10-99人', color: '#ffcea0'},
                    {min: 1, max: 9, label: '1-9人', color: '#ffe7b2'},
                    {min: 0, max: 0, label: '0人', color: '#e2ebf4'},
                ],
                calculate: true
            },
            series: [
                {
                    name: '现有确诊',
                    type: 'map',
                    mapType: 'china',
                    roam: false,
                    label: {
                        normal: {
                            position: 'center',
                            show: true
                        }
                    },
                    data: JSON.parse(dataStr1)
                },
                {
                    name: '累计确诊',
                    type: 'map',
                    mapType: 'china',
                    roam: false,
                    label: {
                        normal: {
                            position: 'center',
                            show: true
                        }
                    },
                    data: JSON.parse(dataStr2)
                }
            ]
        };
        // 将参数设置进去
        mychart.setOption(option);
    
    </script>
    
    </body>
    </html>
    

    9.3 拓展部分

    我们可以根据国内表格数据的处理方式、以及图形化数据的处理方式,举一反三的去处理海外数据,只要掌握了处理流程,其实是可以模拟腾讯新闻,将全部数据展示出来的,要注意的是,我们的项目是为了练习springboot+mybatis+thymeleaf+echarts的使用,了解http请求+json数据处理+定时任务等等功能是如何实现的,那么对数据采集方面要慎重,尽量只采集需要的少部分数据,并且控制请求次数和请求频率,一定要做到“友好访问”。

    十、页面数据处理

    Jsoup(Ji soup 鸡汤)----页面解析器

    解析一个HTML文档的方式如下:
    String html = "<html><head><title>First parse</title></head>"
    + "<body><p>Parsed HTML into a doc.</p></body></html>";
    
    Document doc = Jsoup.parse(html);
    
    解析器能够尽最大可能从你提供的HTML文档中创建出一个干净的解析结果,无论HTML的格式是否完整。
    比如它可以处理:
    
    1)没有关闭的标签 
       <p>Lorem <p>Ipsum  
       可以解析成
       <p>Lorem</p> <p>Ipsum</p>
    2)隐式标签 (补充没有显示的标签)
       它可以自动将 <td>Table data</td> 包装成 <table><tr><td>...
    3)创建可靠的文档结构  
       html标签包含head 和 body,且在head只出现恰当的元素
       
    文档的对象模型                
    1)文档由多个ElementsTextNodes组成
    2)继承结构如下:Document继承Element继承Node. TextNode继承 Node.
    3)一个Element包含一系列的子节点,并拥有一个父Element。他们还唯一提供了一个子元素过滤列表。
    

    十一、国际化

    根据不同的用户群,显示不同的语言,此功能叫做国际化,如丁香医生页面切换语种的功能。

    要想实现动态显示不同语言,首先要将页面中的数据转为动态显示,放在配置文件中读取

    创建list.properties

    list.title=步尔斯特
    list.h2=国内疫情情况如下
    list.table.name1=地区
    list.table.name2=现有确诊
    list.table.name3=累计确诊
    list.table.name4=治愈
    list.table.name5=死亡
    
    

    我们将list.properties放在i18n的文件夹下,然后在application.properties中设置好指定配置

    spring.messages.basename=i18n.list
    

    这样就可以再创建一个list_en_US.properties文件,内容如下

    list.title=burst
    list.h2=As Follows
    list.table.name1=Area
    list.table.name2=Now Confirm
    list.table.name3=Confirm
    list.table.name4=Heal
    list.table.name5=Dead
    

    对应的list.html页面修改如下

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title th:text="#{list.title}">Title</title>
        <link rel="stylesheet" th:href="@{css/bootstrap.css}">
    </head>
    <body>
    
    
    <h2 th:text="#{list.h2}"> 国内疫情情况如下 </h2>
    <br>
    
    <table class="table table-hover">
        <thead>
        <tr>
            <th><p th:text="#{list.table.name1}">地区</p></th>
            <th><p th:text="#{list.table.name2}">现有</p></th>
            <th><p th:text="#{list.table.name3}">累计</p></th>
            <th><p th:text="#{list.table.name4}">治愈</p></th>
            <th><p th:text="#{list.table.name5}">死亡</p></th>
        </tr>
        </thead>
    
        <tbody>
        <tr th:each="bean:${beanList}">
            <td th:text="${bean.area}">name</td>
            <td th:text="${bean.nowConfirm}">nowConfirm</td>
            <td th:text="${bean.confirm}">confirm</td>
            <td th:text="${bean.heal}">heal</td>
            <td th:text="${bean.dead}">dead</td>
        </tr>
        </tbody>
    
    </table>
    
    </body>
    </html>
    

    当我们运行项目后,通过浏览器更改语言,就可以切换成不同语种的显示了。

    以chrome为例,将中文置顶,则显示中文,将英语(美国)置顶,则显示英文,这里要注意,如果没有英语(美国)这个语言,可以在底下的添加语言中,先搜索后添加。

    那是如何实现切换的呢,当我们调出控制台,比对两笔请求的http,可以发现请求头中Accept-Language参数是不同的,请求中文时以zh-CN开头,请求英文时以en-US开头,如果你对其他语种感兴趣,也可以看一下其他语种的简称。

    但是通过浏览器切换仍有些麻烦,所以我们尝试在页面中添加切换按钮

    当我们设置了参数lan用来区分不同语种时,需要使用一个处理器来接收语种参数

    然后将处理器注入到spring容器中

    同时增加一个list_zh_CN.properties文件,声明各字段的中文值
    再次启动项目,就可在页面中进行中英文切换了。

    十二、Redis的使用

    三大客户端框架: Jedis Redission Lettuce

    其中spring-data-redis 是将redis整合在spring中使用的jar包

    在springboot2.0以后的版本 将原本的jedis升级成Lettuce 而本质上是一种连接池的封装

    redis数据的存储,可以在项目启动时存储,另外可以在请求第一次被调用时存储(懒加载)
    请求 -》 redis(存在 -》 直接返回,不存在 -》 mysql中查询 -》 存储到redis中 -》 返回)
    -》 mysql(存在 ,不存在 -》 发送http请求 -》 数据清洗和计算后存储 -》 返回)

    以折线图数据为例
    在处理数据的过程中,有三种数据形态

    1)url直接返回的原始数据
    2)第一次解析后处理的 List<GraphBean>
    3) echarts的直观需要的三个list, 一个对应x轴,两个对应y轴

    第一种数据重要,但一般不放在redis中存储,甚至不放在mysql中。

    展开全文
  • 地图是人类文化的杰作,它融科学、艺术于一体,作为描述、研究人类生存环境的一种信息载体是人类生产与生活中不可缺少的一种工具。”这是陈述彭院士为《中国地图学年鉴》作序的...地图地图可视的结果,地图...
  • echarts 国际化

    千次阅读 2021-11-08 11:40:59
    echarts 国际化
  • 浅谈地图可视

    千次阅读 2020-05-01 22:56:15
    地图可视在我们生活中无处不在,开车导航,寻找某个地方需要导航等,下面浅谈一下地图的一些知识及应用。 当前互联网地图的坐标系现状 地球坐标 (WGS84) 国际标准,从专业GPS 设备中取出的数据的坐标系 国际...
  • 在此基础上提出了一种二维高精地图实现方案,利用无人机航拍、差分定位技术、遥感、GIS和互联网等相关技术,形成从数据采集、数据处理与地图制图、地图渲染、地图服务发布到平台功能设计的完整技术服务方案,为智能...
  • ☀️ 我的主页:YYDataV☀️欢迎点赞 ???? 收藏 ⭐留言,欢迎多多交流 目录 ❤️效果展示❤️ ...近年来,数据可视大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的 “酷炫吊炸天” 的霸
  • 由于版本3与4在API等存在较大区别,就不一一列举,详细区别看官方解释arcgis for js4.7版本能够自动创建layer、graphs等类,而不像3.24版本需要在图形渲染前重新new 新的类。然而,查找大量文件资料,网上有关ArcGIS...
  • 关于GMTCGMTC全球大前端技术大会是由InfoQ举办的年度前端技术盛会,主要面向各行业对前端、移动感兴趣的中高端技术人员。6月20日-21日,GMTC将在北京国际会议...
  • 命令进入项目目录,执行以下命令安装vue 国际化插件vue-i18n npm install vue-i18n --save 2. 项目增加国际化翻译文件 在项目的src下添加lang文件夹增加中文翻译文件(zh.js)以及英文翻译文件(en.js),里面...
  • 由于版本3与4在API等存在较大区别,就不一一列举,详细区别看[官方解释]arcgis for js4.7版本能够自动创建layer、graphs等类,而不像3.24版本需要在图形渲染前重新new 新的类。然而,查找大量文件资料,网上有关...
  • 一个React组件,使用 / WebGL进行3D渲染,以球形投影形式表示3维地球上的数据可视层。 查看示例: () ( ) 突出显示链接( 来源) choropleth ( 来源) 高架多边形( 来源) 空心球( 来源) 路径线( 源) ...
  • github地址:https://github.com/antvis/L7 ... L7 地理空间数据可视分析引擎 L7 是由蚂蚁金服 AntV 数据可视团队推出的基于 WebGL 的开源大规模地理空间数据可视分析开发框架。L7 中的 L 代表 Location,7 代表...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,088
精华内容 1,235
关键字:

地图渲染国际化