echarts implements pseudo-3D maps, ripples of provincial capital coordinates, automatic carousels, and data linkage

Rendering:


Achieved effects:

  1. Pseudo 3D effect map
  2. Provincial capital coordinates display punctuation points with a ripple effect
  3. Area covered by mouse, zone and ripple highlighting
  4. All areas on the map rotate according to time intervals
  5. When clicked or rotated, the area will be refreshed together with the data of all other tables to display the statistical data of different regions.

Complete JS code:

let regions = [];
let orgRegions = [];//Initial state color
var selectedAreaName = ""; // Currently selected/carousel city
var mapName = 'NX';
var geoJson = mapData;

//Punctuation points for ordinary ripple effects
function convertNormalLianyiData(mapData) {<!-- -->
    var res = [];
    for (var i = 0; i < mapData.features.length; i + + ) {<!-- -->
        var prop = mapData.features[i].properties;
        //var geoCoord = prop.center;// The punctuation point is located in the regional capital
        var geoCoord = prop.centroid;//The punctuation point is located in the center of the region
        if (geoCoord & amp; & amp; prop.name != selectedAreaName) {<!-- -->
            res.push({<!-- -->
                name: prop.name,
                //After the horizontal and vertical coordinates, splice the height coordinate, the default is 10
                value: geoCoord.concat(100),
                adcode: prop.adcode,
            });
        }
    }
    return res;
}
// Select the punctuation point of the ripple effect in the area
function convertSelectedLianyiData(mapData) {<!-- -->
    var res = [];
    for (var i = 0; i < mapData.features.length; i + + ) {<!-- -->
        var prop = mapData.features[i].properties;
        //var geoCoord = prop.center;// The punctuation point is located in the regional capital
        var geoCoord = prop.centroid;//The punctuation point is located in the center of the region
        if (geoCoord & amp; & amp; prop.name == selectedAreaName) {<!-- -->
            res.push({<!-- -->
                name: prop.name,
                //After the horizontal and vertical coordinates, splice the height coordinate, the default is 10
                value: geoCoord.concat(100),
                adcode: prop.adcode,
            });
        }
    }
    return res;
}

for (i = 0; i < geoJson.features.length; i + + ) {<!-- -->
    let cityInfo = {<!-- -->
        name: geoJson.features[i].properties.name,
        adcode: geoJson.features[i].properties.adcode,
    }
    city.push(cityInfo);
}
for (i = 0; i < city.length; i + + ) {<!-- -->
    regions.push({<!-- -->
        name: city[i].name,
        adcode: city[i].adcode,
        itemStyle: {<!-- -->
            color: color[i % 10]
        },
    });
    orgRegions.push({<!-- -->
        name: city[i].name,
        adcode: city[i].adcode,
        itemStyle: {<!-- -->
            color: color[i % 10]
        },
    });
}

