1.将工具栏修改为二级菜单;2.修改工具栏的样式,添加动效;

This commit is contained in:
zhangquan 2025-07-16 15:55:13 +08:00
parent 816f788240
commit 0753bec5d5
5 changed files with 241 additions and 109 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

View File

@ -1,17 +1,43 @@
<template>
<div class="toolbar-box">
<div class="toolbar-title" :class="{ 'open': isOpen }" :title="isOpen ? '收起工具栏' : '展开工具栏'" @click="isOpen = !isOpen">
<span>工具栏</span>
<el-icon v-if="isOpen" style="font-size: 18px;"><DArrowRight /></el-icon>
<el-icon v-if="!isOpen" style="font-size: 28px;"><DArrowLeft /></el-icon>
</div>
<div class="toolbar-content">
<div v-if="isOpen" class="toolbar-item" v-for="(item, index) in options" :key="index" :title="item.label" @click="bus.emit(`toolbar_${item.name}`, params)">
<img :src="item.icon" alt="" />
<span class="toolbar-label">{{ item.label }}</span>
<div class="toolbar-container">
<div
class="toolbar-thumbnail"
:title="isOpen ? '收起工具栏' : '展开工具栏'"
@click="isOpen = !isOpen"
></div>
<div class="toolbar">
<!-- 一级工具菜单 -->
<div
v-for="tool in options"
:key="tool.id"
class="tool-wrapper"
:class="{'open': isOpen}"
>
<!-- 主工具按钮 -->
<div class="tool-button" @click="tool.name && bus.emit(`toolbar_${tool.name}`, params)">
<el-image class="tool-icon" :src="tool.icon" fit="contain" />
</div>
<!-- 主工具名称 (右侧淡入淡出) -->
<div class="tool-name main-name">{{ tool.label }}</div>
<!-- 二级工具菜单 (左侧淡入淡出) -->
<div v-if="tool.subtools && tool.subtools?.length > 0" class="toolbar submenu">
<!-- 遍历二级工具按钮 -->
<div
v-for="subtool in tool.subtools"
:key="subtool.id"
class="tool-wrapper"
>
<!-- 二级工具按钮 -->
<div class="tool-button" @click="subtool.name && bus.emit(`toolbar_${subtool.name}`, params)">
<el-image class="tool-icon" :src="subtool.icon" fit="contain" />
</div>
<!-- 二级工具名称 (左侧淡入淡出) -->
<div class="tool-name sub-name">{{ subtool.label }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
@ -37,6 +63,12 @@ import {
drawWarehouse
} from './forestFireDraw'
//
import baseDrawIcon from "@/assets/icons/toolbar_base_draw.png";
import forestDrawIcon from "@/assets/icons/toolbar_forest_draw.png";
import weatherIcon from "@/assets/icons/toolbar_weather.png";
import toolbarClearIcon from '@/assets/icons/toolbar_clear.png';
//
import toolbarLocationIcon from '@/assets/icons/toolbar_location.png';
import toolbarPolylineIcon from '@/assets/icons/toolbar_polyline.png';
import toolbarPolygonIcon from '@/assets/icons/toolbar_polygon.png';
@ -47,10 +79,9 @@ import toolbarAttackArrowIcon from '@/assets/icons/toolbar_attack_arrow.png';
import toolbarDoubleArrowIcon from '@/assets/icons/toolbar_double_arrow.png';
import toolbarMeasureDistanceIcon from '@/assets/icons/toolbar_measure_distance.png';
import toolbarMeasureAreaIcon from '@/assets/icons/toolbar_measure_area.png';
//
import toolbarWarehouseIcon from '@/assets/icons/toolbar_warehouse.png';
import toolbarWatersourceIcon from '@/assets/icons/toolbar_watersource.png';
import toolbarClearIcon from '@/assets/icons/toolbar_clear.png';
const props = defineProps({
viewer: {
@ -67,59 +98,93 @@ let toolbarLayer = null
let primitiveList = []
let params = {}
const isOpen = ref(false)
const options = ref([{
name: 'location',
label: '位置',
icon: toolbarLocationIcon
}, {
name: 'polyline',
label: '线',
icon: toolbarPolylineIcon
}, {
name: 'polygon',
label: '面',
icon: toolbarPolygonIcon
}, {
name: 'curvePolygon',
label: '曲面',
icon: toolbarCurvePolygonIcon
}, {
name: 'straightArrow',
label: '直箭头',
icon: toolbarStraightArrowIcon
}, {
name: 'wideArrow',
label: '宽箭头',
icon: toolbarWideArrowIcon
}, {
name: 'attackArrow',
label: '攻击箭头',
icon: toolbarAttackArrowIcon
}, {
name: 'doubleArrow',
label: '双箭头',
icon: toolbarDoubleArrowIcon
}, {
name: 'measureDistance',
label: '测距',
icon: toolbarMeasureDistanceIcon
}, {
name: 'measureArea',
label: '测面',
icon: toolbarMeasureAreaIcon
}, {
name: 'warehouse',
label: '仓库',
icon: toolbarWarehouseIcon
}, {
name: 'watersource',
label: '水源',
icon: toolbarWatersourceIcon
}, {
name: 'clear',
label: '清除',
icon: toolbarClearIcon
}])
const options = ref([
{
id: 1,
icon: baseDrawIcon,
label: '基础绘制',
subtools: [
{
id: 11,
name: 'location',
label: '位置',
icon: toolbarLocationIcon
}, {
id: 12,
name: 'polyline',
label: '线',
icon: toolbarPolylineIcon
}, {
id: 13,
name: 'polygon',
label: '面',
icon: toolbarPolygonIcon
}, {
id: 14,
name: 'curvePolygon',
label: '曲面',
icon: toolbarCurvePolygonIcon
}, {
id: 15,
name: 'straightArrow',
label: '直箭头',
icon: toolbarStraightArrowIcon
}, {
id: 16,
name: 'wideArrow',
label: '宽箭头',
icon: toolbarWideArrowIcon
}, {
id: 17,
name: 'attackArrow',
label: '攻击箭头',
icon: toolbarAttackArrowIcon
}, {
id: 18,
name: 'doubleArrow',
label: '双箭头',
icon: toolbarDoubleArrowIcon
}, {
id: 19,
name: 'measureDistance',
label: '测距',
icon: toolbarMeasureDistanceIcon
}, {
id: 110,
name: 'measureArea',
label: '测面',
icon: toolbarMeasureAreaIcon
}
],
},
{
id: 2,
icon: forestDrawIcon,
label: '森防绘制',
subtools: [
{
name: 'warehouse',
label: '仓库',
icon: toolbarWarehouseIcon
}, {
name: 'watersource',
label: '水源',
icon: toolbarWatersourceIcon
}
]
},
{
id: 3,
icon: weatherIcon,
label: '气象效果',
},
{
id: 4,
icon: toolbarClearIcon,
label: '清空绘制',
name: 'clear',
}
]);
//
const toolbarClear = () => {
@ -186,57 +251,124 @@ watch(() => props.viewer, (v) => {
</script>
<style lang="scss" scoped>
.toolbar-box {
.toolbar-title {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
color: #8EF8FF;
background-color: rgba(7, 111, 111, 0.7);
padding: 4px;
border-radius: 4px;
cursor: pointer;
margin: 0 4px 4px 0;
&.open {
flex-direction: row;
align-items: end;
}
}
}
.toolbar-content {
max-height: 420px;
font-size: 12px;
.toolbar-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
// justify-content: space-around;
.toolbar-item {
width: 48px;
height: 48px;
color: #8EF8FF;
background-color: rgba(7, 111, 111, 0.7);
align-items: center;
.toolbar-thumbnail {
position: absolute;
width: 40px;
height: 40px;
background-image: url(../../../../assets/icons/toolbar_thumbnail.png);
cursor: pointer;
z-index: 1000;
}
.toolbar {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0 4px 4px 0;
border-radius: 4px;
cursor: pointer;
padding: 10px;
z-index: 0;
&:hover {
background-color: rgba(255, 215, 0, 0.5);
/* 通用工具按钮样式 */
.tool-wrapper {
position: relative;
width: 32px;
height: 0px;
background-color: rgba(7, 111, 111, 0.7);
margin-bottom: 2px;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
transition-duration: 0.8s;
&.open {
height: 40px;
opacity: 1;
}
/* 图标 */
.tool-button {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.tool-icon {
width: 20px;
height: 20px;
}
}
/* 名称 */
.tool-name {
position: absolute;
writing-mode: vertical-rl;
letter-spacing: 2px;
color: #8cf8fe;
white-space: nowrap;
z-index: 3;
opacity: 0; /* 默认隐藏 */
pointer-events: none;
transition: opacity 0.3s ease, transform 0.3s ease; /* 动画持续时间和缓动函数 */
}
&:first-child {
border-radius: 16px 16px 0 0;
margin-top: 12px;
padding-top: 12px;
}
&:last-child {
border-radius: 0 0 16px 16px;
padding-bottom: 5px;
}
&:hover {
background-color: rgba($color: #FFD700, $alpha: .5);
}
}
.toolbar-label {
width: 100%;
text-align: center;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
white-space: nowrap;
}
/* 主菜单名称(右侧) */
.main-name {
left: 100%;
transform: translateX(0px); /* 初始位置 */
}
.tool-wrapper:hover > .main-name {
opacity: 1;
transform: translateX(4px); /* 移动到最终位置 */
transition-delay: 0.2s; /* 延迟 */
}
/* 子菜单容器样式 */
.submenu {
position: absolute;
right: 100%;
pointer-events: none;
transition: opacity 0.3s ease, transform 0.3s ease; /* 动画持续时间和缓动函数 */
}
/* 二级工具名称的定位 (左侧) */
.sub-name {
right: 100%;
transform: translateX(0); /* 初始位置 */
}
/* 当主 tool-wrapper 被 hover 且包含二级菜单时,显示二级菜单 */
.tool-wrapper:hover > .submenu {
pointer-events: all;
transition-delay: 0.1s; /* 延迟 */
& > .tool-wrapper {
height: 40px;
opacity: 1;
}
}
/* 当二级 tool-wrapper 被 hover 时,显示二级工具名称 */
/* 注意这里的选择器,因为二级名称在二级 tool-wrapper 内部 */
.submenu > .tool-wrapper:hover > .sub-name {
opacity: 1;
transform: translateX(-8px); /* 移动到最终位置 */
transition-delay: 0.2s; /* 延迟 */
}
}
</style>