自定义配置折线及柱状图是否显示、颜色、线宽、最小值等
image.png
image.png

配置

<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>

云胡不喜
73 声望11 粉丝

前端的忠实粉丝