// Overlay layers to create a three-dimensional effect
let addShadow = function (geo) {<!-- -->
    let max = 30;
    let upper = '#2768b6';
    let deeper = '#0e408a';
    for (let i = 0; i < max; i + + ) {<!-- -->
        geo.push({<!-- -->
            type: 'map',
            map: mapName,
            // map label
            label: {<!-- -->
                show: false
            },
            layoutCenter: ['50%', '50%'],
            layoutSize: '80%',
            zlevel: -1 * i,
            itemStyle: {<!-- -->
                normal: {<!-- -->
                    color: 'rgba(39, 104,190, 1)',
                    borderColor: '#AEFBFF',
                    borderWidth: 1,
                    opacity: 0.8,
                    shadowColor: i < max / 2 ? upper : deeper,
                    shadowOffsetX: i * -1,
                    shadowOffsetY: i * 1.5,
                    shadowBlur: 1
                },
                emphasis: {<!-- -->
                    show: false,
                    color: "#fff",
                    //The color of the selected map area
                    areaColor: "rgba(0,254,233,0.6)",
                },
            },
            aspectScale: 1, //aspect ratio
            selectedMode: false, //Whether multiple areas are allowed to be selected
        });
    }
};
let geo = [
    {<!-- -->
        type: 'map',
        map: mapName,
        itemStyle: {<!-- -->
            normal: {<!-- -->
                areaColor: {<!-- -->
                    type: "linear",
                    x: 1200,
                    y: 0,
                    x2: 0,
                    y2: 0,
                    colorStops: [
                        {<!-- -->
                            offset: 0,
                            color: "rgba(3,27,78,0.75)", // color at 0%
                        },
                        {<!-- -->
                            offset: 1,
                            color: "rgba(58,149,253,0.75)", // color at 50%
                        },
                    ],
                    global: true, //default is false
                },
                borderColor: "#fff",
                borderWidth: 0.2,
            },
            emphasis: {<!-- -->
                show: false,
                color: "#fff",
                //The color of the selected map area
                areaColor: "rgba(0,254,233,0.6)",
            },
        },
        // map label
        label: {<!-- -->
            show: false
        },
        layoutCenter: ['50%', '50%'],
        layoutSize: '80%',
        zlevel: 0,
        aspectScale: 1, //aspect ratio
        selectedMode: false, //Whether multiple areas are allowed to be selected
    }
];
addShadow(geo);

option = {<!-- -->
    tooltip: {<!-- -->
        show: true, // prompt box
        trigger: 'item',
        formatter: function (params) {<!-- -->
            return params.name;
        }
    },
    geo: geo,
    series: [
        {<!-- -->
            type: 'map',
            map: mapName,
            itemStyle: {<!-- -->
                normal: {<!-- -->
                    areaColor: {<!-- -->
                        type: "linear",
                        x: 1200,
                        y: 0,
                        x2: 0,
                        y2: 0,
                        colorStops: [
                            {<!-- -->
                                offset: 0,
                                color: "rgba(3,27,78,0.75)", // color at 0%
                            },
                            {<!-- -->
                                offset: 1,
                                color: "rgba(58,149,253,0.75)", // color at 50%
                            },
                        ],
                        global: true, //default is false
                    },
                    borderColor: "#fff",
                    borderWidth: 0.2,
                },
                emphasis: {<!-- -->
                    show: false,
                    color: "#fff",
                    //The color of the selected map area
                    areaColor: "rgba(0,254,233,0.6)",
                },
            },
            // map label
            label: {<!-- -->
                show: false
            },
            zlevel: -1,
            aspectScale: 1, //aspect ratio
            selectedMode: false, //Whether multiple areas are allowed to be selected
            data: convertNormalLianyiData(mapData),
        },
        // Ripple effect in normal state
        {<!-- -->
            // Public configuration items for animated scatter points
            type: 'effectScatter',
            //Coordinate system to use
            coordinateSystem: 'geo',
            // ripple effect
            rippleEffect: {<!-- -->
                //Ripple effects
                color: '#f29130',
                period: 4, //Animation time, the smaller the value, the faster it will be
                brushType: 'stroke', //Ripple drawing method stroke, fill
                scale: 10 //The maximum limit of the corrugated ring. The larger the value, the greater the ripples.
            },
            symbol: 'circle',
            symbolSize: 15,
            label: {<!-- -->
                normal: {<!-- -->
                    show: true,
                    position: 'bottom', //display position
                    offset: [5, 0], //Offset setting
                    formatter: function (params) {<!-- -->
                        //circle displays text
                        return params.data.name;
                    },
                    textStyle: {<!-- -->
                        fontSize: 15,
                        color: 'white',
                        borderWidth: 15
                        //borderColor: 'orange'
                    }
                },
                emphasis: {<!-- -->
                    show: true
                }
            },
            //City coordinate style
            itemStyle: {<!-- -->
                normal: {<!-- -->
                    color: {<!-- -->
                        type: 'linear',
                        x: 0,
                        y: 0,
                        x2: 0,
                        y2: 1,
                        colorStops: [
                            {<!-- -->
                                offset: 0,
                                color: '#fbc05d' // Color at 0%
                            },
                            {<!-- -->
                                offset: 1,
                                color: '#ee8125' // Color at 100%
                            }
                        ],
                        global: false // Default is false
                    }
                }
            },
            data: convertNormalLianyiData(mapData)
        },
        // Ripple effect in selected state
        {<!-- -->
            // Public configuration items for animated scatter points
            type: 'effectScatter',
            //Coordinate system to use
            coordinateSystem: 'geo',
            // ripple effect
            rippleEffect: {<!-- -->
                //Ripple effects
                color: '#1a6198',
                period: 4, //Animation time, the smaller the value, the faster it will be
                brushType: 'fill', //Ripple drawing method stroke, fill
                scale: 15 //The maximum limit of the corrugated ring. The larger the value, the greater the ripples.
            },
            symbol: 'circle',
            symbolSize: 15,
            label: {<!-- -->
                normal: {<!-- -->
                    show: true,
                    position: 'bottom', //display position
                    offset: [5, 0], //Offset setting
                    formatter: function (params) {<!-- -->
                        //circle displays text
                        return params.data.name;
                    },
                    textStyle: {<!-- -->
                        fontSize: 15,
                        color: 'white',
                        borderWidth: 15
                        //borderColor: 'orange'
                    }
                },
                emphasis: {<!-- -->
                    show: true
                }
            },
            //City coordinate style
            itemStyle: {<!-- -->
                normal: {<!-- -->
                    color: {<!-- -->
                        type: 'linear',
                        x: 0,
                        y: 0,
                        x2: 0,
                        y2: 1,
                        colorStops: [
                            {<!-- -->
                                offset: 0,
                                color: '#fbc05d' // Color at 0%
                            },
                            {<!-- -->
                                offset: 1,
                                color: '#ee8125' // Color at 100%
                            }
                        ],
                        global: false // Default is false
                    }
                }
            },
            data: convertSelectedLianyiData(mapData)
        }
    ]
};

