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> <template>
<div class="toolbar-box"> <div class="toolbar-container">
<div class="toolbar-title" :class="{ 'open': isOpen }" :title="isOpen ? '收起工具栏' : '展开工具栏'" @click="isOpen = !isOpen"> <div
<span>工具栏</span> class="toolbar-thumbnail"
<el-icon v-if="isOpen" style="font-size: 18px;"><DArrowRight /></el-icon> :title="isOpen ? '收起工具栏' : '展开工具栏'"
<el-icon v-if="!isOpen" style="font-size: 28px;"><DArrowLeft /></el-icon> @click="isOpen = !isOpen"
</div> ></div>
<div class="toolbar-content"> <div class="toolbar">
<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="" /> <div
<span class="toolbar-label">{{ item.label }}</span> 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>
</div> </div>
</div>
</template> </template>
<script setup> <script setup>
@ -37,6 +63,12 @@ import {
drawWarehouse drawWarehouse
} from './forestFireDraw' } 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 toolbarLocationIcon from '@/assets/icons/toolbar_location.png';
import toolbarPolylineIcon from '@/assets/icons/toolbar_polyline.png'; import toolbarPolylineIcon from '@/assets/icons/toolbar_polyline.png';
import toolbarPolygonIcon from '@/assets/icons/toolbar_polygon.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 toolbarDoubleArrowIcon from '@/assets/icons/toolbar_double_arrow.png';
import toolbarMeasureDistanceIcon from '@/assets/icons/toolbar_measure_distance.png'; import toolbarMeasureDistanceIcon from '@/assets/icons/toolbar_measure_distance.png';
import toolbarMeasureAreaIcon from '@/assets/icons/toolbar_measure_area.png'; import toolbarMeasureAreaIcon from '@/assets/icons/toolbar_measure_area.png';
//
import toolbarWarehouseIcon from '@/assets/icons/toolbar_warehouse.png'; import toolbarWarehouseIcon from '@/assets/icons/toolbar_warehouse.png';
import toolbarWatersourceIcon from '@/assets/icons/toolbar_watersource.png'; import toolbarWatersourceIcon from '@/assets/icons/toolbar_watersource.png';
import toolbarClearIcon from '@/assets/icons/toolbar_clear.png';
const props = defineProps({ const props = defineProps({
viewer: { viewer: {
@ -67,59 +98,93 @@ let toolbarLayer = null
let primitiveList = [] let primitiveList = []
let params = {} let params = {}
const isOpen = ref(false) const isOpen = ref(false)
const options = ref([{ const options = ref([
name: 'location', {
label: '位置', id: 1,
icon: toolbarLocationIcon icon: baseDrawIcon,
}, { label: '基础绘制',
name: 'polyline', subtools: [
label: '线', {
icon: toolbarPolylineIcon id: 11,
}, { name: 'location',
name: 'polygon', label: '位置',
label: '面', icon: toolbarLocationIcon
icon: toolbarPolygonIcon }, {
}, { id: 12,
name: 'curvePolygon', name: 'polyline',
label: '曲面', label: '线',
icon: toolbarCurvePolygonIcon icon: toolbarPolylineIcon
}, { }, {
name: 'straightArrow', id: 13,
label: '直箭头', name: 'polygon',
icon: toolbarStraightArrowIcon label: '面',
}, { icon: toolbarPolygonIcon
name: 'wideArrow', }, {
label: '宽箭头', id: 14,
icon: toolbarWideArrowIcon name: 'curvePolygon',
}, { label: '曲面',
name: 'attackArrow', icon: toolbarCurvePolygonIcon
label: '攻击箭头', }, {
icon: toolbarAttackArrowIcon id: 15,
}, { name: 'straightArrow',
name: 'doubleArrow', label: '直箭头',
label: '双箭头', icon: toolbarStraightArrowIcon
icon: toolbarDoubleArrowIcon }, {
}, { id: 16,
name: 'measureDistance', name: 'wideArrow',
label: '测距', label: '宽箭头',
icon: toolbarMeasureDistanceIcon icon: toolbarWideArrowIcon
}, { }, {
name: 'measureArea', id: 17,
label: '测面', name: 'attackArrow',
icon: toolbarMeasureAreaIcon label: '攻击箭头',
}, { icon: toolbarAttackArrowIcon
name: 'warehouse', }, {
label: '仓库', id: 18,
icon: toolbarWarehouseIcon name: 'doubleArrow',
}, { label: '双箭头',
name: 'watersource', icon: toolbarDoubleArrowIcon
label: '水源', }, {
icon: toolbarWatersourceIcon id: 19,
}, { name: 'measureDistance',
name: 'clear', label: '测距',
label: '清除', icon: toolbarMeasureDistanceIcon
icon: toolbarClearIcon }, {
}]) 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 = () => { const toolbarClear = () => {
@ -186,57 +251,124 @@ watch(() => props.viewer, (v) => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.toolbar-box { .toolbar-container {
.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;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-wrap: wrap; align-items: center;
// justify-content: space-around;
.toolbar-item { .toolbar-thumbnail {
width: 48px; position: absolute;
height: 48px; width: 40px;
color: #8EF8FF; height: 40px;
background-color: rgba(7, 111, 111, 0.7); background-image: url(../../../../assets/icons/toolbar_thumbnail.png);
cursor: pointer;
z-index: 1000;
}
.toolbar {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; padding: 10px;
align-items: center; z-index: 0;
margin: 0 4px 4px 0;
border-radius: 4px;
cursor: pointer;
&: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; .main-name {
text-overflow: ellipsis; left: 100%;
overflow: hidden; transform: translateX(0px); /* 初始位置 */
word-break: break-all; }
white-space: nowrap; .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> </style>