echarts自适应(vue3+echarts)

思路:

通过echarts的resize方法加上echarts图表的宽高使用百分比实现echarts图表大小的自适应(为了更好的自适应效果一般建议用来引入echarts组件的的容器的宽高也使用百分比);图表用到的字体和图形的大小也不能写死,而是用当前屏幕的高度和初始屏幕的高度的比值算出一个数值再赋值也就是下文中的transformFontSize方法。

注意:

监听到图表的大小发生变化时需要调用initOption方法,这样图中图形和文字的大小才会发生变化。

具体实现:

1.把echarts封装成组件,以便在要用的地方引入

<template>
  <div :id="name" :style="{ width: width + '%', height: height + '%' }"></div>
</template>
<script setup>
import {reactive, nextTick, onMounted, watch, ref, onBeforeUnmount} from "vue";
import * as echarts from "echarts";
import {useRouter} from "vue-router";
import {transformFontSize} from "@/js/utils";

const router = useRouter();
const props = defineProps({
  name: String,
  width: String,
  color: Array,
  height: String,
  data: Object,
  title: String
});
// const data = reactive([]);
let myChart = null;
onMounted(() => {
  initChart();
});

watch(() => props.data.data_y, (newValue, oldValue) => {
  if(myChart){
    initOption();
  }
}, {immediate: true, deep: true});

function initChart() {
  let container = document.getElementById(props.name);
  myChart = echarts.init(container);
  initOption()
  window.addEventListener("resize", resizeMyChart);
}

const initOption = () => {
  // 绘制图表
  let option = {
    tooltip: {
      trigger: 'item',// axis显示该列下所有坐标轴对应数据,item只显示该点数据
      formatter: (params) => {
        if (props.name === "Bar_dqzc") {
          return params.marker + ' ' + params.name + ' ' + params.value + "人"
        } else if (props.name === "Bar_yhsb") {
          return params.marker + ' ' + params.name + ' ' + params.value + "台"
        }
      },
    },
    // legend: {
    //   top: "3%",
    //   right: "3%",
    //   data: [props.title],
    //   textStyle: {
    //     color: props.color, // 设置图例文字颜色为红色
    //     fontSize: transformFontSize(13),
    //   },
    //   itemHeight: transformFontSize(13),
    //   itemWidth: transformFontSize(30),
    // },
    xAxis: {
      data: props.data.data_x,
      axisLine: {
        lineStyle: {
          color: "#fff",
        },
      },
      axisLabel: {
        color: "#fff",
        fontSize: transformFontSize(13),
        margin: transformFontSize(10),
        // fontWeight: 'bold' // 设置字体粗细为粗体
        // rotate: 35,//35度角倾斜显示
      },
      axisTick: {
        show: true,//x轴齿状
      },
    },
    yAxis: {
      // nameTextStyle: {
      //   color: "#95B3CF",
      //   fontSize: 16,
      // },
      axisLine: {
        show: true,
        lineStyle: {
          color: "#fff",
          width: transformFontSize(1.5)
        },
      },
      axisLabel: {
        color: "#fff",
        fontSize: transformFontSize(13),
        // fontWeight: 'bold' // 设置字体粗细为粗体
      },
      splitLine: {
        show: false,
        lineStyle: {
          color: "#0177d4",
        },
      },
      // interval: 100,
      // max: 500,
    },
    series: [
      // 底部
      {
        z: 2,
        type: 'pictorialBar',
        symbol: 'circle',
        symbolOffset: ['0%', '10%'],
        symbolSize: [transformFontSize(15), transformFontSize(6)],
        toolltip: {
          show: false
        },
        itemStyle: {
          color: props.color[1]
        },
        data: props.data.data_y,
      },
      //内容区域
      {
        z: 1,
        type: 'bar',
        barWidth: transformFontSize(15),
        data: props.data.data_y,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(
              0,
              0,
              0,
              1,
              [
                {
                  offset: 0,
                  color: props.color[1],
                },
                {
                  offset: 0.5,
                  color: props.color[0],
                },
              ],
              false
          ),
        },
      },
      //内容的顶部
      {
        z: 3,
        type: 'pictorialBar',
        symbol: 'circle',
        symbolPosition: 'end',
        symbolOffset: ['0%', '-50%'],
        symbolSize: [transformFontSize(15), transformFontSize(6)],
        toolltip: {
          show: false,
        },
        itemStyle: {
          color: props.color[0]
        },
        data: props.data.data_y,
      }


      //长方形代码
      // {
      //   name: props.title,
      //   type: "bar",
      //   barWidth: transformFontSize(15),
      //   // itemStyle: {
      //   //   normal: {
      //   //     color: props.color
      //   //   },
      //   // },
      //   itemStyle: {
      //     color: new echarts.graphic.LinearGradient(
      //         0,
      //         0,
      //         0,
      //         1,
      //         [
      //           {
      //             offset: 0,
      //             color: props.color[1],
      //           },
      //           {
      //             offset: 0.5,
      //             color: props.color[0],
      //           },
      //         ],
      //         false
      //     ),
      //   },
      //   data: props.data.data_y,
      // },
    ],
    grid: {
      top: "10%",
      left: "15%",
      right: "15",
      bottom: "12%",
      // bottom: "20%",
    }
  };
  myChart.setOption(option);
}

function resizeMyChart() {
  initOption()
  myChart.resize();
}

onBeforeUnmount(() => {
  window.removeEventListener("resize", resizeMyChart);
  myChart = null;
})
</script>

<style scoped lang="less"></style>

2.引入组件

<div class="echarts">
    <Bar :color="['#38F8C7','#259276']" :name="'Bar_dqzc'" :width="'100'" 
         :height="'100'" :data="barData"
         :title="'地区注册用户top5'" v-if="barData.data_y.length!==0">
    </Bar>
</div>

3.传入组件数据格式

const barData = reactive({
  // data_x: ["北京", "上海", "广州", "重庆", "河北"],
  data_x: [],
  data_y: []
})

4.组件中使用的transformFontSize方法

/*
*根据当前屏幕大小换算对应的px
* */
export function transformFontSize(fontsize) {
    // 获取屏幕宽度
    const height = window.innerHeight || document.body.clientHeight
    const ratio = height / 953
    // 取下整
    return parseInt(fontsize * ratio)
}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值