Files
2022-01-27 13:33:17 +08:00

463 lines
14 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="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)">
<div class="a" :title="k">{{ k }}</div>
<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(() => {
// 数据接口
achievement().then(res => {
if (200 == res.code) {
treeData = res.data;
snapTree.value = res.data;
loading.value = false;
}
});
// 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')
// });
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);
setTimeout(() => {
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);
}
});
}, 3000)
});
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 {
left: 10%;
}
.rightBox {
right: 10%;
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;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
.b {
text-align: center;
line-height: 42px;
width: 90px;
}
}
</style>