let geoJSON const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://img.58h.com.cn/json-174251994545205.json', false); xhr.onload = function () { if (xhr.status >= 200 && xhr.status < 300) { // 请求成功,处理响应 // console.log('Response:', JSON.parse(xhr.responseText)); geoJSON = JSON.parse(xhr.responseText) } else { // 处理错误 console.error('Error:', xhr.statusText); } }; xhr.send(); const pointOption = [ { name: '南京', value: [118.796, 32.0583] }, { name: '西安', value: [108.94, 34.341101] }, { name: '上海', value: [121.474, 31.230001] }, { name: '重庆', value: [106.552003, 29.562696] }, { name: '西宁', value: [101.778, 36.6172] }, { name: '北京', value: [116.407001, 39.9046] }, { name: '广州', value: [113.264999, 23.129101] }, { name: '长春', value: [125.32, 43.82] }, ] const lineOption = [] const talentList = [ { name: '博士研究生', value: '3', unit: '人' }, { name: '硕士研究生', value: '21', unit: '人' }, { name: '副高及以上', value: '36', unit: '人' } ] const lastPoint = { name: '绵阳经开区', value: [104.774522, 31.399113], lineStyle: { color: '#FF6C66' } } const colorList = ['#D88BFF', '#5abead', '#66FFFF', '#48D5FF', '#FFE73D', '#66FFFF'] pointOption.map((item, index) => { item.lineStyle = { color: colorList[index % colorList.length] } item.coords = [item.value, lastPoint.value] lineOption.push(item) }) pointOption.push(lastPoint) const option = { tooltip: { trigger: 'item', position: function (point, params, dom, rect, size) { var x = 0 // x坐标位置 var y = 0 // y坐标位置 // 当前鼠标位置 var pointX = point[0] var pointY = point[1] // 提示框大小 var boxWidth = size.contentSize[0] / 2 var boxHeight = size.contentSize[1] + 50 // boxWidth > pointX 说明鼠标左边放不下提示框 if (boxWidth > pointX) { x = pointX + 10 } else { // 左边放的下 x = pointX - boxWidth - 10 } // boxHeight > pointY 说明鼠标上边放不下提示框 if (boxHeight > pointY) { y = 5 } else { // 上边放得下 y = pointY - boxHeight } return [x, y] }, show: true, enterable: true, borderWidth: 0, textStyle: { fontSize: 0, color: 'transparent' }, backgroundColor: 'transparent', extraCssText: 'box-shadow: 0 0 0 transparen', padding: 0, triggerOn: 'none', formatter: params => { const { componentType, data, dataIndex } = params if (componentType === 'series' && data) { let tipHtml = '<div class="tipHtml" style="width:200px;height:135px;background:url(https://img.isqqw.com/profile/upload/2025/03/11/b755154a-eb2b-4ed3-962b-fa27e35da717.png) no-repeat left top;background-size:100% 100%;color:#fff;">' tipHtml += `<h3 class="tipHtml-title" style="height: 31px; padding: 12px 0; font-weight: bold; font-size: 16px; color: #19ecff; line-height: 15px; text-align: center;">人才引进情况</h3>` tipHtml += `<div class="tipHtml-bottom" style="display:flex; justify-content: space-between; padding: 0 9px 9px;">` for (let i = 0; i < talentList.length; i++) { const item = talentList[i] tipHtml += `<div class="tipHtml-bottom-item" style="width:54px; height: 30px;"> <div class="tipHtml-bottom-item-value" style="display: flex; justify-content: center;"> <span style="height: 20px; font-weight: bold; font-size: 12px; color: #66ffff; line-height: 20px; text-align: center;">${Math.ceil(item.value * (0.5 + dataIndex))}</span> <span style=" font-size: 12px; color: #66ffff; line-height: 25px;">${item.unit}</span> </div> <div class="tipHtml-bottom-item-label" style="height: 25px; font-size: 12px; color: #ffffff; line-height: 25px; text-align: center;">${item.name}</div> </div>` } tipHtml += `<img class="tipHtml-icon" src="https://img.58h.com.cn/image-174252006246339.png" style=" position: absolute; bottom: -35px; left: 50%; width: 21px; height: 24px; animation: jumpBoxHandler 1.8s infinite;">` tipHtml += '</div>' return tipHtml } } }, geo: [ { map: 'china', zoom: 1.5, z: 70, top: '150px', selected: false, label: { show: false, padding: 4, color: '#ddd', fontFamily: 'pf-zh' }, itemStyle: { areaColor: { image: 'https://img.58h.com.cn/image-174251997924978.png', repeat: 'repeat' }, borderColor: 'rgba(147,234,245,.5)', borderWidth: 1 }, emphasis: { disabled: true }, regions: [ { name: '南海诸岛', emphasis: { disabled: true }, itemStyle: { borderWidth: 1 } } ] }, { type: 'map', map: 'china', zoom: 1.52, z: 60, top: '150px', selected: false, // left: '15.8%', itemStyle: { areaColor: '#177db7' }, emphasis: { disabled: true }, regions: [ { name: '南海诸岛', emphasis: { disabled: true }, itemStyle: { areaColor: 'transparent', borderWidth: 0 } } ] } ], series: [ // 水波圈效果 { type: 'effectScatter', coordinateSystem: 'geo', showEffectOn: 'render', z: 90, rippleEffect: { period: 12, scale: 4, brushType: 'fill' }, label: { formatter: '{b}', position: 'top', offset: [0, -10], color: '#1DE9B6', show: true, fontSize: 12 }, itemStyle: { color: value => { // console.log(value, 'lll') return value.data.lineStyle.color || '#5abead' }, shadowBlur: 10, shadowColor: '#333' }, symbolSize: 8, data: pointOption }, // 流转线效果 { type: 'lines', z: 100, effect: { show: true, period: 8, // 箭头指向速度,值越小速度越快 trailLength: 0.4, // 特效尾迹长度[0,1]值越大,尾迹越长重 symbol: 'arrow', // 箭头图标 symbolSize: 5 // 图标大小 }, lineStyle: { color: '#1DE9B6', width: 1, // 线条宽度 opacity: 0.1, // 尾迹线条透明度 curveness: 0.3 // 尾迹线条曲直度 }, data: lineOption } ] } echarts.registerMap('china', geoJSON) let timer let index = 0 const onHighlight = () => { return setInterval(() => { if (index < pointOption.length - 1) { index++ } else { index = 0 } myChart.dispatchAction({ type: 'showTip', seriesIndex: 0, dataIndex: index }) }, 3600) } timer = onHighlight() myChart.on('mouseover', params => { timer && clearInterval(timer) }) myChart.on('mouseout', params => { timer && clearInterval(timer) timer = onHighlight() }) function loadCssCode(code) { var style = document.createElement('style') style.type = 'text/css' style.rel = 'stylesheet' try { //for Chrome Firefox Opera Safari style.appendChild(document.createTextNode(code)) } catch (ex) { //for IE style.styleSheet.cssText = code } var head = document.getElementsByTagName('head')[0] head.appendChild(style) } loadCssCode('@keyframes jumpBoxHandler {0% {transform: translate(0px, 0px);} 50% {transform: translate(0px, 20px);} 100% {transform: translate(0px, 0px);}}')