function buildOption(context, eChartData, chartOption, echarts) {<!-- -->
    debugger
    echarts.registerMap(mapName, geoJson);
    startLunbo(context, true);
    // Broadcast Ningxia immediately during initialization
    if (context.vueContext) {<!-- -->
        let selectedCode = '640000';
        let msg = {<!-- -->
            //P_ND: "20220101",
            CZQH: selectedCode
        }
        context.vueContext.emit('sendMsg', msg)
    }
    chartOption = option;
    return chartOption;
};
var myChart;
var interval;
function onRender(context, eChartData, container, obj, instance) {<!-- -->
    debugger
    myChart = instance;

    // The carousel ends when the mouse is moved into it, and the carousel starts when the mouse is moved out.
    myChart.off('mouseover')
    myChart.on("mouseover", (params) => {<!-- -->
        clearInterval(interval);
        clearAllStyle();
        //Record the selected/carousel area
        selectedAreaName = params.name;
        resetScatter();
        setSelectedStyle();
        myChart.setOption(option);
    });
    myChart.off('mouseout')
    myChart.on("mouseout", () => {<!-- -->
        debugger

        selectedAreaName = "";
        resetScatter();

        //Start carousel function
        clearInterval(interval);
        clearAllStyle();
        startLunbo(context);
        //Record the selected/carousel area



        myChart.setOption(option);


    });
    myChart.off('click')
    myChart.on("click", function (params) {<!-- -->
        // debugger

        //Click the division code of the area
        let changeCode = params.region.adcode;
        if (changeCode & amp; & amp; context.vueContext) {<!-- -->
            let msg = {<!-- -->
                //P_ND: "20220101",
                CZQH: changeCode
            }
            context.vueContext.emit('sendMsg', msg)
        }

        //Id of dashboard
        // let dashboardGuid = window['nvwa-dataanalyze-dashboard_0000018A39DD52A99D9A26069BCED0DE'].dashboardGuid;

        console.log('Click to get Params', params);
    });
};
/**
 *
 * @param context chart context parameters
 * @param init Whether it is the first load: true: open the selection immediately, false: open the selection after a time interval
 */
