css扇形菜单动画效果

 菜单组件 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>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/635402.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

协变(List泛型作为方法参数时的父类子类问题)

有段时间没搞.net的项目了&#xff08;没办法&#xff0c;谁让国内JAVA流行是事实&#xff09;。最近又回归.net&#xff08;哪里需要哪里搬~&#xff09;。 接收到需求后&#xff0c;一顿输出&#xff0c;结果…咦?编译失败??? 错误信息&#xff1a; CS1503:参数1:无法…

阿里云 EMR Serverless Spark 版开启免费公测

阿里云 EMR Serverless Spark 版是一款云原生&#xff0c;专为大规模数据处理和分析而设计的全托管 Serverless 产品。它为企业提供了一站式的数据平台服务&#xff0c;包括任务开发、调试、调度和运维等&#xff0c;极大地简化了数据处理的全生命周期工作流程。使用 EMR Serve…

win11安装MySQL

目录[-] 1. 1. 下载2. 2. 安装 参考文档&#xff1a;MySQL :: MySQL 8.4 Reference Manual 1. 下载 mysql官网下载msi安装程序&#xff1a;MySQL :: Begin Your Download 2. 安装 运行下载的mis程序,逐步安装。 安装模式&#xff1a; complete; 进入配置&#xff1a; data di…

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权&#xff0c;可以让你生成有洞察力的、 简洁的、易于理解的SEO报告&#xff0c;帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

苹果CMS:如何去掉首页帮助提示信息

首先我们安装好苹果CMS&#xff0c;未安装的可以参考苹果cms&#xff1a;介绍及安装 安装好之后我们需要进入模版设置&#xff0c;可能对于刚刚接触CMS框架的朋友是不清楚地址的&#xff1a; https://www.yourweb.com/admin_login.php/admin/mxpro/mxproset 其中【yourweb】…

探索移动云:我的ES与Kibana之旅

目录 引言&#xff1a; 如何免费体验移动云产品 登录并完成实名认证 选择试用ECS云主机 安全组配置 安装Elasticsearch和Kibana 安装Elasticsearch ​编辑安装kibana 测试结果 使用感觉 引言&#xff1a; 移动云技术产品的发展已经取得了巨大的进步。云数融合、A1、大…

宝塔面包安装搭建Flarum开源论坛程序 文档教程

一、服务器环境说明 宝塔 7.0.3 或更新版本 Linux Server&#xff08;本文用的是 CentOs 7.4.6 64位&#xff09; Apache 或者 Nginx&#xff08;本文用的是 Nginx 1.16.0&#xff09; MySQL 5.6&#xff08;本文使用 MySQL 5.7&#xff0c;原因请看下方引用&#xff09; PHP 7…

weblogic ssrf漏洞(CVE-2014-4210)

漏洞复现环境搭建请参考 Vulhub漏洞复现环境搭建流程_vulhub一键搭建漏洞测试靶场,来进行漏洞复现-CSDN博客 docker未能成功启动redis请参考 http://t.csdnimg.cn/5osP3 漏洞版本 weblogic 10.0.2 -- 10.3.6.0 漏洞验证 &#xff08;1&#xff09;访问7001端口&#xff0c;…

基于MetaGPT构建单智能体

前言 在之前的文章中&#xff0c;我们详细地描述了Agent的概念和组成&#xff0c;在代码案例中体验了Agent的记忆、工具、规划决策模块&#xff0c;并通过几个Agent框架来加强读者对Agent开发设计与应用的理解&#xff0c;接下来我们就要进入智能体Agent的实际开发中&#xff0…

Linux系统Redhat7.4版本安装mysql-5.7.17详细步骤

1.1、在根目录创建一个data目录 mkdir /data 1.2、将MySQL安装包上传到/data目录下 1.3、解压MySQL安装包到当前目录 tar -zxvf mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz 1.4、因为解压后MySQL目录名称太长&#xff0c;修改成简短的mysql mv mysql-5.7.17-linux-glibc2.…

