bonus-ui/src/views/screen/wsScreenWidescreen/components/center/index-old-3d.vue

414 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="middle-warp">
<div class="top-btns">
<div class="btn" :class="{ active: btnIndex == 1 }" @click="handleBtn(1)">总价值数</div>
<div class="btn" :class="{ active: btnIndex == 2 }" @click="handleBtn(2)">在库装备数</div>
<div class="btn" :class="{ active: btnIndex == 3 }" @click="handleBtn(3)">机械化率</div>
</div>
<!-- 外层容器用于加阴影 -->
<div class="map-wrapper">
<!-- 倾斜层实现 3D 倾斜效果 -->
<div class="map-tilt">
<div ref="mapChart" class="map-container"></div>
</div>
</div>
<!-- 点击城市显示详情 -->
<div
v-if="selectedCity && btnIndex == 1"
class="city-tooltip"
:style="{ left: tooltipPos.x + 25 + 'px', top: tooltipPos.y + 25 + 'px' }"
>
<div class="city-name">{{ selectedCity.cityName }}</div>
<div
>装备价值: <span class="num">{{ selectedCity.totalValue }}</span
><span class="unit"> 万元</span></div
>
<div
>装备数量: <span class="num">{{ selectedCity.totalEquipmentQuantity }}</span
><span class="unit"> 台</span></div
>
<div
>配置率: <span class="num">{{ selectedCity.configRate || 0 }}</span
><span class="unit"> %</span></div
>
<div
>线路数量: <span class="num">{{ selectedCity.lineNum }}</span
><span class="unit"> 台</span></div
>
<div
>变电数量: <span class="num">{{ selectedCity.substationNum }}</span
><span class="unit"> 台</span></div
>
<div
>电缆数量: <span class="num">{{ selectedCity.cableNum }}</span
><span class="unit"> </span></div
>
</div>
</div>
</template>
<script>
import 'echarts-gl'
import * as echarts from 'echarts'
import anhuiMapJson from '../anhui.json'
import labelBg from '../../img/value-bg.png'
import { getUnitEquipmentConfigurationApi, getEquipmentNumberApi, getMechanizationRateApi } from '@/api/wsScreen'
export default {
data() {
return {
btnIndex: 1,
myChart: null,
selectedCity: null,
tooltipPos: { x: 0, y: 0 },
cityData: [
// 调试数据
// {
// cityName: '合肥市',
// deptName: '安徽送变电工程有限公司',
// value: [117.227239, 31.820586, 100],
// totalValue: 100,
// totalEquipmentQuantity: 100,
// configRate: 100,
// lineNum: 100,
// substationNum: 100,
// cableNum: 100,
// },
// {
// cityName: '芜湖市',
// deptName: '芜湖送变电工程有限公司',
// value: [118.62807, 31.68005, 100],
// totalValue: 100,
// totalEquipmentQuantity: 100,
// configRate: 100,
// lineNum: 100,
// substationNum: 100,
// cableNum: 100,
// },
],
}
},
created() {
this.getInfo()
// setTimeout(() => {
// console.log('🚀 ~ 地图数据 ~ this.cityData:', this.cityData)
// this.initMap()
// }, 300)
},
methods: {
handleBtn(index) {
this.btnIndex = index
this.cityData = []
this.getInfo()
},
async getInfo() {
try {
let res = null
if (this.btnIndex == 1) {
res = await getUnitEquipmentConfigurationApi()
if (!res.data) return
this.cityData = res.data.map((item) => {
let value = item.location.split(',')
value.push(item.totalValue)
// console.log('🚀 ~ getInfo ~ value:', value)
return {
...item,
value,
}
})
} else if (this.btnIndex == 2) {
res = await getEquipmentNumberApi()
this.cityData = res.data.map((item) => {
let value = item.location.split(',')
value.push(item.num)
// console.log('🚀 ~ getInfo ~ value:', value)
return {
...item,
value,
deptName: item.name,
}
})
} else if (this.btnIndex == 3) {
// res = await getMechanizationRateApi()
}
setTimeout(() => {
console.log('🚀 ~ 地图数据 ~ this.cityData:', this.cityData)
this.initMap()
}, 300)
console.log('🚀 ~ 地图数据 ~ res:', res)
} catch (error) {
console.log('🚀 ~ 地图数据 ~ error:', error)
// this.initMap()
}
},
initMap() {
echarts.registerMap('anhui', anhuiMapJson)
this.myChart = echarts.init(this.$refs.mapChart)
const seriesData = this.cityData
const option = {
backgroundColor: 'transparent',
geo3D: {
map: 'anhui',
roam: false, // 👈 允许拖拽
regionHeight: 7, // 👈 省份厚度
shading: 'lambert', // 光照模型realistic / lambert / color
realisticMaterial: {
roughness: 0.6,
metalness: 0.1,
texture: '#3A5EB1',
},
itemStyle: {
color: '#3A5EB1', // 👈 顶层背景色
borderColor: '#ECFEFF', // 👈 外层描边
borderWidth: 2,
opacity: 1,
},
label: {
show: false,
},
light: {
main: {
intensity: 1.2,
shadow: true,
shadowQuality: 'high',
alpha: 40, // 光照角度
beta: 20,
},
ambient: {
intensity: 0.6,
},
},
viewControl: {
distance: 168, // 视角远近
alpha: 52, // 旋转角度
beta: -16,
rotateSensitivity: 0, // 禁止旋转
zoomSensitivity: 0, // 禁止缩放
panSensitivity: 0, // 禁止平移
center: [12, -30, 0],
// scale: [1.5, 1, 1]
},
},
series: [
{
type: 'scatter3D',
coordinateSystem: 'geo3D',
data: seriesData,
symbol: 'circle',
symbolSize: 18,
itemStyle: {
color: '#f90', // 👈 散点颜色在这里改
opacity: 1, // 可调透明度
},
label: {
show: true,
position: 'top', // 先指定一个基准位置(如 'top'
offset: [0, -10], // 向上偏移 10pxx 方向 0y 方向 -10
triggerEvent: true,
formatter: (params) => {
const val = params.data.value || []
let unit = ''
if (this.btnIndex === 1) unit = '亿'
else if (this.btnIndex === 2) unit = '台'
else if (this.btnIndex === 3) unit = '%'
return val.length
? `{val|${val[2]} ${unit}}\n{name|${
params.data.deptName
}}`
: `{name|${params.data.deptName}}`
},
rich: {
val: {
backgroundColor: { image: labelBg },
height: 28,
minWidth: 70,
lineHeight: 28,
padding: [0, 10],
align: 'center',
verticalAlign: 'middle',
color: '#fff',
fontSize: 18,
},
name: {
color: '#fff',
fontFamily: 'DS-TITLE',
fontSize: 16,
padding: [6, 0, 0, 0],
},
},
},
},
],
}
this.myChart.setOption(option)
// 点击事件
this.myChart.on('click', (params) => {
console.log('🚀 ~ click ~ params:', params)
// params.name去掉 市
let city =
params.data.deptName == '安徽送变电工程有限公司' ? '安徽送变电' : params.data.cityName.replace(/市$/, '')
// if (params.seriesType === 'scatter' && params.data) {
// city =
// params.data.deptName == '安徽送变电工程有限公司' ? '安徽送变电' : params.data.cityName.replace(/市$/, '')
// } else {
// city = params.name.replace(/市$/, '')
// }
this.$router.push({
path: '/screen/cityScreen',
query: {
cityName: city,
},
})
})
// 鼠标移入时展示
this.myChart.on('mouseover', (params) => {
console.log('🚀 ~ mouseover ~ params:', params)
let city = params.data
// if (params.seriesType === 'scatter' && params.data) {
// // console.log('🚀 ~ 当前坐标点信息 ~ params.data:', params.data)
// console.log('🚀 ~ mouseover ~ city:', city)
// } else {
// this.selectedCity = null
// city = this.cityData.find((c) => c.cityName === params.name)
// }
this.selectedCity = city || null
if (params.event) {
this.tooltipPos = {
x: params.event.offsetX,
y: params.event.offsetY,
}
}
})
// 鼠标移出时隐藏
this.myChart.on('mouseout', () => {
this.selectedCity = null
})
window.addEventListener('resize', () => {
this.myChart.resize()
})
},
},
beforeDestroy() {
if (this.myChart) {
this.myChart.dispose()
this.myChart = null
}
},
}
</script>
<style lang="scss" scoped>
.middle-warp {
margin-top: 80px;
position: relative;
padding-top: 20px;
border-radius: 8px;
overflow: hidden;
}
.top-btns {
margin-left: -80px;
display: flex;
justify-content: center;
.btn:not(:last-child) {
margin-right: 80px;
}
.btn {
font-size: 18px;
text-align: center;
padding: 6px 15px;
font-family: DS-TITLE;
color: #ccc;
background-image: url('../../img/btn.png');
background-size: 100% 100%;
cursor: pointer;
}
.active {
background-image: url('../../img/btn-active.png');
background-size: 100% 100%;
}
}
// 外层容器:添加底部阴影
.map-wrapper {
/* margin-top: -180px; */
position: relative;
filter: drop-shadow(0 20px 20px rgba(0, 0, 0, 0.3)); // 20px 柔和阴影
transform: translateZ(0); // 启用硬件加速
}
// 倾斜层:实现 15 度倾斜的 3D 效果
.map-tilt {
transform: rotateX(15deg);
transform-origin: bottom center;
perspective: 1200px; // 👈 增加景深,效果更立体
transition: transform 0.3s ease;
pointer-events: none;
height: 900px;
display: flex;
justify-content: center;
}
// 鼠标悬停时轻微动态效果(可选)
.middle-warp:hover .map-tilt {
transform: rotateX(12deg);
}
// 实际图表容器
.map-container {
width: 160%;
height: 900px;
background: transparent;
pointer-events: auto; // 图表本身可交互
display: flex;
align-items: center;
justify-content: center;
}
.city-tooltip {
position: absolute;
top: 20px;
right: 80px;
width: 288px;
height: 288px;
color: #fdfdfd;
padding: 12px;
border-radius: 6px;
font-size: 17px;
background-image: url('../../img/dialog.png');
background-size: 100% 100%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
z-index: 10;
.city-name {
font-size: 25px;
font-family: DS-TITLE;
margin: -5px 0 10px;
}
div {
padding-bottom: 5px;
}
// 除了第一个和最后一个外,添加一个浅下边框
div:not(:first-child):not(:last-child) {
margin-bottom: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.num {
font-weight: 900;
}
.unit {
font-size: 12px;
color: #ccc;
}
}
</style>