echarts 圆柱体(带头部阴影)

<template>
  <div :id="echartsId"></div>
</template>
<script setup>
  import * as echarts from 'echarts'
  import { reactive, ref, onMounted, defineProps, watch, onUnmounted } from 'vue'
  const props = defineProps({
    echartsBool: {
      type: Boolean,
      default: false,
    },
    echartsId: {
      type: String,
      default: 'echartsId',
    },
    // 柱状宽度
    echartsBarWidth: {
      type: String,
      default: '30%',
    },
    // x轴数据
    xAxisDataJson: {
      type: Array,
      default: () => {
        return []
      },
    },
    // y轴数据
    yAxisJson: {
      type: Object,
      default: () => {
        return {
          name: '单位:数量',
        }
      },
    },
    // y轴字体样式
    nameTextStyle: {
      type: Object,
      default: () => {
        return {
          color: '#fff',
          fontSize: 14,
          fontWeight: 400,
          verticalAlign: 'bottom',
          // 左上字体位置
          padding: [0, -20, 10, 20],
          fontFamily: 'PingFang SC',
        }
      },
    },
    //  柱状图颜色
    barColorJson: {
      type: Object,
      default: () => {
        return {
          headColor1: 'rgba(43,194,195,1)',
          headColor2: 'rgba(43,194,195,0.5)',
          upBarColor: 'rgba(30,70,76,0.5)',
          bottomBarColor1: 'rgba(43,194,195,1)',
          bottomBarColor2: 'rgba(43,194,195,0.5)',
          topColor: 'rgba(30,70,76,1)',
        }
      },
    },
    // 数据展示
    dataList: {
      type: Array,
      default: () => {
        return [
          {
            name: '公司1',
            value: 73,
            max: 100,
          },
          {
            name: '公司2',
            value: 18,
            max: 100,
          },
          {
            name: '公司3',
            value: 43,
            max: 100,
          },
          {
            name: '公司4',
            value: 66,
            max: 100,
          },
        ]
      },
    },
    // legend方向
    legendDirection: {
      type: Object,
      default: () => {
        return {
          bottom: '0',
          top: '0',
          left: '0',
          right: '0',
        }
      },
    },
    // grid方向
    gridDirection: {
      type: Object,
      default: () => {
        return {
          bottom: '35',
          top: '25%',
          right: '0%',
          left: '10%',
        }
      },
    },
    // dataListLength 大小==长度约束柱状宽度  定时器==个数 两个不会同时出现大小暂时不用
    dataListLength: {
      type: Number,
      default: 8,
    },
  })
  const dataKey = reactive(['topData', 'bottomBar', 'bottomCircle', 'middleCircle', 'upBar'])
  const dataJson = ref({
    topData: [], // 头部数据
    bottomBar: [], // 底部立体柱子
    bottomCircle: [], // 底下圆片
    middleCircle: [], // 中间圆片
    upBar: [], // 上边的柱子
  })
  const dataClear = () => {
    dataKey.forEach((el) => {
      dataJson.value[el] = []
    })
  }
  const initDataAction = () => {
    dataClear()
    props.dataList.forEach((item) => {
      dataJson.value.topData.push({
        name: '',
        value: item.max,
        symbolPosition: 'end',
        itemStyle: {
          normal: {
            color: new echarts.graphic.LinearGradient(
              0,
              0,
              0,
              1,
              [
                {
                  offset: 0,
                  color: props.barColorJson.topColor,
                },
                {
                  offset: 1,
                  color: props.barColorJson.topColor,
                },
              ],
              false
            ),
          },
        },
      })
      dataJson.value.bottomBar.push({
        value: item.value,
        itemStyle: {
          normal: {
            color: new echarts.graphic.LinearGradient(
              1,
              0,
              0,
              0,
              [
                {
                  offset: 0,
                  color: props.barColorJson.bottomBarColor1,
                },
                {
                  offset: 1,
                  color: props.barColorJson.bottomBarColor2,
                },
              ],
              false
            ),
          },
        },
        name: item.name,
      })
      dataJson.value.bottomCircle.push({
        name: item.name,
        value: item.max,
        itemStyle: {
          normal: {
            color: new echarts.graphic.LinearGradient(
              1,
              0,
              0,
              0,
              [
                {
                  offset: 0,
                  color: props.barColorJson.headColor1,
                },
                {
                  offset: 1,
                  color: props.barColorJson.headColor2,
                },
              ],
              false
            ),
          },
        },
      })
      dataJson.value.middleCircle.push({
        name: item.name,
        value: item.value,
        symbolPosition: 'end',
        itemStyle: {
          normal: {
            color: new echarts.graphic.LinearGradient(
              1,
              0,
              0,
              0,
              [
                {
                  offset: 0,
                  color: props.barColorJson.headColor1,
                },
                {
                  offset: 1,
                  color: props.barColorJson.headColor2,
                },
              ],
              false
            ),
          },
        },
      })
      dataJson.value.upBar.push({
        name: item.name,
        value: item.max - item.value,
        itemStyle: {
          normal: {
            color: props.barColorJson.upBarColor,
          },
        },
      })
    })
  }
  const option = ref({
    backgroundColor: 'transparent',
    dataZoom: [
      {
        show: false, // 是否显示滑动条
        xAxisIndex: 0, // 表示从X轴的零刻度线开始的
        startValue: 0, // 数据窗口范围的起始数值
        endValue: props.dataListLength - 1, // 数据窗口范围的结束数值(一次性展示几个)
      },
    ],
    tooltip: {
      trigger: 'item',
      backgroundColor: 'rgba(43,194,195,0.5)',
      borderColor: 'rgba(43,194,195,1)',
      borderWidth: 2,
      padding: 5,
      textStyle: {
        color: 'rgba(43,194,195,1)',
        fontSize: 18,
        width: 300,
        height: 40,
      },
      formatter: function (params) {
        let tooltipBox = ''
        tooltipBox += '<div>' + params.name + '</div>'
        tooltipBox += '<div>' + params.seriesName + ':' + params.value + '%</div>'
        return tooltipBox
      },
      // formatter: '{c}' + '%',
      extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);',
      // 自定义的 CSS 样式
    },
    grid: {
      right: props.gridDirection.right,
      top: props.gridDirection.top,
      bottom: props.gridDirection.bottom,
      left: props.gridDirection.left,
    },
    // 设置图例
    legend: {
      icon: 'roundRect',
      show: true,
      data: ['得分率'],
      textStyle: {
        color: '#fff',
        fontSize: '14',
      },
      top: props.legendDirection.top,
      bottom: props.legendDirection.bottom,
      left: props.legendDirection.left,
      right: props.legendDirection.right,
    },
    xAxis: {
      type: 'category',
      data: props.xAxisDataJson,
      axisTick: {
        show: true,
        type: 'value',
        //文字在刻度中间
        alignWithLabel: true,
      },
      axisLine: {
        show: true,
      },
      // 字体样式
      axisLabel: {
        show: true,
        textStyle: {
          color: '#fff',
          fontSize: 12,
        },
        lineHeight: '50', // 行高
        interval: 0,
        rotate: -45,
        formatter: function (value) {
          // 当文字长度大于2时,使用slice方法截取字符串并拼接省略号;否则直接返回原文字
          if (value.length > 5) {
            return `${value.slice(0, 5)}...`
          } else {
            return value
          }
        },
      },
    },
    yAxis: {
      type: 'value',
      name: props.yAxisJson.name,
      nameTextStyle: props.nameTextStyle,
      max: 100,
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed', // 将轴线设置为虚线
          color: '#35414C',
        },
      },
      axisTick: {
        show: true,
      },
      axisLine: {
        show: true,
      },
      axisLabel: {
        show: true,
        // 字体样式
        color: '#fff', //更改坐标轴文字颜色
        fontSize: 12, //更改坐标轴文字大小
      },
    },
    // 宽高
    // symbolSize: [20, 5],
    // xy偏移
    // symbolOffset: [0, -3],
    // label 展示
    //silent
    series: [
      // 头
      {
        name: '得分率',
        type: 'pictorialBar',
        // 做了滚动暂时不用了
        // symbolSize: props.dataList?.length > props.dataListLength ? ['30%', '4.5%'] : [30, 6],
        symbolSize: [30, 6],
        symbolOffset: [0, -3],
        z: 12,
        data: dataJson.value.topData,
        itemStyle: {
          color: 'rgba(43,194,195,0.7)', // 设置图标颜色为红色
        },
        silent: true,
      },
      //底部立体柱
      {
        name: '得分率',
        stack: '1',
        type: 'bar',
        silent: false,
        // 做了滚动暂时不用了
        // barWidth: props.dataList?.length > props.dataListLength ? props.echartsBarWidth : 30,
        barWidth: 30,
        data: dataJson.value.bottomBar,
        itemStyle: {
          normal: {
            color: {
              x: 1,
              y: 0,
              x2: 0,
              y2: 0,
              type: 'linear',
              global: false,
              colorStops: [
                {
                  //第一节下面
                  offset: 0,
                  color: 'rgba(43,194,195,0.5)',
                },
                {
                  offset: 1,
                  color: '#2BC2C3',
                },
              ],
            },
          },
        },
      },
      //最底下的圆片
      {
        name: '得分率',
        type: 'pictorialBar',
        // 做了滚动暂时不用了
        // symbolSize: props.dataList?.length > props.dataListLength ? ['30%', '5%'] : [30, 8],
        symbolSize: [30, 8],
        symbolOffset: [0, 3],
        z: 12,
        itemStyle: {
          normal: {
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: 'rgba(43,194,195,1)',
              },
              {
                offset: 1,
                color: 'rgba(43,194,195,1)',
              },
            ]),
          },
        },
        data: dataJson.value.bottomCircle,
        silent: true,
      },
      // 中间圆片
      {
        name: '得分率',
        type: 'pictorialBar',
        // 做了滚动暂时不用了
        // symbolSize: props.dataList?.length > props.dataListLength ? ['30%', '5%'] : [30, 8],
        symbolSize: [30, 8],
        symbolOffset: [0, -3],
        itemStyle: {
          normal: {
            color: new echarts.graphic.LinearGradient(
              0,
              0,
              0,
              1,
              [
                {
                  offset: 0,
                  color: 'rgba(43,194,195,1)',
                },
                {
                  offset: 1,
                  color: 'rgba(43,194,195,1)',
                },
              ],
              false
            ),
          },
        },
        z: 12,
        data: dataJson.value.middleCircle,
      },
      //上部立体柱
      {
        name: '得分率',
        stack: '1',
        type: 'bar',
        itemStyle: {
          normal: {
            color: 'rgba(43,194,195,1)',
            opacity: 0.7,
          },
        },
        // 顶部展示
        // label: {
        //   show: true,
        //   position: "top", //top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight
        //   distance: 20,
        //   color: "#FFFE00",
        //   fontSize: 30,
        //   formatter: function (item) {
        //     var a = 100;
        //     return a - item.value + "%";
        //   },
        // },
        silent: true,
        // 做了滚动暂时不用了
        // barWidth: props.dataList?.length > props.dataListLength ? props.echartsBarWidth : 30,
        barWidth: 30,
        data: dataJson.value.upBar,
      },
    ],
  })
  let bar = ''
  const initData = () => {
    // datalist操作
    initDataAction()
    option.value.series?.forEach((el, index) => {
      el.data = dataJson.value[dataKey[index]]
    })
    option.value.xAxis.data = []
    option.value.xAxis.data = props.xAxisDataJson
    // 设置配置项
    bar.setOption(option.value)
    window.addEventListener('resize', bar.resize)
    if (props.dataList.length > props.dataListLength - 1) {
      startAnimation()
    }
  }
  let timer = '' // 定时器
  const stopAnimation = () => {
    clearInterval(timer)
    timer = null
  }
  // 通过datalist进行长度判断是否滚动
  const startAnimation = () => {
    timer = setInterval(() => {
      // 每次向后滚动一个,最后一个从头开始
      if (option.value.dataZoom[0].endValue === props.dataList?.length - 1) {
        option.value.dataZoom[0].startValue = 0 // 数据窗口范围的起始数值
        option.value.dataZoom[0].endValue = props.dataListLength - 1 // 数据窗口范围的结束数值
      } else {
        option.value.dataZoom[0].startValue = option.value.dataZoom[0].startValue + 1 // 数据窗口范围的起始数值
        option.value.dataZoom[0].endValue = option.value.dataZoom[0].endValue + 1 // 数据窗口范围的结束数值
      }
      bar.setOption(option.value)
    }, 3000)
  }
  onMounted(() => {
    let chartDom = document.getElementById(`${props.echartsId}`)
    bar = echarts.init(chartDom)
    initData()
  })
  onUnmounted(() => {
    stopAnimation()
  })
  watch(
    () => props.echartsBool,
    () => {
      // 清除之前的视图
      bar.clear()
      stopAnimation()
      initData()
    }
  )
</script>

效果:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值