vue3+echarts实现3d环形图

实现效果如下:

实现步骤:

1.安装echarts-gl

npm i echarts-gl

2.在页面定义容器,本css是tailwind css,width和height依据你所需要的图形大小自己定义

<div class="w-full h-[330px]" ref="pieChart"></div>

3.在js文件中引入echarts和echarts-gl

import * as echarts from "echarts";
import 'echarts-gl'

4.完整js代码

function getParametricEquation(
    startRatio,
    endRatio,
    isSelected,
    isHovered,
    k,
    height,
  ) {
    // 计算
    let midRatio = (startRatio + endRatio) / 2

    let startRadian = startRatio * Math.PI * 2
    let endRadian = endRatio * Math.PI * 2
    let midRadian = midRatio * Math.PI * 2

    // 如果只有一个扇形,则不实现选中效果。
    if (startRatio === 0 && endRatio === 1) {
      isSelected = false
    }

    // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
    k = typeof k !== 'undefined' ? k : 1 / 3

    // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
    let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
    let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0

    // 计算高亮效果的放大比例(未高亮,则比例为 1)
    let hoverRate = isHovered ? 1.05 : 1

    // 返回曲面参数方程
    return {
      u: {
        min: -Math.PI,
        max: Math.PI * 3,
        step: Math.PI / 32,
      },

      v: {
        min: 0,
        max: Math.PI * 2,
        step: Math.PI / 20,
      },

      x: function (u, v) {
        if (u < startRadian) {
          return (
            offsetX +
            Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          )
        }
        if (u > endRadian) {
          return (
            offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          )
        }
        return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
      },

      y: function (u, v) {
        if (u < startRadian) {
          return (
            offsetY +
            Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          )
        }
        if (u > endRadian) {
          return (
            offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          )
        }
        return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
      },

      z: function (u, v) {
        if (u < -Math.PI * 0.5) {
          return Math.sin(u)
        }
        if (u > Math.PI * 2.5) {
          return Math.sin(u)
        }
        return Math.sin(v) > 0 ? 1 * height : -1
      },
    }
  }
  // 生成模拟 3D 饼图的配置项
  function getPie3D(pieData, internalDiameterRatio) {
    let series = []
    let sumValue = 0
    let startValue = 0
    let endValue = 0
    let legendData = []
    let k =
      typeof internalDiameterRatio !== 'undefined'
        ? (1 - internalDiameterRatio ) / (1 + internalDiameterRatio) 
        : 1 / 3

    // 为每一个饼图数据,生成一个 series-surface 配置
    for (let i = 0; i < pieData.length; i++) {
      sumValue += pieData[i].value

      let seriesItem = {
        name:
          typeof pieData[i].name === 'undefined'
            ? `series${i}`
            : pieData[i].name,
        type: 'surface',
        parametric: true,
        wireframe: {
          show: false,
        },
        pieData: pieData[i],
        pieStatus: {
          selected: false,
          hovered: false,
          k: k,
        },
      }

      if (typeof pieData[i].itemStyle != 'undefined') {
        let itemStyle = {}

        typeof pieData[i].itemStyle.color != 'undefined'
          ? (itemStyle.color = pieData[i].itemStyle.color)
          : null
        typeof pieData[i].itemStyle.opacity != 'undefined'
          ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
          : null

        seriesItem.itemStyle = itemStyle
      }
      series.push(seriesItem)
    }

    // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
    // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
    for (let i = 0; i < series.length; i++) {
      endValue = startValue + series[i].pieData.value
      series[i].pieData.startRatio = startValue / sumValue
      series[i].pieData.endRatio = endValue / sumValue
      series[i].parametricEquation = getParametricEquation(
        series[i].pieData.startRatio,
        series[i].pieData.endRatio,
        false,
        false,
        k,
        series[i].pieData.value,
      )

      startValue = endValue

      legendData.push(series[i].name)
    }
    return series
  }
  // 传入数据生成 option
  const optionsData = [
    {
      name: '',
      value: 160,
      itemStyle: {
        color: 'rgba(100, 170, 220, 1)',
      },
    },
    {
      name: '',
      value: 200,
      itemStyle: {
        color: 'rgba(190, 190, 230,1)',
      },
    },
    {
      name: '',
      value: 150,
      itemStyle: {
        color: 'rgba(167, 240, 190, 1)',
      },
    },
    
    {
      name: '',
      value: 100,
      itemStyle: {
        color: 'rgba(110, 215, 200, 1)',
      },
    },
    {
      name: '',
      value: 140,
      itemStyle: {
        color: 'rgba(220, 220,175, 1)',
      },
    },
  ]const pieChart = ref()
  const pieChartValue = ref(null)
  const echartInit = () => {
    pieChartValue.value = echarts.init(pieChart.value);
    const series = getPie3D(optionsData, 0.85)//第二个参数控制圆环粗细
    pieChartValue.value.setOption({
      legend: {
        show: false,
      },
      animation: true,
      tooltip: {
        //划过显示的内容
        formatter: (params) => {
          if (
            params.seriesName !== 'mouseoutSeries' &&
            params.seriesName !== 'pie2d'
          ) {
            return `${
              params.seriesName
            }<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
              params.color
            };"></span>${
              option.series[params.seriesIndex].pieData.value + '件'
            }`
          }
        },
        textStyle: {
          fontSize: 14,
        },
      },
      title: {
        x: 'center',
        top: '20',
        textStyle: {
          color: '#fff',
          fontSize: 22,
        },
      },
      labelLine: {
        show: false,
        lineStyle: {
          color: 'rgba(255, 192, 19, .7)',
        },
        normal: {
          show: true,
          length: 20,
          length2: 40,
        },
      },
      label: {
        show: false,
        position: 'outer',
        //指引线的内容
        formatter: '{b|{b}} \n{c|{c}} {value|件}',
        padding: [0, -30],
        rich: {
          b: {
            fontSize: 16,
            color: '#fff',
            fontWeight: 600,
            lineHeight: 40
          },
          c: {
            color: '#15DDFA', 
            fontSize: 24,
            fontWeight: 600,
            lineHeight: 40,
          },
          value: {
            color: '#ffffff', 
            fontSize: 16,
            fontWeight: 400,
          }
        },
      },
      xAxis3D: {
        min: -1,
        max: 1,
      },
      yAxis3D: {
        min: -1,
        max: 1,
      },
      zAxis3D: {
        min: -1,
        max: 1,
      },
      grid3D: {
        show: false,
        boxHeight: 0.2,//环形图的高度,可自己调节
        top: -70,
        // environment: "rgba(255,255,255,0)",
        viewControl: {
          distance: 180,//调整视角到主体的距离,类似调整zoom
          alpha: 23, //角度
          beta: 30,
          autoRotate: false, // 自动旋转
          rotateSensitivity: 0, //设置为0无法旋转
          zoomSensitivity: 0, //设置为0无法缩放
          panSensitivity: 0, //设置为0无法平移
        },
      },
      series: series,
    })
  }
