This commit is contained in:
2023-07-26 17:24:38 +08:00
parent e692cd9fc8
commit 1b3f64eb82
2 changed files with 178 additions and 103 deletions

View File

@ -1,11 +1,13 @@
<script setup> <script setup>
import AMapLoader from '@amap/amap-jsapi-loader'; import AMapLoader from '@amap/amap-jsapi-loader';
import {computed, onMounted, ref, shallowRef} from "vue"; import {computed, onMounted, ref, shallowRef, toRefs, watch} from "vue";
import {init, registerMap} from "echarts"; import {init, registerMap} from "echarts";
import { import {
countAchievementByArea, countAchievementByArea,
countAchievementByCity, countAchievementByCity,
countAchievementByProvince, countAchievementByProvince,
countDemandByArea,
countDemandByCity,
countDemandByProvince, countDemandByProvince,
countEnterpriseByArea, countEnterpriseByArea,
countEnterpriseByCity, countEnterpriseByCity,
@ -18,14 +20,25 @@ import backBtnPng from '@/assets/images/map_back.png'
import RegionPagine from "@/views/website/home/comp/RegionPagine.vue"; import RegionPagine from "@/views/website/home/comp/RegionPagine.vue";
import html2canvas from "html2canvas"; import html2canvas from "html2canvas";
import anime from "animejs"; import anime from "animejs";
import {debounce} from 'lodash-es'
import {ElMessage} from "element-plus";
const leftBoxPageNum = ref(1) const leftBoxPageNum = ref(1)
const rightBoxPageNum = ref(1)
const mapRef = ref(null); const mapRef = ref(null);
const districtSearch = shallowRef(null) const districtSearch = shallowRef(null)
const myEcharts = shallowRef(null) const myEcharts = shallowRef(null)
const map = shallowRef(null) const map = shallowRef(null)
const mapData = ref([]) const mapData = ref([])
const props = defineProps({
mapIndex: {
type: Number,
default: 0
}
})
const {mapIndex} = toRefs(props)
const emit = defineEmits(["changeMapIndex"])
const methods = [ const methods = [
{ {
name: "expert", name: "expert",
@ -45,8 +58,8 @@ const methods = [
name: "demand", name: "demand",
title: "需求分布地图", title: "需求分布地图",
byProvince: countDemandByProvince, byProvince: countDemandByProvince,
byCity: countDemandByProvince, byCity: countDemandByCity,
byArea: countDemandByProvince byArea: countDemandByArea
}, },
{ {
name: "enterprise", name: "enterprise",
@ -57,11 +70,11 @@ const methods = [
}, },
] ]
const methodIndex = ref(0)
const areaCount = ref([]) // 按行政区划统计 const areaCount = ref([]) // 按行政区划统计
const industryCount = ref([]) // 按领域统计 const industryCount = ref([]) // 按领域统计
const areaCountPaged = computed(() => areaCount.value.slice((leftBoxPageNum.value - 1) * 5, leftBoxPageNum.value * 5)) const areaCountPaged = computed(() => areaCount.value.slice((leftBoxPageNum.value - 1) * 5, leftBoxPageNum.value * 5))
const industryCountPaged = computed(() => industryCount.value.slice((rightBoxPageNum.value - 1) * 5, rightBoxPageNum.value * 5))
const options = { const options = {
// nameProperty: 'adcode', // nameProperty: 'adcode',
visualMap: { visualMap: {
@ -99,7 +112,7 @@ const loadAMap = async () => {
const AMap = await AMapLoader.load({ const AMap = await AMapLoader.load({
"key": "377d7c36dd385e2a722f29d4c6e1ffbf", // 申请好的Web端开发者Key首次调用 load 时必填 "key": "377d7c36dd385e2a722f29d4c6e1ffbf", // 申请好的Web端开发者Key首次调用 load 时必填
"version": "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15 "version": "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
"plugins": ["AMap.DistrictSearch", "AMap.DistrictExplorer"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 "plugins": [/*"AMap.DistrictSearch", "AMap.DistrictExplorer"*/], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
"AMapUI": { "AMapUI": {
// 是否加载 AMapUI缺省不加载 // 是否加载 AMapUI缺省不加载
version: '1.1', // AMapUI 缺省 1.1 version: '1.1', // AMapUI 缺省 1.1
@ -112,12 +125,12 @@ const loadAMap = async () => {
// viewMode: '3D' //使用3D视图 // viewMode: '3D' //使用3D视图
}); });
map.value.on("click", mapClick) map.value.on("click", mapClick)
districtSearch.value = new AMap.DistrictSearch({ // districtSearch.value = new AMap.DistrictSearch({
level: 'province', // level: 'province',
extensions: 'all', // extensions: 'all',
subdistrict: 1, // subdistrict: 1,
showbiz: false, // showbiz: false,
}) // })
} }
const loading = ref(false) const loading = ref(false)
const loadDistrict = (adcode) => { const loadDistrict = (adcode) => {
@ -143,18 +156,22 @@ const loadDistrict = (adcode) => {
let result let result
try { try {
if (level === 0) { if (level === 0) {
result = await methods[methodIndex.value]['byProvince']() result = await methods[mapIndex.value]['byProvince']()
} else if (level === 1) { } else if (level === 1) {
result = await methods[methodIndex.value]['byCity'](adcode) result = await methods[mapIndex.value]['byCity'](adcode)
} else if (level === 2) { } else if (level === 2) {
result = await methods[methodIndex.value]['byArea'](adcode) result = await methods[mapIndex.value]['byArea'](adcode)
} }
} catch (e) { } catch (e) {
loading.value = false loading.value = false
return return
} }
industryCount.value = result.industry if (result.industry) industryCount.value = Object.keys(result.industry).map(key => ({
areaCount.value = result.count name: key,
count: result.industry[key]
})
)
areaCount.value = result.count ?? []
mapData.value = geoJSON.features.map(el => { mapData.value = geoJSON.features.map(el => {
const areaProp = el.properties const areaProp = el.properties
return { return {
@ -215,21 +232,15 @@ const mapClick = (ev) => {
loadDistrict(ev.data.adcode) loadDistrict(ev.data.adcode)
} }
const handleScroll = (ev) => {
let direction = ev.deltaY > 0 ? 'down' : 'up' const playScrollAnimation = (direction, start) => {
// 判断滚轮滚动方向
if (direction === 'down' && methodIndex.value < methods.length - 1) {
methodIndex.value++
} else if (direction === 'up' && methodIndex.value > 0) {
methodIndex.value--
} else {
return
}
ev.preventDefault()
ev.stopPropagation()
const pageWrap = document.querySelector('.page-wrap') const pageWrap = document.querySelector('.page-wrap')
const rootWrap = document.querySelector('.root-container') const rootWrap = document.querySelector('.root-container')
html2canvas(pageWrap).then(canvas => { html2canvas(pageWrap).then(canvas => {
canvas.addEventListener("wheel", (ev) => {
ev.stopPropagation()
ev.preventDefault()
})
if (direction === 'down') { if (direction === 'down') {
rootWrap.insertBefore(canvas, pageWrap) rootWrap.insertBefore(canvas, pageWrap)
} else if (direction === 'up') { } else if (direction === 'up') {
@ -241,15 +252,49 @@ const handleScroll = (ev) => {
translateY: direction === 'down' ? "-100%" : "0", translateY: direction === 'down' ? "-100%" : "0",
duration: 300, duration: 300,
easing: 'linear', easing: 'linear',
begin: start,
complete: () => { complete: () => {
rootWrap.removeChild(canvas) rootWrap.removeChild(canvas)
rootWrap.style.transform = 'translateY(0%)' rootWrap.style.transform = 'translateY(0%)'
isScrolling.value = false
} }
}) })
}) })
loadDistrict("100000")
} }
const isScrolling = ref(false)
const handleScroll = async (ev) => {
let direction = ev.deltaY > 0 ? 'down' : 'up'
// 判断滚轮滚动方向
if (direction === 'down' && mapIndex.value >= methods.length - 1 || direction === 'up' && mapIndex.value <= 0) {
return
}
ev.preventDefault()
ev.stopPropagation()
if (isScrolling.value) {
return;
}
isScrolling.value = true
playScrollAnimation(direction, () => {
})
if (direction === 'down' && mapIndex.value < methods.length - 1) {
emit("changeMapIndex", mapIndex.value + 1)
} else if (direction === 'up' && mapIndex.value > 0) {
emit("changeMapIndex", mapIndex.value - 1)
}
}
watch(mapIndex, (newVal, oldVal) => {
console.log(`mapIndex change from ${oldVal} to ${newVal}`)
if (newVal === oldVal) {
return
}
isScrolling.value = true
const direction = newVal > oldVal ? 'down' : 'up'
playScrollAnimation(direction, () => {
})
loadDistrict("100000")
})
</script> </script>
<template> <template>
@ -257,7 +302,7 @@ const handleScroll = (ev) => {
<div class="root-container"> <div class="root-container">
<div class="page-wrap" @wheel="handleScroll"> <div class="page-wrap" @wheel="handleScroll">
<div class="title">{{ <div class="title">{{
methods[methodIndex].title methods[mapIndex].title
}} }}
</div> </div>
<div v-if="loading" class="loading-modal"> <div v-if="loading" class="loading-modal">
@ -267,7 +312,7 @@ const handleScroll = (ev) => {
<img :src="backBtnPng" alt="back"/> <img :src="backBtnPng" alt="back"/>
</div> </div>
<!-- 人数表格 --> <!-- 人数表格 -->
<div class="people-count"> <div class="count-table area">
<div class="table"> <div class="table">
<div class="head"> <div class="head">
<div class="th"> <div class="th">
@ -285,6 +330,25 @@ const handleScroll = (ev) => {
</div> </div>
<RegionPagine v-model:page="leftBoxPageNum" :total="areaCount.length"/> <RegionPagine v-model:page="leftBoxPageNum" :total="areaCount.length"/>
</div> </div>
<!-- 领域 -->
<div class="count-table industry">
<div class="table">
<div class="head">
<div class="th">
<div class="title">领域</div>
<div class="count">人数</div>
</div>
</div>
<div class="body">
<div v-for="item in industryCountPaged"
:key="item.adcode" class="tr">
<div class="title">{{ item.name }}</div>
<div class="count">{{ item.count }}</div>
</div>
</div>
</div>
<RegionPagine v-model:page="rightBoxPageNum" :total="industryCount.length"/>
</div>
<div id="map-container" ref="mapRef"></div> <div id="map-container" ref="mapRef"></div>
<div <div
id="container" id="container"
@ -357,12 +421,21 @@ const handleScroll = (ev) => {
cursor: pointer; cursor: pointer;
} }
.people-count { .count-table {
position: absolute; position: absolute;
top: 300px;
left: 120px;
z-index: 101; z-index: 101;
&.area {
top: 200px;
left: 120px;
}
&.industry {
top: 200px;
right: 120px;
}
.table { .table {
border: 1px solid #0054ff; border: 1px solid #0054ff;

View File

@ -1,32 +1,34 @@
<template> <template>
<div v-loading="loading" class="fullPage" ref="fullPageRef"> <div ref="fullPageRef" v-loading="loading" class="fullPage">
<div class="indicator"> <div class="indicator">
<div <div
:class="`${state.fullpage.current == idx ? 'active' : ''}`" v-for="idx in 6"
v-for="idx in len"
:key="idx"
:id="idx.toString()" :id="idx.toString()"
:key="idx"
:class="`${indicatorActiveIndex == idx ? 'active' : ''}`"
class="point" class="point"
@click="handleIndicatorClick(idx)" @click="handleIndicatorClick(idx)"
></div> ></div>
</div> </div>
<div <div
class="fullPageContainer"
:data-index="state.fullpage.current"
ref="fullPageContainerRef" ref="fullPageContainerRef"
:data-index="state.fullpage.current"
class="fullPageContainer"
@mousewheel="mouseWheelHandle" @mousewheel="mouseWheelHandle"
> >
<!-- @DOMMouseScroll="mouseWheelHandle" --> <!-- @DOMMouseScroll="mouseWheelHandle" -->
<div <div
v-for="(item, $index) in state.boxList" v-for="(item, $index) in state.boxList"
class="section"
:key="$index" :key="$index"
:style="`z-index: ${item.zIndex};`" :style="`z-index: ${item.zIndex};`"
class="section"
> >
<!-- v-if="`index${state.fullpage.current}` == item.title" --> <!-- v-if="`index${state.fullpage.current}` == item.title" -->
<component <component
v-if="Math.abs(state.fullpage.current - ($index + 1)) <= 1"
:is="item.comp" :is="item.comp"
v-if="Math.abs(state.fullpage.current - ($index + 1)) <= 1"
:map-index="mapIndex"
@changeMapIndex="mapIndex = $event"
></component> ></component>
</div> </div>
</div> </div>
@ -50,22 +52,9 @@
</template> </template>
<script setup> <script setup>
import { import {computed, onMounted, reactive, ref, shallowRef,} from "vue";
reactive,
onMounted,
ref,
shallowRef,
onUnmounted,
computed,
} from "vue";
import index0 from "./comp/index0.vue" import index0 from "./comp/index0.vue"
import index1 from "./comp/index1.vue"; import index1 from "./comp/index1.vue";
import index2 from "./comp/index2.vue";
import index3 from "./comp/index3.vue";
import index4 from "./comp/index4.vue";
import index5 from "./comp/index5.vue";
import index6 from "./comp/index6.vue";
import index7 from "./comp/index7.vue";
import index8 from "./comp/index8.vue"; import index8 from "./comp/index8.vue";
const loading = ref(true); const loading = ref(true);
@ -74,6 +63,8 @@ setTimeout(() => {
}, 500); }, 500);
const fullPageRef = ref(); const fullPageRef = ref();
const fullPageContainerRef = ref(); const fullPageContainerRef = ref();
const mapIndex = ref(0) // 0-3
const mapRef = ref()
onMounted(() => { onMounted(() => {
fullPageContainerRef.value.addEventListener( fullPageContainerRef.value.addEventListener(
"DOMMouseScroll", "DOMMouseScroll",
@ -89,6 +80,8 @@ onMounted(() => {
// }); // });
const len = computed(() => state.boxList.length); const len = computed(() => state.boxList.length);
// const len = ref(6); // const len = ref(6);
const next = () => { const next = () => {
// 往下切换 // 往下切换
// TODO: // TODO:
@ -107,6 +100,7 @@ const pre = () => {
move(state.fullpage.current); // 执行切换 move(state.fullpage.current); // 执行切换
} }
}; };
function move(index) { function move(index) {
state.fullpage.isScrolling = true; // 为了防止滚动多页,需要通过一个变量来控制是否滚动 state.fullpage.isScrolling = true; // 为了防止滚动多页,需要通过一个变量来控制是否滚动
directToMove(index); //执行滚动 directToMove(index); //执行滚动
@ -115,6 +109,7 @@ function move(index) {
state.fullpage.isScrolling = false; state.fullpage.isScrolling = false;
}, 1010); }, 1010);
} }
function directToMove(index) { function directToMove(index) {
let height = fullPageRef.value["clientHeight"]; //获取屏幕的宽度 let height = fullPageRef.value["clientHeight"]; //获取屏幕的宽度
// let scrollPage = proxy.$refs["fullPageContainer"]; // 获取执行tarnsform的元素 // let scrollPage = proxy.$refs["fullPageContainer"]; // 获取执行tarnsform的元素
@ -123,6 +118,7 @@ function directToMove(index) {
fullPageContainerRef.value.style.transform = `translateY(${scrollHeight})`; fullPageContainerRef.value.style.transform = `translateY(${scrollHeight})`;
state.fullpage.current = index; state.fullpage.current = index;
} }
function mouseWheelHandle(event) { function mouseWheelHandle(event) {
// 监听鼠标监听 // 监听鼠标监听
// 添加冒泡阻止 // 添加冒泡阻止
@ -164,36 +160,6 @@ let state = reactive({
zIndex: 1, zIndex: 1,
title: "index1", title: "index1",
}, },
// {
// comp: shallowRef(index2),
// zIndex: 1,
// title: "index2",
// },
// {
// comp: shallowRef(index3),
// zIndex: 1,
// title: "index3",
// },
// {
// comp: shallowRef(index4),
// zIndex: 1,
// title: "index4",
// },
// {
// comp: shallowRef(index5),
// zIndex: 1,
// title: "index5",
// },
// {
// comp: shallowRef(index6),
// zIndex: 1,
// title: "index6",
// },
// {
// comp: shallowRef(index7),
// zIndex: 1,
// title: "index7",
// },
{ {
comp: shallowRef(index8), comp: shallowRef(index8),
zIndex: 1, zIndex: 1,
@ -206,19 +172,49 @@ let state = reactive({
}, },
}); });
const indicatorActiveIndex = computed(() => {
if (state.fullpage.current === 1) {
return 1
} else if (state.fullpage.current === 2) {
return mapIndex.value + 2
} else {
return state.fullpage.current + 3
}
})
// 点击 indicator 时 // 点击 indicator 时
const handleIndicatorClick = (idx) => { const handleIndicatorClick = (idx) => {
if (idx == state.fullpage.current) { console.log(idx)
return; let boxIndex
} else if (idx > state.fullpage.current) { let _mapIndex;
for (let i = state.fullpage.current; i < idx; i++) { if (idx === 1) {
boxIndex = 1
_mapIndex = null
} else if (idx <= 5) {
boxIndex = 2
_mapIndex = idx - 2
} else {
boxIndex = 3
_mapIndex = null
}
if (boxIndex > state.fullpage.current) {
for (let i = state.fullpage.current; i < boxIndex; i++) {
next(); next();
} }
} else { } else if (boxIndex < state.fullpage.current) {
for (let i = state.fullpage.current; i > idx; i--) { for (let i = state.fullpage.current; i > boxIndex; i--) {
pre(); pre();
} }
} }
if (_mapIndex !== null && _mapIndex !== mapIndex.value) {
// mapRef.value?.loadMapByIndex(_mapIndex)
// console.log(mapRef.value.loadMapByIndex)
mapIndex.value = _mapIndex
}
}; };
</script> </script>
@ -228,32 +224,38 @@ const handleIndicatorClick = (idx) => {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
.indicator { .indicator {
position: absolute; position: absolute;
top: 50%; top: 50%;
right: 20px; right: 20px;
z-index: 999; z-index: 999;
transform: translateY(-50%); transform: translateY(-50%);
.point { .point {
transition: all 1s; transition: all 1s;
width: 12px; width: 12px;
height: 12px; height: 12px;
background-color: #999; background-color: #999;
border-radius: 50%; border-radius: 50%;
&.active { &.active {
background-color: #0054ff; background-color: #0054ff;
} }
&:not(:last-child) { &:not(:last-child) {
margin-bottom: 6px; margin-bottom: 6px;
} }
} }
} }
} }
.fullPageContainer { .fullPageContainer {
width: 100%; width: 100%;
height: 100%; height: 100%;
transition: all linear 0.5s; transition: all linear 0.5s;
} }
.section { .section {
width: 100%; width: 100%;
height: 100%; height: 100%;