AI智能体|扣子Coze“图像流”功能速览

大家好&#xff0c;我是无界生长。 AI智能体&#xff5c;扣子Coze“图像流”功能速览Coze提供易上手的图像处理工作流&#xff0c;包含智能生成、智能编辑和基础编辑三类节点&#xff0c;旨在通过AI技术简化图像处理过程。本文对扣子Coze“图像流”功能做了简单介绍&#xff0…

爬虫学习--11.MySQL数据库的基本操作(上)

MySQL数据库的基本操作 创建数据库 我们可以在登陆 MySQL 服务后&#xff0c;使用命令创建数据库&#xff0c;语法如下: CREATE DATABASE 数据库名; 显示所有的数据库 show databases; 删除数据库 使用普通用户登陆 MySQL 服务器&#xff0c;你可能需要特定的权限来创建或者删…

基于EifficientNet的视网膜病变识别

分析一下代码 model.py ①下面这个方法的作用是&#xff1a;将传入的ch&#xff08;channel&#xff09;的个数调整到离它最近的8的整数倍&#xff0c;这样做的目的是对硬件更加友好。 def _make_divisible(ch, divisor8, min_chNone):if min_ch is None:min_ch divisornew…

爬虫学习--12.MySQL数据库的基本操作(下)

MySQL查询数据 MySQL 数据库使用SQL SELECT语句来查询数据。 语法&#xff1a;在MySQL数据库中查询数据通用的 SELECT 语法 SELECT 字段1&#xff0c;字段2&#xff0c;……&#xff0c;字段n FROM table_name [WHERE 条件] [LIMIT N] 查询语句中你可以使用一个或者多个表&…

Ajax用法总结(包括原生Ajax、Jquery、Axois)

HTTP知识 HTTP&#xff08;hypertext transport protocol&#xff09;协议『超文本传输协议』&#xff0c;协议详细规定了浏览器和万维网服务器之间互相通信的规则。 请求报文 请求行: GET、POST /s?ieutf-8...&#xff08;url的一长串参数&#xff09; HTTP/1.1 请求头…

MySQL数据库单表查询中查询条件的写法

1.使用比较运算符作为查询条件 ; !; >; >; <; <; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;字段 from 表名 where Gender “M”; 即挑选出Gender “M” 的教师&#xff0c; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;…

如何使用Android NDK将头像变成“遗像”

看完本文的标题&#xff0c;可能有人要打我。你说黑白的老照片不好吗&#xff1f;非要说什么遗像&#xff0c;我现在就把你变成遗像&#xff01;好了&#xff0c;言归正传。我想大部分人都用过美颜相机或者剪映等软件吧&#xff0c;它们的滤镜功能是如何实现的&#xff0c;有人…

TCP Spurious Retransmission

TCP虚假重传是网络中可能存在丢包问题的一个指标&#xff0c;但并不意味着一定存在丢包。虚假重传指的是当TCP发送方错误地认为原始数据包已丢失时&#xff0c;会不必要地进行重传&#xff0c;而实际上原始数据包已成功到达目的地。 虚假重传可能由多种因素引起&#xff0c;例…

【Linux】进程信号及相关函数/系统调用的简单认识与使用

文章目录 前言一、相关函数/系统调用1. signal2. kill3. abort (库函数)4. raise (库函数)5. alarm 前言 现实生活中, 存在着诸多信号, 比如红绿灯, 上下课铃声…我们在接收到信号时, 就会做出相应的动作. 对于进程也是如此的, 进程也会收到来自 OS 发出的信号, 根据信号的不同…

分布式锁2-Zookeeper分布式锁实战

Zookeeper分布式锁实战 使用curator操作Zookeeper进行实战&#xff1b; curator是什么&#xff1a;Apache Curator包含一套高级API框架和工具类&#xff0c;它 是Apache ZooKeeper 的Java 客户端库。 准备 pom文件引入curtor依赖和zookeeper依赖 <!--curator--> <…