菜单组件 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.type
let 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.type
emit('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.length
if (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.showMenu
if (!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>