onMounted(() => {
    echartInit()
  })

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3是一种流行的JavaScript框架,而Echarts5是一种强大的数据可视化库。结合Vue3和Echarts5,可以很容易地实现世界地的可视化效果。 首先,你需要在Vue项目中安装Echarts5。可以通过npm或yarn来安装echarts: ``` npm install echarts ``` 或者 ``` yarn add echarts ``` 安装完成后,你可以在Vue组件中引入Echarts,并使用它来绘制世界地。 在Vue组件中,你可以使用`<template>`标签来定义HTML模板,使用`<script>`标签来编写JavaScript代码,使用`<style>`标签来定义CSS样式。 下面是一个简单的示例代码,展示了如何在Vue3中使用Echarts5绘制世界地: ```vue <template> <div id="world-map" style="width: 100%; height: 400px;"></div> </template> <script> import * as echarts from 'echarts'; export default { mounted() { this.drawWorldMap(); }, methods: { drawWorldMap() { const chartDom = document.getElementById('world-map'); const myChart = echarts.init(chartDom); // 定义地数据 const mapData = [ { name: 'China', value: 100 }, { name: 'United States', value: 50 }, // 其他国家... ]; // 配置地选项 const option = { tooltip: { trigger: 'item', formatter: '{b}: {c}', }, visualMap: { min: 0, max: 100, left: 'left', top: 'bottom', text: ['High', 'Low'], seriesIndex: [1], inRange: { color: ['#e0ffff', '#006edd'], }, }, series: [ { type: 'map', mapType: 'world', roam: true, label: { show: true, }, data: mapData, }, ], }; // 使用配置项绘制地 myChart.setOption(option); }, }, }; </script> <style> #world-map { width: 100%; height: 400px; } </style> ``` 在上面的代码中,我们首先引入了Echarts库,然后在`mounted`生命周期钩子函数中调用`drawWorldMap`方法来绘制地。`drawWorldMap`方法中,我们使用`echarts.init`方法初始化一个Echarts实例,并通过配置项`option`来定义地的样式和数据。最后,使用`myChart.setOption(option)`方法将配置项应用到地上。 这样,你就可以在Vue项目中使用Vue3和Echarts5来实现世界地的可视化效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值