vue3+echarts5实现3d饼图

1.新建chart.js文件 

function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
  // 计算
  let midRatio = (startRatio + endRatio) / 2;
  let startRadian = startRatio * Math.PI * 2;
  let endRadian = endRatio * Math.PI * 2;
  let midRadian = midRatio * Math.PI * 2;
  isSelected = false;
  k = typeof k !== "undefined" ? k : 1 / 3;
  let offsetX = isSelected ? Math.sin(midRadian) * 0.1 : 0;
  let offsetY = isSelected ? Math.cos(midRadian) * 0.1 : 0;
  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) * h * 0.1;
      }
      return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
    },
  };
}

export 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;
  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: 1 / 10, },
    };
    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);
  }
  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);
  }
  let option = {
    color: ["rgba(26, 255, 167, 1)", "rgba(42, 184, 255, 1)", "rgba(210, 0, 255, 1)"],
    title: {
      text: `46.2% \n{num|回收物料状态}`,
      right: 'center',
      top: '35%',
      textStyle: { color: "#fff", fontWeight: 400, fontSize: 24, rich: { num: { fontSize: 14 } }, },
    },
    legend: { bottom: "20", itemWidth: 10, itemHeight: 10, icon: "rund", textStyle: { color: "#fff" }, },
    xAxis3D: {},
    yAxis3D: {},
    zAxis3D: {},
    grid3D: {
      // distance缩小、alpha放大、beta调整角度
      viewControl: { autoRotate: false, distance: 120, alpha: 26, beta: 60, },
      left: "center",
      top: -20,
      show: false,
      boxHeight: 20,
    },
    series: series,
  };
  return option;
}

2.vue文件引入并使用

<script setup>
import * as echarts from "echarts";
import "echarts-gl"; // 3d图表库
import { getPie3D } from "./chart";

// 中 -> 3d饼图 --> 回收物料状态
const pieRef = ref(null);
const pieOption = async () => {
  echarts.init(pieRef.value).setOption(getPie3D([
    { name: "完好状态",  value: 30, itemStyle: { opacity: 0.7 } },
    { name: "待修状态",  value: 50, itemStyle: { opacity: 0.7 } },
    { name: "报废状态",  value: 20, itemStyle: { opacity: 0.7 } }
  ], 0.7));
}
</script>

<template>
 <div class="bai pie-ec" ref="pieRef"></div>
</template>

显示效果

### Vue 中使用 ECharts 实现立体 3D #### DOM 层引入 为了在 Vue 项目中集成并展示 3D ,需先安装 `echarts` 和 `echarts-gl` 库。通过命令行工具执行如下指令完成依赖包的安装: ```bash npm install echarts --save npm install echarts-gl --save ``` 接着,在 Vue 组件内部导入这两个库以便后续调用其 API 进行表初始化操作。 #### 使用简易 3D 效果 创建一个新的 Vue 单文件组件用于承载 3D 实例,并定义好对应的 HTML 结构以及样式设置来容纳表容器[^1]。 ```html <template> <div id="main" style="width: 600px;height:400px;"></div> </template> <script> import * as Echarts from &#39;echarts&#39;; import &#39;echarts-gl&#39;; export default { name: "PieChart", mounted() { this.initChart(); }, methods: { initChart() { let chartDom = document.getElementById(&#39;main&#39;); var myChart = Echarts.init(chartDom); const option = { title : { text: &#39;某站点用户访问来源&#39;, subtext: &#39;纯属虚构&#39;, left: &#39;center&#39; }, tooltip : { trigger: &#39;item&#39; }, legend: { orient: &#39;vertical&#39;, left: &#39;left&#39; }, series : [ { type: &#39;pie&#39;, // 设置为 pie 类型表示这是一个 radius: [&#39;50%&#39;, &#39;70%&#39;],// 定义内径和外径比例从而形成环形的效果;如果只想要普通的则可以调整此参数 avoidLabelOverlap: false, itemStyle: { borderRadius: 10, // 圆角半径让形看起来更柔和一些 borderColor: &#39;#fff&#39;, borderWidth: 2 }, label: { show: true, position: &#39;outside&#39; }, emphasis: { label: { show: true, fontSize: &#39;20&#39;, fontWeight: &#39;bold&#39; } }, data:[ {value:335, name:&#39;直接访问&#39;}, {value:310, name:&#39;邮件营销&#39;}, {value:234, name:&#39;联盟广告&#39;}, {value:135, name:&#39;视频广告&#39;}, {value:1548, name:&#39;搜索引擎&#39;} ] } ], renderer: &#39;canvas&#39;, // 渲染器选择 canvas 或者 svg,默认是 canvas grid3D: {} // 启用三维网格特性支持绘制更加复杂的场景 }; if (option && typeof option === &#39;object&#39;) { myChart.setOption(option); // 将配置项应用到表上 } } } }; </script> ``` 上述代码片段展示了如何利用 ECharts 创建一个基础版本的 3D ,并将其嵌入至 Vue 的模板结构之中。值得注意的是这里启用了 `grid3D` 特性以开启对于 3D 表的支持[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值