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

View File

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