菜单组件 IntelligentAnalysis.vue
中间圆形区域可以换个图片
<template><div class="intel-analysis"><div class="info" :class="{ 'close-animation': !showMenu }"><div class="middle"></div><div class="text-info"><div v-for="(item, index) in list" :key="index"><div :class="`item ${item.type === currentType ? 'active' : ''}`":style="{ rotate: `${item.rotate}deg`, left: item.left, top: item.top, }" @click="handleClick(item, index)"><div style="width: 10px;height: 11px;"><div :class="`${item.type === currentType && list2.length > 0 ? 'triangle' : ''}`"></div></div><div class="text">{{ item.text }}</div><div class="icon"><img :src="item.icon" alt=""></div></div></div></div></div><div class="info-sec-bg"></div><div class="info-sec" ref="infoSecRef"><div v-for="(item, index) in list2" :key="index"><div :class="`citem ${item.type === currentType2 ? 'active' : ''}`":style="{ rotate: `${item.rotate}deg`, left: item.left, top: item.top, }" @click="handleClick2(item, index)"><div class="text">{{ item.text }}</div></div></div></div></div>
</template><script>
import { defineComponent, onMounted, reactive, toRefs, watch } from 'vue'
import temp from '@/assets/imgs/supervisionGIS/temp.png'export default defineComponent({name: 'IntelligentAnalysis',components: {},props: {showMenu: {type: Boolean,default: false}},emits: ['showMenu'],setup(props, { emit }) {const state = reactive({show: false,list: [{type: 'eng',icon: temp,text: '节能效果',// rotate: '8deg',},{type: 'ctrl',icon: temp,text: '节能效果',// rotate: '-11deg',},{type: 'engZhenduan',icon: temp,text: '节能效果',// rotate: '-33deg',},{type: 'secondNet',icon: temp,text: '节能效果',// rotate: '-56deg',},{type: 'comcell',icon: temp,text: '节能效果',// rotate: '-90deg',},// {// type: 'comcell',// icon: temp,// text: '投诉re区',// rotate: '-90deg',// }],list2: [{type: 'eng2',icon: temp,text: '节能效果',// rotate: '8deg',},{type: 'ctrl2',icon: temp,text: '节能效果',// rotate: '-11deg',},{type: 'engZhenduan2',icon: temp,text: '节能效果',// rotate: '-33deg',},{type: 'engZhenduan2',icon: temp,text: '节能效果',// rotate: '-33deg',},// {// type: 'engZhenduan2',// icon: temp,// text: '能耗诊治',// // rotate: '-33deg',// },// {// type: 'engZhenduan2',// icon: temp,// text: '能耗诊治',// // rotate: '-33deg',// },// {// type: 'engZhenduan2',// icon: temp,// text: '能耗诊治',// // rotate: '-33deg',// },// {// type: 'engZhenduan2',// icon: temp,// text: '能耗诊治',// // rotate: '-33deg',// },// {// type: 'engZhenduan2',// icon: temp,// text: '能耗诊治',// // rotate: '-33deg',// },],currentType: '',currentType2: '',infoSecRef: null,})const methods = {// 点击具体内容handleClick(item, index) {state.currentType = item.typelet domSec = document.querySelector('.info-sec')let domBg = document.querySelector('.info-sec-bg')domSec.style.display = 'block'if (state.list2.length > 0) {domBg.style.display = 'block'}// 二级菜单扇形switch (state.list2.length) {case 1:domSec.style.clipPath = 'polygon(50% 50%, 0% 42%, 0% 51%)'break;case 2:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 60%)'break;case 3:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 70%)'break;case 4:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 82%)'break;case 5:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 96%)'break;case 6:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 116%)'break;case 7:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 148%)'break;case 8:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 215%)'break;case 9:domSec.style.clipPath = 'polygon(50% 50%, 0% 41%, 0% 484%)'break;default:break;}if (state.list2.length !== 1) {// 计算二级菜单度数的一半const num = -(((state.list2.length - 1) * 10) / 2)if (index === 0) {// 点第一个一级菜单时,二级菜单角度不变domSec.style.rotate = `${item.rotate - 3}deg`} else if (index === state.list.length - 1 && state.list.length > 1) {// 点最后一个一级菜单时,二级菜单角度要往回拉全部度数domSec.style.rotate = `${item.rotate - (2 * num) + 5}deg`} else {if (state.list2.length < 7) {// 点中间的一级菜单时,二级菜单角度要往回拉全部度数的一半domSec.style.rotate = `${item.rotate - num}deg`} else {if (index === 1) {domSec.style.rotate = `${item.rotate - num - (15)}deg`} else if (index === state.list.length - 2) {domSec.style.rotate = `${item.rotate - num - (-20)}deg`} else {domSec.style.rotate = `${item.rotate - num}deg`}}}} else {// 二级菜单只有一个时,旋转一级菜单的角度domSec.style.rotate = `${item.rotate}deg`}domSec.style.transition = '0.5s'// emit('pageTypeChange', item)},handleClick2(item) {state.currentType2 = item.typeemit('getCurMenu', item)},}watch(() => props.showMenu, () => {console.log(props.showMenu, '---props.showMenu--');if (!props.showMenu) {state.currentType = ''state.currentType2 = ''state.infoSecRef.style.display = 'none'}})onMounted(() => {state.list.forEach((item, index) => {const length = state.list.length// item.rotate = `-${(120 / length * index)}`item.rotate = `-${((100 / (length - 1)) * index)}`if (index === length - 1) {item.rotate = -100}if (index === 0) {item.rotate = 0}console.log(item.rotate, '--margin-left--');})state.list2.forEach((item, index) => {const length = state.list2.lengthif (index === 0) {item.rotate = 0} else {item.rotate = -(10 * index)}console.log(item.rotate, '--item.rotate--');})})return {...toRefs(state),...methods,}}
})
</script><style scoped lang="less">
.intel-analysis {.info {width: 320px;height: 320px;border-radius: 50%;// width: 206px;// height: 206px;// border-radius: 0 0 0 206px;background: linear-gradient(160deg, rgba(3, 46, 116, 0) 0%, #032E74 22%, rgba(3, 46, 116, 0.99) 52%, #032E74 80%, rgba(3, 46, 116, 0) 100%);position: relative;display: flex;justify-content: center;align-items: center;z-index: 3;animation: show 0.5s;.middle {width: 80px;height: 80px;background-color: var(--gdky-layout-bg);border-radius: 50%;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);cursor: pointer;}}.item {display: flex;align-items: center;font-size: 14px;color: var(--gdky-second-content-color);padding-right: 55px;margin-bottom: 16px;cursor: pointer;position: absolute;left: -5%;/* 居中 */top: 44%;/* 居中 */transform: translate(7%, -50%);// /* 居中 */transform-origin: center right;z-index: 4;&:hover {color: #3C74CF;}&.active {font-weight: 600;color: #3C74CF;}.text {margin-left: 18px;}.triangle {width: 0;height: 0;border-left: 5px solid transparent;/* 左边 */border-right: 5px solid transparent;/* 右边 */border-bottom: 10px solid #ffcc00;/* 底边,根据等边三角形计算得到 */transform: rotate(-90deg);}.icon {display: flex;align-items: center;justify-content: center;width: 28px;height: 28px;margin-left: 16px;background: linear-gradient(293deg, #032E74 0%, #001941 100%);border-radius: 50%;border: 1px solid #032E74;}}// 二级菜单.info-sec {display: none;width: 540px;height: 540px;border-radius: 50%;clip-path: polygon(50% 50%, 0% 42%, 0% 51%);background: linear-gradient(160deg, rgba(3, 46, 116, 0) 0%, #032E74 22%, rgba(3, 46, 116, 0.99) 52%, #032E74 80%, rgba(3, 46, 116, 0) 100%);position: absolute;top: -110px;right: -110px;z-index: 0;animation: show 0.5s;.citem {display: flex;// justify-content: center;align-items: center;font-size: 14px;color: var(--gdky-second-content-color);padding-right: 112px;margin-bottom: 16px;cursor: pointer;position: absolute;left: 20%;/* 居中 */top: 47%;/* 居中 */transform: translate(-50%, -50%);// /* 居中 */transform-origin: center right;&:hover {color: #3C74CF;}&.active {font-weight: 600;color: #3C74CF;}}}// 一级菜单和二级菜单中间的背景 .info-sec-bg {display: none;width: 340px;height: 340px;border-radius: 50%;background: var(--gdky-layout-bg);position: absolute;top: -10px;right: -10px;z-index: 1;animation: show 0.5s;}.close-animation {animation: close 0.5s;}@keyframes show {0% {transform: rotate(120deg) scale(0);}100% {transform: rotate(0deg) scale(1);}}@keyframes close {0% {transform: rotate(0deg) scale(1);}100% {transform: rotate(120deg) scale(0);}}}
</style>
index.vue引用菜单组件 IntelligentAnalysis.vue
<template><div class="page--wrap"><!-- 菜单。右上 --><div class="right-intel-analysis"><div class="center" @click="handleMenu"><!-- 可以放一个图形进来 --><!-- <div class="robot"></div> --></div><transition name="menu"><IntelligentAnalysis class="menu" :showMenu="showMenu" v-show="showMenu" @getCurMenu="getCurMenu" /></transition></div></div>
</template><script>
import { defineComponent, reactive, toRefs, computed, onMounted, provide, ref, watch, getCurrentInstance } from "vue";
import Map from './MapComponents/Map.vue'
import { useAppStore } from '@/store/modules/app'
import { useStore } from '@/store/modules/Supervision/index'
import { GetApiData } from '@/api/Supervision/index.js'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'import IntelligentAnalysis from './Components/IntelligentAnalysis.vue'export default defineComponent({name: '470543',components: {IntelligentAnalysis,},setup() {const vm = getCurrentInstance();const appStore = useAppStore()const modulesStore = useStore()const router = useRouter()const state = reactive({showMenu: false,curMeu: {}, // 当前选中的菜单});onMounted(() => {})const methods = {// 点击右上角菜单handleMenu() {state.showMenu = !state.showMenuif (!state.showMenu) {state.curMeu = '' // 清空选中的菜单}},// 获取当前选中的菜单getCurMenu(item) {state.curMeu = item}}return {...toRefs(state),...methods,};}
});
</script><style lang="less" scoped>
.page--wrap {position: relative;height: 100%;width: 100%;display: flex;flex-direction: row;.right-intel-analysis {.center {width: 60px;height: 60px;background: var(--gdky-overlay-bg);border-radius: 50%;position: absolute;top: 2%;right: 1%;cursor: pointer;z-index: 100;display: flex;align-items: center;justify-content: center;.robot {// z-index: 5;width: 35px; // 200* 5000 25帧height: 35px;background-image: url(./assets/analysis-robot.png);background-repeat:no-repeat;background-position:0 0;background-size: 35px 875px;animation: robot-dy 2s steps(25) infinite;}@keyframes robot-dy{ 0%{ background-position:0 0;} 100%{ background-position: 0 -875px;}}}.menu {position: absolute;right: -110px;top: -110px;}.menu-enter-active, .menu-leave-active {transition: transform 0.5s;}.menu-enter, .menu-leave-to {transform: scale(0);}}
}
</style>