| | |
| | | .map { |
| | | position: relative; |
| | | width: 52vw; |
| | | height: 80vh; |
| | | height: 72vh; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | justify-content: center; |
| | |
| | | background: #f0f9eb; |
| | | } |
| | | .container { |
| | | width: 100vh; |
| | | width: 52vw; |
| | | height: 72vh; |
| | | position: absolute; |
| | | /*background: #8c939d;*/ |
| | |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <body id="app1"> |
| | | <!--<header>--> |
| | | <!-- 环形穿梭车智能系统--> |
| | | <!--</header>--> |
| | |
| | | <!-- <div class="outer-ring"></div>--> |
| | | <!-- <div v-for="track in energyGatheringRing" class="inner-ring" :style="{ borderColor: track.trackColor , boxShadow : 'inset 0 0 30px '+track.radiationColor+', 0 0 20px '+track.radiationColor}"></div>--> |
| | | <!-- <div v-for="track in energyGatheringRing" class="outer-ring" :style="{ borderColor: track.trackColor , boxShadow : 'inset 0 0 30px '+track.radiationColor+', 0 0 20px '+track.radiationColor}"></div>--> |
| | | <svg class="container"> |
| | | <!-- <path d="M 100,250--> |
| | | <!-- L 100,800--> |
| | | <!-- C 100,800 100,850 150,850--> |
| | | <!-- C 150,850 200,850 200,800--> |
| | | <!-- L 200,250--> |
| | | <!-- C 200,250 200,200 250,200--> |
| | | <!-- L 1100,200--> |
| | | <!-- C 1100,200 1150,200 1150,150--> |
| | | <!-- C 1150,150 1150,100 1100,100--> |
| | | <!-- L 250,100--> |
| | | <!-- C 250,100 90,90 100,250 z"--> |
| | | <!-- style="fill:none; stroke:blue; stroke-width:4;" />--> |
| | | <svg class="container" |
| | | viewBox="0 0 1200 850" |
| | | preserveAspectRatio="xMidYMid meet"> |
| | | <path d="M 1200,750 |
| | | L 1200,100 |
| | | C 1200,100 1200,50 1150,50 |
| | |
| | | " |
| | | style="fill:none; stroke:blue; stroke-width:4;" /> |
| | | </svg> |
| | | <!-- <div class="bus-station">--> |
| | | <!-- <div v-for="(item,i) in devpPos1" class="bus-item-top" :style="'left:' + (75 + i * 15) + 'px'">{{item.dev_no}}</div>--> |
| | | <!-- </div>--> |
| | | <!-- <div class="bus-station" style="flex-direction: column">--> |
| | | <!-- <div v-for="(item,i) in devpPos2" class="bus-item-left" :style="'top:' + (200 + i * 50) + 'px'">{{item.dev_no}}</div>--> |
| | | <!-- </div>--> |
| | | <!-- <div class="bus-station" style="flex-direction: column">--> |
| | | <!-- <div v-for="(item,i) in devpPos3" class="bus-item-left2" :style="'top:' + (100 + i * 10) + 'px'">{{item.dev_no}}</div>--> |
| | | <!-- </div>--> |
| | | <!-- Stations on outer ring--> |
| | | <div v-for="station in tableDataDev" class="station" :style="{ top: station.valueY + 'px', left: station.valueX + 'px' }">{{ station.index }}</div> |
| | | <!-- <div v-for="station in tableDataDev" class="station" :style="{ top: station.valueY + 'px', left: station.valueX + 'px' , backgroundColor: station.modeColor}">{{ station.index }}</div>--> |
| | | <div v-for="station in tableDataDev" class="station" :style="{ |
| | | top: convertToCSSPosition(station.valueX, station.valueY).y + 'px', |
| | | left: convertToCSSPosition(station.valueX, station.valueY).x + 'px', |
| | | backgroundColor: station.modeColor}">{{ station.index }}</div> |
| | | <div> |
| | | <el-switch |
| | | style="display: block" |
| | |
| | | </el-switch> |
| | | </div> |
| | | <!-- Buses --> |
| | | <div v-for="bus in tableDataRgv" class="bus" :style="{ top: bus.valueY + 'px', left: bus.valueX + 'px' , borderColor: bus.modeColor, backgroundColor: bus.statusColor}">{{ bus.index }}</div> |
| | | <!-- <div v-for="bus in tableDataRgv" class="bus" :style="{ top: bus.valueY + 'px', left: bus.valueX + 'px' , borderColor: bus.modeColor, backgroundColor: bus.statusColor}">{{ bus.index }}</div>--> |
| | | <div v-for="bus in tableDataRgv" class="bus" :style="{ |
| | | top: convertToCSSPosition(bus.valueX, bus.valueY).y + 'px', |
| | | left: convertToCSSPosition(bus.valueX, bus.valueY).x + 'px', |
| | | borderColor: bus.modeColor, backgroundColor: bus.statusColor}">{{ bus.index }}</div> |
| | | </div> |
| | | |
| | | <!-- Left Task Bar --> |
| | |
| | | </div> |
| | | |
| | | <script> |
| | | // 在Vue实例外获取body尺寸 |
| | | function getBodySize() { |
| | | return { |
| | | width: document.body.clientWidth, |
| | | height: document.body.clientHeight |
| | | }; |
| | | } |
| | | var app = new Vue({ |
| | | el: '#app', |
| | | data: { |
| | | containerSize: { width: 0, height: 0}, |
| | | bodySize: { width: 0, height: 0 }, |
| | | activeNames: ['1'], |
| | | valueLeft: '0', |
| | | valueLeft1: '0', |
| | |
| | | watch: { |
| | | |
| | | }, |
| | | |
| | | // 在 mounted 中初始化尺寸和监听 |
| | | mounted() { |
| | | this.updateContainerSize(); |
| | | this.updateBodySize(); |
| | | window.addEventListener('resize', this.handleResize); |
| | | }, |
| | | beforeDestroy() { |
| | | window.removeEventListener('resize', this.handleResize); |
| | | }, |
| | | computed: { |
| | | mappedStations() { |
| | | return this.tableDataDev.map(station => ({ |
| | | ...station, |
| | | position: this.convertToCSSPosition(station.valueX, station.valueY) |
| | | })); |
| | | } |
| | | }, |
| | | methods: { |
| | | init(){ |
| | | this.getTableDataRgv() |
| | |
| | | }, 1000) |
| | | }, |
| | | |
| | | // 获取容器实际尺寸 |
| | | updateContainerSize() { |
| | | const mapEl = this.$el.querySelector('.map'); |
| | | this.containerSize = { |
| | | width: mapEl.clientWidth, |
| | | height: mapEl.clientHeight |
| | | }; |
| | | }, |
| | | |
| | | // 更新body尺寸 |
| | | updateBodySize() { |
| | | this.bodySize = getBodySize(); |
| | | }, |
| | | |
| | | // 坐标转换函数 |
| | | convertToCSSPosition(svgX, svgY) { |
| | | const svgWidth = 1200; // SVG 原始宽度 |
| | | let svgWidthR = 0; // |
| | | const svgHeight = 850; // SVG 原始高度 |
| | | let svgHeightR = 0; // |
| | | if (svgX>svgWidth/2){ |
| | | svgWidthR = (((svgX-svgWidth/2)/svgWidth) * this.containerSize.width) + this.bodySize.width/2 - this.bodySize.width*((1-0.52)/2); |
| | | } else { |
| | | svgWidthR = this.bodySize.width/2 - (((svgWidth/2 - svgX)/svgWidth) * this.containerSize.width) - this.bodySize.width*((1-0.52)/2); |
| | | } |
| | | if (svgY>svgHeight/2){ |
| | | svgHeightR = (((svgY-svgHeight/2)/svgHeight) * this.containerSize.height) + this.bodySize.height/2 - this.bodySize.height*((1-0.72)/2); |
| | | } else { |
| | | svgHeightR = this.bodySize.height/2 - (((svgHeight/2 - svgY)/svgHeight) * this.containerSize.height) - this.bodySize.height*((1-0.72)/2); |
| | | } |
| | | return { |
| | | x: svgWidthR, |
| | | y: svgHeightR |
| | | }; |
| | | }, |
| | | |
| | | handleZoom(e) { |
| | | const scaleDelta = e.deltaY > 0 ? 0.9 : 1.1; |
| | | const currentScale = this.scale || 1; |
| | | const newScale = Math.max(0.5, Math.min(2, currentScale * scaleDelta)); |
| | | |
| | | // 应用缩放 |
| | | const svgEl = this.$el.querySelector('.container'); |
| | | svgEl.style.transform = `scale(${newScale})`; |
| | | this.scale = newScale; |
| | | }, |
| | | verifyPassword(callback) { |
| | | this.$prompt('请输入管理员密码: root', '验证', { |
| | | confirmButtonText: '确定', |
| | |
| | | that.energyGatheringRing = res.data |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | // 处理窗口大小变化 |
| | | handleResize: _.debounce(function() { |
| | | this.updateContainerSize(); |
| | | this.updateBodySize(); |
| | | }, 100) |
| | | } |
| | | }) |
| | | |