function startLunbo(context, init = false) {<!-- -->
    // debugger
    //Retain the subscript and color information of the currently selected city
    const lastSelectedArea = {<!-- -->
        index: 0,
        color: 'rgba(39, 104,190, 1)',
    };
    let _context = context;
    // Start carousel, -1 means displaying provincial information
    let mapIndex = -1;
    interval = setInterval(() => {<!-- -->
        if (mapIndex == -1) {<!-- -->
            clearAllStyle();
            if (!init) {<!-- -->
                // Broadcast Ningxia
                if (_context.vueContext) {<!-- -->
                    let selectedCode = '640000';
                    let msg = {<!-- -->
                        //P_ND: "20220101",
                        CZQH: selectedCode
                    }
                    _context.vueContext.emit('sendMsg', msg)
                }
            }
            mapIndex + + ;

        } else {<!-- -->
            regions[lastSelectedArea.index].itemStyle.color = lastSelectedArea.color;
            let finishLunbo = (mapIndex == mapData.features.length);
            mapIndex = mapIndex % mapData.features.length;
            lastSelectedArea.index = mapIndex;
            lastSelectedArea.color = regions[lastSelectedArea.index].itemStyle.color;
            //The color of the selected region in the current carousel
            regions[mapIndex].itemStyle.color = '#ffffff';
            // regions[mapIndex].itemStyle.color = '#e2cd00';
            //Record the selected/carousel area
            selectedAreaName = regions[mapIndex].name;

            // Broadcast the fiscal division of the current rotation
            if (_context.vueContext) {<!-- -->
                let selectedCode = regions[mapIndex].adcode;
                let msg = {<!-- -->
                    //P_ND: "20220101",
                    CZQH: selectedCode
                }
                _context.vueContext.emit('sendMsg', msg)
            }
            if (finishLunbo == true) {<!-- -->
                // All polling is completed, restart from the provincial level, and the subscript returns to -1
                mapIndex = -1;
            } else {<!-- -->
                mapIndex + + ;
            }

            for (let i = 0; i < option.geo.length; i + + ) {<!-- -->
                const geoItem = option.geo[i];
                geoItem.regions = regions;
            }

            resetScatter();
        }

        myChart.setOption(option);
    }, 15000); // Modify the frequency of carousel here (unit: milliseconds)
}
// Clear all selected regions' styles
function clearAllStyle() {<!-- -->
    // debugger
    for (let i = 0; i < option.geo.length; i + + ) {<!-- -->
        const geoItem = option.geo[i];
        geoItem.regions = orgRegions;
    }
    regions = [];
    for (i = 0; i < city.length; i + + ) {<!-- -->
        regions.push({<!-- -->
            name: city[i].name,
            adcode: city[i].adcode,
            itemStyle: {<!-- -->
                color: color[i % 10]
            },

        });
    }
    myChart.setOption(option);
}
//Reset ripple effect
function resetScatter() {<!-- -->
    option.series[1].data = convertNormalLianyiData(mapData);
    option.series[2].data = convertSelectedLianyiData(mapData);
}
//Set the style of the selected area
function setSelectedStyle() {<!-- -->
    //debugger
    //The color of the selected area
    let selectedStyle = {<!-- -->
        color: "rgba(0,254,233,0.6)",
    }
    for (let i = 0; i < regions.length; i + + ) {<!-- -->
        const selectedItem = regions[i];
        if (selectedItem.name == selectedAreaName) {<!-- -->
            selectedItem.itemStyle = selectedStyle;
            break;
        }
    }
    for (let i = 0; i < option.geo.length; i + + ) {<!-- -->
        const geoItem = option.geo[i];
        geoItem.regions = regions;
    }
}