Files

461 lines
14 KiB
Vue
Raw Normal View History

2022-01-11 17:05:48 +08:00
<template>
<div class="box3" v-loading="loading">
<div class="tit">专利与成果分布地图</div>
<div v-if="state.isShowGoBack" class="close-back" @click="goBack">
<img src="./img/back_button.png" />
</div>
<!-- echartsDom 兼容缩放 -->
<div ref="map" class="map echartsDom" id="map"></div>
<div class="leftBox">
<div class="head">
<div class="a">地区</div>
<div class="b">成果数量</div>
</div>
<div v-if="Object.keys(snapTree).length > 0" v-for="v in snapTree">
<div class="a">{{ v.name }}</div>
<div class="b">{{ v.count }}</div>
</div>
<div v-else>
<div class="a">暂无</div>
<div class="b">暂无</div>
</div>
</div>
<div class="rightBox">
<div class="head">
<div class="a">领域</div>
<div class="b">成果数量</div>
</div>
<div v-if="Object.keys(getIndustry(snapTree)).length > 0" v-for="(v,k) in getIndustry(snapTree)">
2022-01-12 17:38:36 +08:00
<div class="a" :title="k">{{ k }}</div>
2022-01-11 17:05:48 +08:00
<div class="b">{{ v }}</div>
</div>
<div v-else>
<div class="a">暂无</div>
<div class="b">暂无</div>
</div>
</div>
</div>
</template>
<script setup>
import { defineComponent, getCurrentInstance, onMounted, reactive } from "vue";
import echarts from 'echarts'
import { achievement } from "@/api/website/home/index";
const { proxy } = getCurrentInstance();
const loading = shallowRef(true)
let treeData = { "340000": { "code": "340000", "name": "安徽省", "count": 107, "industry": { "1-1": 2, "1-2": 1, "2-1": 3 }, "children": { "340100": { "code": "340100", "name": "合肥市", "count": 106, "industry": { "1-1": 1, "1-2": 1, "2-1": 2 }, "children": { "340111": { "code": "340111", "name": "包河区", "count": 105, "industry": { "1-1": 1, "2-1": 1 }, "children": null }, "340121": { "code": "340121", "name": "长丰县", "count": 105, "industry": { "1-2": 1, "2-1": 1 }, "children": null } } }, "340200": { "code": "340200", "name": "芜湖市", "count": 105, "industry": { "1-1": 1, "2-1": 1 }, "children": {} } } }, "500000": { "code": "500000", "name": "重庆", "count": 300, "industry": null, "children": { "500100": { "code": "500100", "name": "市辖区", "count": 300, "industry": null, "children": null } } }, "630000": { "code": "630000", "name": "青海省", "count": 1200, "industry": null, "children": { "630200": { "code": "630200", "name": "海东市", "count": 1200, "industry": null, "children": null } } } };
const snapTree = shallowRef({});
function searchRegionData (code) {
// console.log(code, treeData,'searchRegionData')
return deepFindTree(code, treeData);
}
function deepFindTree (code, tree) {
let snap = false;
for (const key in tree) {
if (Object.hasOwnProperty.call(tree, key)) {
if (code == key) {
snap = tree[code];
break;
} else if (tree[key]['children'] != null) {
snap = deepFindTree(code, tree[key]['children']);
if (snap) {
break;
}
} else {
snap = false;
}
}
}
return snap;
}
function getIndustry (object) {
let snap = {};
for (const key in object) {
if (Object.hasOwnProperty.call(object, key)) {
const element = object[key];
if (element['industry'] != null) {
for (const ek in element['industry']) {
if (Object.hasOwnProperty.call(element['industry'], ek)) {
const ele = element['industry'][ek];
if (!Object.hasOwnProperty.call(snap, ek)) {
snap[ek] = 0
}
snap[ek] += ele
}
}
// for (let index = 0; index < element['industry'].length; index++) {
// const ele = element['industry'][index];
// if(Object.hasOwnProperty.call(snap, ele)) {
// }
// }
}
}
}
return snap
}
const state = reactive({
loading: false,
isShowGoBack: false,
nameType: '',
cityName: '中国',
areaCode: 10000,
AreaCodeStack: ['中国'],
geoJsonData: '',
echartsMap: null,
map: null,
uimap: null,
district: null,
polygons: [],
cityCode: '100000',
citySelect: null,
districtSelect: null,
opts: {},
areaData: {},
mapData: [],
zip: {},//打包zip
codeList: [],
isCodeListLoadComplete: false,//codeList是否全部获取完毕
downloadTips: '下载geoJson数据',//下载进度提示
isShowTips: false,//是否显示下载提示
});
onMounted(async () => {
// 数据接口
await achievement().then(res => {
if (200 == res.code) {
treeData = res.data;
snapTree.value = res.data;
loading.value = false;
}
});
2022-01-18 18:55:17 +08:00
// let echartsDomList = document.querySelectorAll('.echartsDom');
// // 兼容echarts
// echartsDomList.forEach(element => {
// element.style.zoom = window.devicePixelRatio;
// element.style.transform = "scale(" + (1 / window.devicePixelRatio) + ")";
// element.style.transformOrigin = "0%0%";
// element.style.width = window.devicePixelRatio * 100 + '%';
// element.style.height = window.devicePixelRatio * 100 + '%';
// console.log(element.style.zoom, 'element.style.zoom')
// });
2022-01-11 17:05:48 +08:00
let height = document.body.clientHeight;
let width = document.body.clientWidth;
let dom = proxy.$refs['map'];
dom.style.width = width + 'px';
dom.style.height = height - 80 + 'px';
state.echartsMap = echarts.init(dom);
state.echartsMap.on('click', echartsMapClick);
state.map = new AMap.Map('container', {
resizeEnable: true,
center: [116.30946, 39.937629],
zoom: 3
});
state.opts = {
subdistrict: 1, //返回下一级行政区
showbiz: false //最后一级返回街道信息
};
state.district = new AMap.DistrictSearch(state.opts);//注意:需要使用插件同步下发功能才能这样直接使用
state.district.search('中国', (status, result) => {
if (status == 'complete') {
getData(result.districtList[0], '', 100000);
}
});
});
function goBack () {
state.isShowGoBack = false;
loading.value = true;
state.district.search('中国', (status, result) => {
if (status == 'complete') {
getData(result.districtList[0], '', 100000);
snapTree.value = treeData;
}
});
}
function echartsMapClick (params) {//地图点击事件
if (params.data.cityCode == '710000') {
return;
}
if (params.data.level == 'district') {
return;
}
if (params.data.level == 'street') return;//此处的params.data为state.mapData里的数据
let snap = searchRegionData(params.data.cityCode);
snapTree.value = {}
if (snap) {
snapTree.value = snap['children']
}
state.cityCode = params.data.cityCode;
state.cityName = params.data.name;
state.district.setLevel(params.data.level); //行政区级别
state.district.setExtensions('all');
state.isShowGoBack = true;
loading.value = true;
//行政区查询
//按照adcode进行查询可以保证数据返回的唯一性
state.district.search(state.cityCode, (status, result) => {
if (status === 'complete') {
if (params.data.level == 'district') {
return;
}
state.AreaCodeStack.push(result.districtList[0].adcode);
getData(result.districtList[0], params.data.level, state.cityCode);//这个getData函数在前面已经定义过了
}
});
}
function getData (data, level, adcode) {//处理获取出来的边界数据
var subList = data.districtList;
if (subList) {
var curlevel = subList[0].level;
if (curlevel === 'street') {//为了配合echarts地图区县名称显示正常这边街道级别数据需要特殊处理
let mapJsonList = state.geoJsonData.features;
let mapJson = {};
for (let i in mapJsonList) {
if (mapJsonList[i].properties.name == state.cityName) {
mapJson['features'] = [].concat(mapJsonList[i]);
}
}
state.mapData = [];
let item = searchRegionData(cityCode)
if (item) {
console.log('1 searchRegionData(cityCode)', item);
}
//这个mapData里包含每个区域的code、名称、对应的等级实现第三步功能时能用上
state.mapData.push({ name: state.cityName, value: item ? item.count : 0, level: curlevel });
loadMap(state.cityName, mapJson);
state.geoJsonData = mapJson;
return;
}
//街道级以上的数据处理方式
state.mapData = [];
for (var i = 0, l = subList.length; i < l; i++) {
var name = subList[i].name;
var cityCode = subList[i].adcode;
//这个mapData里包含每个区域的code、名称、对应的等级实现第三步功能时能用上
let item = searchRegionData(cityCode)
if (item) {
console.log('2 searchRegionData(cityCode)', item);
}
state.mapData.push({
name: name,
value: item ? item.count : 0,
cityCode: cityCode,
level: curlevel
});
}
loadMapData(adcode);
}
}
function loadMapData (areaCode) {
AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {
//创建一个实例
var districtExplorer = window.districtExplorer = new DistrictExplorer({
eventSupport: true, //打开事件支持
map: state.map
});
districtExplorer.loadAreaNode(areaCode, (error, areaNode) => {
if (error) {
console.error(error);
return;
}
let mapJson = {};
//特别注意这里哦如果查看过正常的geojson文件都会发现文件都是以features 字段开头的,所以这里要记得加上
mapJson.features = areaNode.getSubFeatures();
loadMap(state.cityName, mapJson);
});
});
}
function loadMap (mapName, data) {
if (data) {
echarts.registerMap(mapName, data);//把geoJson数据注入echarts
//配置echarts的option
var option = {
visualMap: {
type: 'piecewise',
left: "center", //组件离容器左侧的距离,'left', 'center', 'right','20%'
bottom: "30",
orient: "horizontal", //图例排列方向
padding: 5,
pieces: [
{ gte: 0, lte: 99, label: '99', color: '#CAE9FD' },
{ gte: 100, lte: 299, label: '100-299', color: '#7ED2F7' },
{ gte: 300, lte: 499, label: '299-499', color: '#039DDD' },
{ gte: 500, label: '500', color: '#0D4884' },
// {max: 30, label: '安全', color: '#2c9a42'},
// {min: 30, max: 60, label: '警告', color: '#d08a00'},
// {min: 60, label: '危险', color: '#c23c33'},
],
// color: '#fff',
textStyle: {
color: '#fff',
},
visibility: 'off',
},
tooltip: {
//提示框信息
trigger: 'item',
formatter: '{b}\n{c}个',
},
series: [{
name: '数据名称',
type: 'map',
roam: false,
top: "15%",
bottom: state.isShowGoBack ? '8%' : '-20%',
mapType: mapName,
selectedMode: 'single',
showLegendSymbol: false,
visibility: 'off',
backgroundColor: "transparent",
itemStyle: {
normal: {
color: '#ccc',
areaColor: '#fff',
borderColor: '#fff',
borderWidth: 0.5,
label: {
show: true,
textStyle: {
color: "rgb(249, 249, 249)"
}
}
},
emphasis: {
areaColor: "rgb(237, 201, 216)",
borderColor: '#fff',
areaStyle: {
color: '#fff'
},
label: {
show: true,
textStyle: {
color: "rgb(249, 249, 249)"
},
// formatter: function (value) { //标签的格式化工具。
// return value.name + '' + value.value; // 范围标签显示内容。
// }
}
}
},
data: state.mapData, //这个data里包含每个区域的code、名称、对应的等级实现第三步功能时能用上
}]
};
state.echartsMap.setOption(option);
loading.value = false;
}
}
</script>
<style lang="scss" scoped>
.box3 {
width: 100%;
height: 100%;
background: linear-gradient(0deg, #010101, #041744);
position: relative;
.tit {
position: absolute;
top: 75px;
width: 100%;
text-align: center;
font-size: 36px;
font-family: Source Han Sans CN;
font-weight: 300;
color: #ffffff;
}
}
.map {
width: 100%;
height: 100%;
background-image: url(./img/lightEffect.png);
background-size: 644px 272px;
background-repeat: no-repeat;
background-position: center top;
}
.close-back {
background: url(img/close_back.png) no-repeat;
transition: all 0.5s;
height: 70px;
width: 85px;
color: #fff;
left: 65px;
position: absolute;
top: 100px;
cursor: pointer;
z-index: 1000;
&:hover {
left: 55px;
}
img {
margin: 28px auto 0;
width: 30px;
display: block;
transition: all 0.5s;
}
}
.leftBox {
2022-01-18 18:55:17 +08:00
left: 10%;
2022-01-11 17:05:48 +08:00
}
.rightBox {
2022-01-18 18:55:17 +08:00
right: 10%;
2022-01-11 17:05:48 +08:00
max-height: 465px !important;
}
.leftBox,
.rightBox {
position: absolute;
top: 25%;
max-width: 280px;
min-width: 200px;
max-height: 256px;
overflow: hidden;
background: rgba(4, 22, 65, 0.5);
border: 1px solid #0054ff;
color: rgba(161, 192, 255, 1);
& > div {
display: flex;
}
.head {
border-bottom: 1px solid #0054ff;
color: #ffffff;
}
.a {
flex: 1;
border-right: 1px solid #0054ff;
text-align: center;
line-height: 42px;
2022-01-12 17:38:36 +08:00
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
2022-01-11 17:05:48 +08:00
}
.b {
text-align: center;
line-height: 42px;
width: 90px;
}
}
</style>