自定义配置折线及柱状图是否显示、色彩、线宽、最小值等
配置
<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 = nullexport 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>