diff --git a/components.d.ts b/components.d.ts
index 5e2d588..971b418 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -42,8 +42,6 @@ declare module 'vue' {
CustomScrollTitle: typeof import('./src/components/custom-scroll-title/index.vue')['default']
CustomTableOperate: typeof import('./src/components/custom-table-operate/index.vue')['default']
CustomTableTree: typeof import('./src/components/custom-table-tree/index.vue')['default']
- IndexCo: typeof import('./src/components/custom-echart-line/index-co.vue')['default']
- IndexRe: typeof import('./src/components/new-hyaline-cake/index-re.vue')['default']
NewHyalineCake: typeof import('./src/components/custom-echart-hyaline-cake/new-hyaline-cake.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
diff --git a/src/components/custom-echart-hyaline-cake/new-hyaline-cake.vue b/src/components/custom-echart-hyaline-cake/new-hyaline-cake.vue
index 1256fe2..2f39c56 100644
--- a/src/components/custom-echart-hyaline-cake/new-hyaline-cake.vue
+++ b/src/components/custom-echart-hyaline-cake/new-hyaline-cake.vue
@@ -74,10 +74,10 @@ function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h
k = typeof k !== 'undefined' ? k : 1 / 3;
// 计算选中效果的偏移量(基于扇形中心角度)
- const offsetX = Math.cos(midRadian) * props.option.itemGap;
- const offsetY = Math.sin(midRadian) * props.option.itemGap;
+ const offsetX = isSelected ? Math.cos(midRadian) * props.option.itemGap : 0;
+ const offsetY = isSelected ? Math.sin(midRadian) * props.option.itemGap : 0;
// 计算高亮时的放大比例(未高亮时为1)
- const hoverRate = isHovered ? 1.08 : 1;
+ const hoverRate = isHovered ? 1.05 : 1;
// 返回 parametric 曲面方程
return {
@@ -88,7 +88,7 @@ function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h
step: Math.PI / 32,
},
v: {
- // v 参数控制扇形的径向方向(厚度方向)
+ // v 从 0 - 2π 参数控制扇形的径向方向(厚度方向)
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
@@ -124,6 +124,7 @@ function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h
return Math.sin(u) * h * 0.1;
}
// 正常情况下,z 根据 v 参数控制上下表面的高度差
+ // 当前图形的高度是Z根据h(每个value的值决定的)
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
},
};
@@ -374,67 +375,95 @@ function handleClick(params) {
// 触发组件 click 事件供父组件使用
emit('click', params);
}
+// 在函数顶部声明(确保作用域覆盖所有需要的地方)
+window.debugZValues = {
+ current: null,
+ history: [],
+};
function handleMouseover(params) {
- const optionVal = chartOption.value;
+ if (params.seriesName === 'mouseoutSeries') return;
+
+ const chart = getInstance();
+ const optionVal = chart.getOption(); // 改用实时获取最新配置
const series = optionVal.series;
const idx = params.seriesIndex;
+ const hh = series[idx].parametricEquation.z();
+ window.debugZValues.current = hh;
+ window.debugZValues.history.push({
+ event: 'mouseover',
+ series: series[idx].name,
+ zValue: hh,
+ time: new Date().toISOString(),
+ });
+ console.log('当前Z值:', hh, '历史记录:', window.debugZValues.history);
+ // 打印移入前的完整状态(调试用)
+ console.log(
+ '[移入] 当前所有扇形状态',
+ series.map((s) => ({
+ name: s.name,
+ hovered: s.pieStatus?.hovered,
+ selected: s.pieStatus?.selected,
+ height: s.parametricEquation?.z(Math.PI, Math.PI),
+ }))
+ );
- // 鼠标经过透明环时不做高亮处理
- if (params.seriesName === 'mouseoutSeries') {
- return;
- }
- // 如果此扇形已经高亮,无需重复操作
- if (hoveredIndex === idx) {
- return;
- }
- console.log('hoveredIndexOne :>> ', hoveredIndex);
- console.log('idx= :>> ', idx);
- // 取消之前高亮的扇形
- if (hoveredIndex !== null) {
+ // 取消之前的高亮(确保只修改状态,不破坏参数方程)
+ if (hoveredIndex !== null && hoveredIndex !== idx) {
const prev = series[hoveredIndex];
- const isSelected = prev.pieStatus.selected;
+ prev.pieStatus.hovered = false; // 仅修改状态
prev.parametricEquation = getParametricEquation(
+ // 重新生成正确方程
prev.pieData.startRatio,
prev.pieData.endRatio,
- isSelected,
- false,
+ prev.pieStatus.selected,
+ false, // isHovered=false
prev.pieStatus.k,
prev.pieData.value
);
- prev.pieStatus.hovered = false;
- hoveredIndex = null;
}
- // 设置当前扇形的高亮状态
- const isSelected = series[idx].pieStatus.selected;
- const startRatio = series[idx].pieData.startRatio;
- const endRatio = series[idx].pieData.endRatio;
- const k = series[idx].pieStatus.k;
- const h = series[idx].pieData.value;
- series[idx].parametricEquation = getParametricEquation(startRatio, endRatio, isSelected, true, k, h);
- series[idx].pieStatus.hovered = true;
- hoveredIndex = idx;
- console.log('hoveredIndexTwo :>> ', hoveredIndex);
+ // 设置新高亮
+ const current = series[idx];
+ current.pieStatus.hovered = true;
+ current.parametricEquation = getParametricEquation(
+ current.pieData.startRatio,
+ current.pieData.endRatio,
+ current.pieStatus.selected,
+ true, // isHovered=true
+ current.pieStatus.k,
+ current.pieData.value
+ );
- setOptions(optionVal);
+ hoveredIndex = idx;
+ chart.setOption({ series }); // 仅更新series部分
}
function handleGlobalout() {
if (hoveredIndex !== null) {
- const optionVal = chartOption.value;
+ const chart = getInstance();
+ const optionVal = chart.getOption();
const series = optionVal.series;
const prev = series[hoveredIndex];
- const isSelected = prev.pieStatus.selected;
+
+ // 打印修复前的错误状态(调试用)
+ console.warn('[修复前] 异常状态', {
+ name: prev.name,
+ z: prev.parametricEquation.z(Math.PI, Math.PI),
+ equation: prev.parametricEquation,
+ });
+
+ // 重置状态并重新生成方程
+ prev.pieStatus.hovered = false;
prev.parametricEquation = getParametricEquation(
prev.pieData.startRatio,
prev.pieData.endRatio,
- isSelected,
- false,
+ prev.pieStatus.selected,
+ false, // isHovered=false
prev.pieStatus.k,
prev.pieData.value
);
- prev.pieStatus.hovered = false;
+
hoveredIndex = null;
- setOptions(optionVal);
+ chart.setOption({ series }, { replaceMerge: 'series' }); // 强制替换series
}
}
// 记录当前选中和高亮的系列索引
diff --git a/src/views/land/components/landFive.vue b/src/views/land/components/landFive.vue
index ea48e76..394f99b 100644
--- a/src/views/land/components/landFive.vue
+++ b/src/views/land/components/landFive.vue
@@ -23,6 +23,7 @@ const state = reactive({
containLabel: true,
},
tooltip: {
+ className: 'custom-tooltip-container',
trigger: 'axis',
axisPointer: {
type: 'shadow',
diff --git a/src/views/land/components/landOne.vue b/src/views/land/components/landOne.vue
index 7581ab4..27ed2f3 100644
--- a/src/views/land/components/landOne.vue
+++ b/src/views/land/components/landOne.vue
@@ -22,11 +22,12 @@ const state = reactive({
containLabel: true,
},
tooltip: {
+ className: 'custom-tooltip-container', // 自定义父容器类名
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
- backgroundColor: 'rgba(0,0,0,0.6);',
+ backgroundColor: 'rgba(0,0,0,0.5);',
borderColor: '#35d0c0',
formatter: (data) => {
const params = data[0];
diff --git a/src/views/land/components/landSix.vue b/src/views/land/components/landSix.vue
index eb201ad..5caa33b 100644
--- a/src/views/land/components/landSix.vue
+++ b/src/views/land/components/landSix.vue
@@ -15,10 +15,11 @@ const props = defineProps({
const state = reactive({
option: {
+ k: 0.5,
opacity: 1,
itemGap: 0.1,
legendSuffix: '万亩',
- itemHeight: 500,
+ itemHeight: 200,
grid3D: {
show: false,
boxHeight: 1,
@@ -31,7 +32,7 @@ const state = reactive({
rotateSensitivity: 10, //设置旋转灵敏度,为0无法旋转
zoomSensitivity: 10, //设置缩放灵敏度,为0无法缩放
panSensitivity: 10, //设置平移灵敏度,0无法平移
- autoRotate: true, //自动旋转
+ autoRotate: false, //自动旋转
autoRotateAfterStill: 2, //在鼠标静止操作后恢复自动旋转的时间间隔,在开启 autoRotate 后有效
},
},
diff --git a/src/views/land/components/landThere.vue b/src/views/land/components/landThere.vue
index 0c76b3e..ba8bf3f 100644
--- a/src/views/land/components/landThere.vue
+++ b/src/views/land/components/landThere.vue
@@ -27,6 +27,7 @@ const state = reactive({
containLabel: true,
},
tooltip: {
+ className: 'custom-tooltip-container',
trigger: 'axis',
axisPointer: {
type: 'shadow',
diff --git a/src/views/land/components/lsh.txt b/src/views/land/components/lsh.txt
new file mode 100644
index 0000000..ec93880
--- /dev/null
+++ b/src/views/land/components/lsh.txt
@@ -0,0 +1,344 @@
+let selectedIndex = '';
+let hoveredIndex = '';
+option = getPie3D(
+ [
+ {
+ name: 'cc',
+ value: 47,
+ itemStyle: {
+ color: '#f77b66',
+ },
+ },
+ {
+ name: 'aa',
+ value: 44,
+ itemStyle: {
+ color: '#3edce0',
+ },
+ },
+ {
+ name: 'bb',
+ value: 32,
+ itemStyle: {
+ color: '#f94e76',
+ },
+ },
+ {
+ name: 'ee',
+ value: 16,
+ itemStyle: {
+ color: '#018ef1',
+ },
+ },
+ {
+ name: 'dd',
+ value: 23,
+ itemStyle: {
+ color: '#9e60f9',
+ },
+ },
+ ],
+ 0.59
+);
+// 生成扇形的曲面参数方程
+function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
+ // 计算
+ const midRatio = (startRatio + endRatio) / 2;
+
+ const startRadian = startRatio * Math.PI * 2;
+ const endRadian = endRatio * Math.PI * 2;
+ const midRadian = midRatio * Math.PI * 2;
+
+ // 如果只有一个扇形,则不实现选中效果。
+ if (startRatio === 0 && endRatio === 1) {
+ // eslint-disable-next-line no-param-reassign
+ isSelected = false;
+ }
+
+ // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
+ // eslint-disable-next-line no-param-reassign
+ k = typeof k !== 'undefined' ? k : 1 / 3;
+
+ // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
+ const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
+ const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
+
+ // 计算高亮效果的放大比例(未高亮,则比例为 1)
+ const 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(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(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(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;
+ }
+ // 当前图形的高度是Z根据h(每个value的值决定的)
+ return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
+ },
+ };
+}
+// 生成模拟 3D 饼图的配置项
+function getPie3D(pieData, internalDiameterRatio) {
+ const series = [];
+ // 总和
+ let sumValue = 0;
+ let startValue = 0;
+ let endValue = 0;
+ const legendData = [];
+ const k =
+ typeof internalDiameterRatio !== 'undefined'
+ ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
+ : 1 / 3;
+
+ // 为每一个饼图数据,生成一个 series-surface 配置
+ for (let i = 0; i < pieData.length; i += 1) {
+ sumValue += pieData[i].value;
+
+ const 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,
+ },
+ };
+
+ if (typeof pieData[i].itemStyle !== 'undefined') {
+ const { itemStyle } = pieData[i];
+
+ // eslint-disable-next-line no-unused-expressions
+ typeof pieData[i].itemStyle.color !== 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
+ // eslint-disable-next-line no-unused-expressions
+ 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,也就是实现每一个扇形。
+ console.log(series);
+ for (let i = 0; i < series.length; i += 1) {
+ 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,
+ // 我这里做了一个处理,使除了第一个之外的值都是10
+ series[i].pieData.value === series[0].pieData.value ? 35 : 10
+ );
+
+ startValue = endValue;
+
+ legendData.push(series[i].name);
+ }
+
+ // 准备待返回的配置项,把准备好的 legendData、series 传入。
+ const option = {
+ // animation: false,
+ tooltip: {
+ formatter: (params) => {
+ if (params.seriesName !== 'mouseoutSeries') {
+ return `${
+ params.seriesName
+ }
${option.series[params.seriesIndex].pieData.value}`;
+ }
+ return '';
+ },
+ },
+ xAxis3D: {
+ min: -1,
+ max: 1,
+ },
+ yAxis3D: {
+ min: -1,
+ max: 1,
+ },
+ zAxis3D: {
+ min: -1,
+ max: 1,
+ },
+ grid3D: {
+ show: false,
+ boxHeight: 5,
+ top: '-20%',
+ viewControl: {
+ // 3d效果可以放大、旋转等,请自己去查看官方配置
+ alpha: 35,
+ // beta: 30,
+ rotateSensitivity: 1,
+ zoomSensitivity: 0,
+ panSensitivity: 0,
+ autoRotate: true,
+ distance: 150,
+ },
+ // 后处理特效可以为画面添加高光、景深、环境光遮蔽(SSAO)、调色等效果。可以让整个画面更富有质感。
+ postEffect: {
+ // 配置这项会出现锯齿,请自己去查看官方配置有办法解决
+ enable: false,
+ bloom: {
+ enable: true,
+ bloomIntensity: 0.1,
+ },
+ SSAO: {
+ enable: true,
+ quality: 'medium',
+ radius: 2,
+ },
+ // temporalSuperSampling: {
+ // enable: true,
+ // },
+ },
+ },
+ series,
+ };
+ return option;
+}
+// 修正取消高亮失败的 bug
+// 监听 mouseover,近似实现高亮(放大)效果
+myChart.on('mouseover', function (params) {
+ // 准备重新渲染扇形所需的参数
+ let isSelected;
+ let isHovered;
+ let startRatio;
+ let endRatio;
+ let k;
+ let i;
+
+ // 如果触发 mouseover 的扇形当前已高亮,则不做操作
+ if (hoveredIndex === params.seriesIndex) {
+ return;
+
+ // 否则进行高亮及必要的取消高亮操作
+ } else {
+ // 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
+ if (hoveredIndex !== '') {
+ // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
+ isSelected = option.series[hoveredIndex].pieStatus.selected;
+ isHovered = false;
+ startRatio = option.series[hoveredIndex].pieData.startRatio;
+ endRatio = option.series[hoveredIndex].pieData.endRatio;
+ k = option.series[hoveredIndex].pieStatus.k;
+ i = option.series[hoveredIndex].pieData.value === option.series[0].pieData.value ? 35 : 10;
+ // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
+ option.series[hoveredIndex].parametricEquation = getParametricEquation(
+ startRatio,
+ endRatio,
+ isSelected,
+ isHovered,
+ k,
+ i
+ );
+ option.series[hoveredIndex].pieStatus.hovered = isHovered;
+
+ // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
+ hoveredIndex = '';
+ }
+
+ // 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
+ if (params.seriesName !== 'mouseoutSeries') {
+ // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
+ isSelected = option.series[params.seriesIndex].pieStatus.selected;
+ isHovered = true;
+ startRatio = option.series[params.seriesIndex].pieData.startRatio;
+ endRatio = option.series[params.seriesIndex].pieData.endRatio;
+ k = option.series[params.seriesIndex].pieStatus.k;
+
+ // 对当前点击的扇形,执行高亮操作(对 option 更新)
+ option.series[params.seriesIndex].parametricEquation = getParametricEquation(
+ startRatio,
+ endRatio,
+ isSelected,
+ isHovered,
+ k,
+ option.series[params.seriesIndex].pieData.value + 5
+ );
+ option.series[params.seriesIndex].pieStatus.hovered = isHovered;
+
+ // 记录上次高亮的扇形对应的系列号 seriesIndex
+ hoveredIndex = params.seriesIndex;
+ }
+
+ // 使用更新后的 option,渲染图表
+ myChart.setOption(option);
+ }
+});
+
+// 修正取消高亮失败的 bug
+myChart.on('globalout', function () {
+ if (hoveredIndex !== '') {
+ // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
+ isSelected = option.series[hoveredIndex].pieStatus.selected;
+ isHovered = false;
+ k = option.series[hoveredIndex].pieStatus.k;
+ startRatio = option.series[hoveredIndex].pieData.startRatio;
+ endRatio = option.series[hoveredIndex].pieData.endRatio;
+ // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
+ i = option.series[hoveredIndex].pieData.value === option.series[0].pieData.value ? 35 : 10;
+ option.series[hoveredIndex].parametricEquation = getParametricEquation(
+ startRatio,
+ endRatio,
+ isSelected,
+ isHovered,
+ k,
+ i
+ );
+ option.series[hoveredIndex].pieStatus.hovered = isHovered;
+
+ // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
+ hoveredIndex = '';
+ }
+
+ // 使用更新后的 option,渲染图表
+ myChart.setOption(option);
+});