共计 12347 个字符,预计需要花费 31 分钟才能阅读完成。
自定义配置折线及柱状图是否显示、色彩、线宽、最小值等
配置
<template>
<a-modal
v-model="visible"
:width="dialogWidth"
:centered="true"
:title="title"
@click="clickOutside"
:destroyOnClose="true"
@cancel="cancelFun"
:keyboard="false"
:maskClosable="false"
@ok="confirmFun"
>
<div @click="clickOutside" style="max-height:530px;overflow:auto;position:relative">
<div class="title row">
<div class="name-item"></div>
<div class="show-item"> 是否显示 </div>
<div class="min-item"> 最小值 </div>
<div class="line-item"> 线宽 </div>
<div class="color-item"> 色彩 </div>
</div>
<div>
<template v-for="(item, ind) in setData">
<div v-if="item.name" class="row-item" :key="ind + item.name">
<div class="name-item">{{item.name}}:</div>
<div class="flex show-item">
<a-switch v-model="item.show" @change="showChange($event, ind)" />
</div>
<div class="flex min-item">
<a-input-number v-model="item.min" @change="minChange($event, ind)"></a-input-number>
<!-- {{ind}} -->
</div>
<div class="flex line-item">
<a-input-number v-model="item.lineWidth" @change="lineWidthChange($event, ind)" :min="1"></a-input-number>
</div>
<div class="flex color-item">
<div
class="color-box"
@click="setColorSelect(ind)"
style="width:10px;height:10px;cursor:pointer;position:relative"
:style="{background: item.color}"
>
<div v-if="showColorInd == ind">
<sketch-picker
id="color-select-box"
class="sketch-picker"
style="width:200px;position:absolute;
left: -100px;
z-index: 10;":style="
ind >= 7
? 'top: -312px;left: -207px;'
: ind >= 2 && ind <= 4
? 'left: -227px;top:-100px'
: ind === 5 || ind === 6
? 'left: -227px;top:-186px'
: 'bottom:-312px;left: -207px;'
"v-model="item.colors"@input="updateColor($event, ind)"
/>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</a-modal>
</template>
<script>
import {Chrome, Sketch} from 'vue-color'
export default {
components: {
'sketch-picker': Sketch,
'chrome-picker': Chrome
},
props: {
title: {
type: String,
default: '曲线配置'
},
dialogWidth: {
type: Number,
default: 600
}
},
data() {
return {
showColorInd: -1,
setData: [],
visible: false
}
},
mounted() {},
methods: {clickOutside(event) {const current = document.getElementById('color-select-box')
let that = this
if (current && event.target.className != 'color-box' && that.showColorInd != -1) {if (!current.contains(event.target)) {that.showColorInd = -1}
}
},
initData(data) {let arr = []
data.forEach(item => {
let obj = arr.find(itm => {return itm.name === item.name})
if (!obj) {
item.min = item.min ? item.min : 0
item.lineWidth = item.lineWidth ? item.lineWidth : 1
item.show = item.show === false ? false : true
item.colorSelectShow = false
item.colors = {hex: item.color}
arr.push(item)
}
})
this.setData = arr
},
lineWidthChange(value, ind) {let obj = Object.assign({}, this.setData[ind], {lineWidth: value})
this.$set(this.setData, ind, obj)
},
setColorSelect(ind) {
// let haveShow = this.setData.find(item => {
// return item.colorSelectShow === true
// })
// let obj = Object.assign({}, this.setData[ind], {colorSelectShow: haveShow ? false : true})
// this.$set(this.setData, ind, obj)
this.showColorInd = ind
},
updateColor(value, ind) {let obj = Object.assign({}, this.setData[ind], {colors: value}, {color: value.hex})
console.log('obj=', obj)
this.$set(this.setData, ind, obj)
},
minChange(value, ind) {// console.log('minChange=', value)
let obj = Object.assign({}, this.setData[ind], {min: value})
this.$set(this.setData, ind, obj)
},
showChange(value, ind) {let obj = Object.assign({}, this.setData[ind], {show: value})
this.$set(this.setData, ind, obj)
},
show(data) {
this.visible = true
this.initData(data)
},
hide() {this.visible = false},
cancelFun() {this.$emit('cancel')
},
confirmFun() {console.log('setData=', this.setData)
this.hide()
this.$emit('ok', this.setData)
}
}
}
</script>
<style scoped lang="less">
.row-item {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ccc;
align-self: center;
margin-bottom: 6px;
padding: 0 20px;
.flex {
min-width: fit-content;
display: flex;
align-items: center;
// justify-content: center;
width: 150px;
}
.show-item {width: 90px;}
.name-item {
font-weight: bold;
font-size: 16px;
min-width: 140px;
text-align: right;
width: fit-content;
}
.min-item {width: 90px;}
.color-item {
width: 80px;
margin: 10px auto;
}
.line-item {margin-left: 10px;}
}
.title {
margin-bottom: 10px;
display: flex;
div {
font-size: 16px;
font-weight: bold !important;
// min-width: 100px;
width: 100px;
text-align: center;
&.show-item {
width: 120px;
padding-left: 40px;
}
&.min-item {width: 105px;}
&.color-item {
width: 108px;
text-align: center;
margin-left: -10px;
}
}
}
</style>
曲线显示组件
<template>
<div>
<div class="toolCharts" v-if="showForm">
<a-form layout="inline">
<a-form-item label="">
<a-checkbox @change="refreshCharts" v-model="showData"> 数据显示 </a-checkbox>
</a-form-item>
<!-- <a-form-item label="">
<a-checkbox @change="refreshCharts" v-model="showMark"> 标记显示 </a-checkbox>
</a-form-item> -->
<a-form-item label="数据字体" v-if="!isAnalysis">
<a-select @change="refreshCharts" v-model="fontsize">
<a-select-option v-for="(item, index) in fontsizeOpt" :key="index" :value="item"
>{{item}}px</a-select-option
>
</a-select>
</a-form-item>
<a-form-item label="标记类型">
<a-select @change="refreshCharts" v-model="tagType">
<a-select-option v-for="(item, index) in tagTypeOpt" :key="index" :value="item.id">{{item.label}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="数据距离">
<a-select style="width:80px" @change="refreshCharts" v-model="dataInterval">
<a-select-option v-for="(item, index) in dataIntervalOpt" :key="index" :value="item">{{item}}</a-select-option>
</a-select>
</a-form-item>
<!-- <a-form-model-item label="缩放比例">
<a-select default-value="fourTree" @change="dragChartsBtn" style="width:100px">
<a-select-option value="fourTree">4:3</a-select-option>
<a-select-option value="sixteen">16:9</a-select-option>
</a-select>
</a-form-model-item> -->
<!-- <a-form-item label="X 轴距离">
<a-select v-model="xInterval">
<a-select-option v-for="(item, index) in xIntervalOpt" :key="index" :value="item">{{item}}</a-select-option>
</a-select>
</a-form-item> -->
</a-form>
</div>
<div
ref="curveChart"
:style="chartsLength > 8 ? {height: chartsHeight +'px'} :''"
class="curveChart"
:class="[isDtfx ?'dtfx-box':'curve-box', clientWidth <= 1600 ?'min-screen':'max-screen']"
></div>
</div>
</template>
<script>
import {handlerRecordShow} from './config'
let myCharts = null
export default {
props: {
showForm: {
type: Boolean,
default: true
}
},
name: 'CurveChart',
data() {
return {
myCharts: null,
showData: true,
showMark: true,
fontsizeOpt: [8, 10, 12, 14, 16],
fontsize: 10,
tagTypeOpt: [{ id: 'circle', label: '圆形'},
{id: 'triangle', label: '三角形'}
],
tagType: 'circle',
dataIntervalOpt: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 20, 32, 60],
dataInterval: 1,
xIntervalOpt: [6],
xInterval: 6,
seriesData: [],
chartsLength: 8,
chartsHeight: 'calc(100vh - 247px)',
legendData: [],
chartsData: {}
// zoomType: 'parameterhw'
}
},
computed: {clientWidth() {return document.body.clientWidth},
isAnalysis() {return this.$route.path.indexOf('Analysis') != -1
},
isCumulative() {
// blockAnalysis 区块剖析
// 是否累计曲线
let name = this.$route.name
// console.log(name)
return name === 'cumulativeProductionCurve' ? true : false
},
isDtfx() {
let name = this.$route.name
if (name === 'blockAnalysis' || name === 'wellGroupAnalysis' || name === 'dynamic-analysis-well') {return true} else {return false}
}
},
mounted() {// this.initCharts();
},
methods: {// dragChartsBtn(value) {// if(value == "sixteen"){
// this.zoomType = 'parameterhwbig'
// }else{
// this.zoomType = 'parameterhw'
// }
// },
initCharts(record) {// console.log('initCharts', record)
let recordData = record.data
// 获取折线数量
this.chartsLength = record.chartsYName.length
if (this.chartsLength > 8) {
let screenChartsHeight = this.$refs.curveChart.clientHeight
let diffValue = this.chartsLength - 8
let curH = this.fontsize > 14 ? 10 : 8
this.chartsHeight = screenChartsHeight + curH * diffValue
// console.log('chartsHeight', this.chartsHeight, screenChartsHeight)
}
let gridArr = []
let xAxisArr = []
let yAxisArr = []
for (var i = 0; i < record.chartsYName.length; i++) {let ch = (91 - 4 * record.chartsYName.length) / record.chartsYName.length
if (i == 0) {gridArr.push({ left: 140, right: 30, top: ch * i + 4 * (i + 1) + 3.8 + '%', height: ch + '%' })
} else {
gridArr.push({
left: 140,
right: 30,
top: ch * i + 4.3 * (i + 1) + 4 + '%',
// width: '92%',
height: ch - 1.5 + '%'
})
}
// 数据的 length <= 20 默认 1 个数据距离
// 数据的 length <= 40 默认 2 个数据距离
let dataInterval = this.dataInterval
const xAxis = {
type: 'category',
gridIndex: i,
data: record.xdata,
boundaryGap: true,
// x 轴轴线
axisLine: {
show: false,
onZero: false,
lineStyle: {
color: '#000',
width: 2
}
},
// x 轴上刻度
axisTick: {
show: false,
// 在设置 boundaryGap 为 true 的前提下,设置 alignWithLabel 使刻度线和标签对齐
alignWithLabel: true
},
// x 轴上文字
axisLabel: {
show: false,
interval: 0,
// interval: 30,
textStyle: {color: '#000'},
formatter: (value, index) => {if ((index + 1) % dataInterval === 0) {return value} else {return ''}
}
},
// 纵向网格线
splitLine: {
show: false,
lineStyle: {color: ['#ddd']
}
}
}
if (i == record.chartsYName.length - 1) {
xAxis.axisLine.show = true
xAxis.axisTick.show = true
xAxis.axisLabel.show = true
}
xAxisArr.push(xAxis)
let obj = recordData.find(item => {
let name = item.labelName || item.name
return record.chartsYName[i] && record.chartsYName[i].indexOf(name) != -1
})
// console.log('obj===', record.chartsYName[i], obj)
const yAxis = {
type: 'value',
gridIndex: i,
min: obj ? obj.min : 0,
name: record.chartsYName[i],
nameLocation: 'center',
nameGap: 88,
nameRotate: 0,
splitNumber: 2,
nameTextStyle: {
color: '#222',
align: 'center',
fontSize: 12
// padding:[0, 30, 0, 30]
},
// y 轴轴线
axisLine: {
show: true,
lineStyle: {
width: 2,
color: 'black'
}
},
axisTick: {
show: true,
lineStyle: {width: 3}
},
// y 轴上刻度文字
axisLabel: {
margin: 10, // 刻度标签与轴线之间的间隔
// left: -28, // 整个 echart 地位
textStyle: {color: '#222'}
},
// 横向网格线
splitLine: {
show: true,
lineStyle: {color: ['#ddd']
}
}
}
// if(i == 1 || i == 2 || i == 5 || i == 7){
// yAxis.splitNumber = 3;
// }
// console.log('yAxis==', yAxis)
yAxisArr.push(yAxis)
}
this.options = {
title: {
text: '综合开发曲线',
left: 'center',
top: 0,
show: false
},
legend: {
show: true,
itemHeight: 4,
itemWidth: 10,
top: 8,
// itemGap: 10,
selectedMode: true, // 勾销图例上的点击事件
data: this.legendData
},
grid: gridArr,
tooltip: {
trigger: 'axis',
confine: true,
axisPointer: {type: 'shadow'}
// formatter: 'Group {a}: ({c})'
},
xAxis: xAxisArr,
yAxis: yAxisArr,
series: this.seriesData
}
this.myCharts = this.$echarts.init(this.$refs.curveChart)
this.myCharts.clear()
this.myCharts.setOption(this.options, true)
myCharts = this.myCharts
window.onresize = function() {if (myCharts) {myCharts.resize()
}
}
},
getSeriesData(data) {
let record = data.data
// console.log("data.data",data.data)
this.seriesData = []
let dLength = data.xdata.length
if (this.dataInterval === 0) {this.dataInterval = Math.ceil(dLength / 15)
}
let interval = this.dataInterval
for (var i = 0; i < record.length; i++) {if (record[i].name && record[i].key !== 'djrzql') {this.legendData.push(record[i].name)
}
let optBar = {name: record[i].name,
type: 'bar',
barMaxWidth: 40,
xAxisIndex: record[i].index,
yAxisIndex: record[i].index,
data: record[i].data,
// barWidth: '10',
itemStyle: {// color: record[i].color, //'yellow'
normal: {
color: '#fff',
borderWidth: record[i].lineWidth || 1,
borderColor: record[i].color
}
},
// 柱子上文字
label: {
normal: {
distance: 2,
show: this.showData,
position: 'top',
fontSize: this.fontsize,
formatter: params => {if ((params.dataIndex + 1) % interval === 0) {return params.value} else {return ''}
}
}
}
}
let optLine = {name: record[i].name,
type: 'line',
xAxisIndex: record[i].index,
yAxisIndex: record[i].index,
data: record[i].data,
smooth: false,
symbol: this.tagType, // triangle circle
// symbolSize: 0.01, // 折线拐点大小
// symbol: 'circle',
// 数据量过大时,symbolSize 非 0.01,label 不显示
symbolSize: dLength >= 300 ? 0.01 : 4,
// 折线款式
lineStyle: {color: record[i].color,
width: record[i].lineWidth || 1,
type: 'solid' // 线型实线、虚线、或圆点
},
itemStyle: {
borderWidth: 1,
borderColor: record[i].color, //'#EE6666'
color: record[i].color //'yellow'
},
label: {
// 折线上文字款式
normal: {
show: this.showData,
position: 'top',
fontSize: this.fontsize,
formatter: params => {if ((params.dataIndex + 1) % interval === 0) {return params.value} else {return ''}
},
color: '#000'
}
}
}
// 日产液数据 label 在下面 日产油在上面
if ((record[i].type == 'line' || record[i].type == 'point') &&
this.seriesData.length > 0 &&
this.seriesData[this.seriesData.length - 1].xAxisIndex == optLine.xAxisIndex
) {optLine.label.normal.position = 'bottom'}
if (record[i].key == 'hs' || record[i].key == 'rzql' || record[i].key == 'zqjkwd') {optLine.label.normal.position = 'bottom'}
if (record[i].type == 'bar') {this.seriesData.push(optBar)
}
if (record[i].type == 'line') {this.seriesData.push(optLine)
}
if (record[i].type == 'point') {
optLine.lineStyle.width = 0
this.seriesData.push(optLine)
}
}
this.initCharts(data)
this.setDragChartsShowParam()},
setData(data) {let record = handlerRecordShow(data)
// let record = data
// console.log('setData =', record)
this.dataInterval = 0
this.chartsData = record
this.getSeriesData(record)
},
refreshCharts() {this.getSeriesData(this.chartsData)
},
// 设置缩放图显示参数
setDragChartsShowParam() {
let obj = {
tagType: this.tagType,
fontsize: this.fontsize,
dataInterval: this.dataInterval
}
this.$emit('setChart', obj)
}
}
}
</script>
<style lang="less" scoped>
.curveChart {
// overflow: hidden;
// overflow-y: scroll;
// border: 1px solid red;
height: calc(100% - 50px) !important;
min-height: 408px;
}
// .dtfx-box {// height: calc(100% - 360px) !important;
// }
// .dtfx-box.min-screen {// height: calc(100% - 370px) !important;
// }
// .curve-box {// height: calc(100% - 240px) !important;
// }
// .curve-box.min-screen {// height: calc(100% - 250px) !important;
// }
.toolCharts {
height: 36px;
overflow: hidden;
// border: 1px solid red;
}
</style>
正文完
发表至: typescript
2023-04-26