<template>
<div class="chart-container">
<div class="control-area">
<div class="input-group">
<label>X最小值:</label>
<el-input-number
v-model="brushRange.xMin"
:min="xAxisMin"
:max="xAxisMax"
:precision="2"
@change="handleBrushChange"
/>
</div>
<div class="input-group">
<label>X最大值:</label>
<el-input-number
v-model="brushRange.xMax"
:min="xAxisMin"
:max="xAxisMax"
:precision="2"
@change="handleBrushChange"
/>
</div>
<div class="input-group">
<label>Y最小值:</label>
<el-input-number
v-model="brushRange.yMin"
:min="yAxisMin"
:max="yAxisMax"
:precision="2"
@change="handleBrushChange"
/>
</div>
<div class="input-group">
<label>Y最大值:</label>
<el-input-number
v-model="brushRange.yMax"
:min="yAxisMin"
:max="yAxisMax"
:precision="2"
@change="handleBrushChange"
/>
</div>
</div>
<div ref="chart" class="echarts-container"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import * as echarts from 'echarts'
const chart = ref(null)
let chartInstance = null
const axisRange = ref({
x: [0, 10],
y: [0, 20]
})
const brushRange = ref({
xMin: 0,
xMax: 0,
yMin: 0,
yMax: 0
})
const initChart = () => {
chartInstance = echarts.init(chart.value)
const generateData = () => {
return Array.from({length: 100}, (_, i) => [
+(i * 0.1).toFixed(2),
+(Math.sin(i * 0.2) * 10 + 10).toFixed(2)
])
}
const option = {
xAxis: {
type: 'value',
name: 'X轴',
min: axisRange.value.x[0],
max: axisRange.value.x[1],
axisLabel: { formatter: '{value} °' }
},
yAxis: {
type: 'value',
name: 'Y轴',
min: axisRange.value.y[0],
max: axisRange.value.y[1],
axisLabel: { formatter: '{value} N·m' }
},
series: [{
type: 'line',
data: generateData(),
smooth: true,
symbol: 'none',
lineStyle: {
width: 2,
color: '#5470C6'
},
areaStyle: {
color: 'rgba(84, 112, 198, 0.1)'
}
}],
brush: {
toolbox: ['rect', 'clear'],
xAxisIndex: 0,
yAxisIndex: 0,
brushStyle: {
borderWidth: 2,
color: 'rgba(135,206,250,0.3)',
borderColor: '#5470C6'
}
}
}
chartInstance.setOption(option)
updateBrushArea()
chartInstance.on('brush', handleBrushSelect)
}
const updateBrushArea = () => {
chartInstance.dispatchAction({
type: 'brush',
areas: [{
brushType: 'rect',
coordRange: [
[brushRange.value.xMin, brushRange.value.xMax],
[brushRange.value.yMin, brushRange.value.yMax]
],
xAxisIndex: 0,
yAxisIndex: 0
}]
})
}
const handleBrushChange = () => {
brushRange.value.xMin = Math.max(axisRange.value.x[0],
Math.min(brushRange.value.xMin, brushRange.value.xMax))
brushRange.value.xMax = Math.min(axisRange.value.x[1],
Math.max(brushRange.value.xMax, brushRange.value.xMin))
brushRange.value.yMin = Math.max(axisRange.value.y[0],
Math.min(brushRange.value.yMin, brushRange.value.yMax))
brushRange.value.yMax = Math.min(axisRange.value.y[1],
Math.max(brushRange.value.yMax, brushRange.value.yMin))
updateBrushArea()
}
const handleBrushSelect = (params) => {
if (!params.areas || params.areas.length === 0) return
const range = params.areas[0].coordRange
if (!range) return
brushRange.value = {
xMin: +range[0][0].toFixed(2),
xMax: +range[0][1].toFixed(2),
yMin: +range[1][0].toFixed(2),
yMax: +range[1][1].toFixed(2)
}
}
onMounted(() => {
initChart()
window.addEventListener('resize', () => chartInstance?.resize())
})
onBeforeUnmount(() => {
window.removeEventListener('resize', () => chartInstance?.resize())
chartInstance?.dispose()
})
</script>
<style scoped>
.chart-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
}
.control-area {
padding: 20px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
background: #f8f9fa;
border-bottom: 1px solid #eee;
}
.input-group {
display: flex;
align-items: center;
gap: 8px;
label {
white-space: nowrap;
color: #666;
}
:deep(.el-input-number) {
width: 120px;
.el-input__inner {
text-align: center;
}
}
}
.echarts-container {
flex: 1;
min-height: 400px;
}
</style>