This commit is contained in:
李想 2025-04-25 11:37:59 +08:00
parent 64a09455c4
commit 3677c1e953
7 changed files with 380 additions and 67 deletions

2
components.d.ts vendored
View File

@ -16,6 +16,8 @@ declare module 'vue' {
CustomCarouselPicture: typeof import('./src/components/custom-carousel-picture/index.vue')['default']
CustomEchartBar: typeof import('./src/components/custom-echart-bar/index.vue')['default']
CustomEchartBubble: typeof import('./src/components/custom-echart-bubble/index.vue')['default']
CustomEchartHyaline: typeof import('./src/components/custom-echart-hyaline/index.vue')['default']
CustomEchartHyalineCake: typeof import('./src/components/custom-echart-hyaline-cake/index.vue')['default']
CustomEchartLine: typeof import('./src/components/custom-echart-line/index.vue')['default']
CustomEchartLineLine: typeof import('./src/components/custom-echart-line-line/index.vue')['default']
CustomEchartMaps: typeof import('./src/components/custom-echart-maps/index.vue')['default']

View File

@ -0,0 +1,282 @@
<template>
<div ref="chartRef" :style="{ height, width }"></div>
</template>
<script>
import { ref, reactive, watchEffect } from 'vue';
import { cloneDeep } from 'lodash';
import { useEcharts } from '@/hooks/useEcharts';
export default {
name: 'CustomEchartHyalineCake',
props: {
chartData: {
type: Array,
default: () => [
{
name: '项目一',
value: 60,
},
{
name: '项目二',
value: 44,
},
{
name: '项目三',
value: 32,
},
],
},
option: {
type: Object,
default: () => ({}),
},
type: {
type: String,
default: 'bar',
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: 'calc(100vh - 78px)',
},
isSeries: {
type: Boolean,
default: false,
},
},
emits: ['click'],
setup(props, { emit }) {
const chartRef = ref(null);
const { setOptions, getInstance, startAutoPlay } = useEcharts(chartRef);
const option = ref({});
const itemHeight = ref(120);
// let colors = ['#07daf2', '#64de8a', '#ecc23c', '#ffdb5c', '#ff9f7f', '#9fe6b8', '#67e0e3', '#32c5e9', '#fb7293', '#9A60B4', '#ea7ccc'];
watchEffect(() => {
props.chartData && initCharts();
});
function initCharts() {
if (props.option) {
Object.assign(option, cloneDeep(props.option));
}
option.value = getPie3D(props.chartData, 0.5);
setOptions(option.value);
}
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) {
isSelected = false;
}
k = typeof k !== 'undefined' ? k : 1 / 3;
const offsetX = Math.cos(midRadian) * 0.2;
const offsetY = Math.sin(midRadian) * 0.2;
const hoverRate = 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;
}
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
},
};
}
// 3D
function getPie3D(pieData) {
const series = [];
//
let sumValue = 0;
let startValue = 0;
let endValue = 0;
const legendData = [];
const k = 1;
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],
itemStyle: {
// color: colors[i], //
opacity: '0.6',
borderRadius: 300,
borderColor: '#fff',
borderWidth: 0,
},
pieStatus: {
selected: false,
hovered: false,
k,
},
};
if (typeof pieData[i].itemStyle !== 'undefined') {
const { itemStyle } = pieData[i];
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 += 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,
itemHeight.value
);
startValue = endValue;
legendData.push(series[i].name);
}
const option = {
tooltip: {
position: function (point, params, dom, rect, size) {
var x = point[0];
var y = point[1];
var viewWidth = size.viewSize[0];
var viewHeight = size.viewSize[1];
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// tooltip 使
if (x + boxWidth > viewWidth) {
x = x - boxWidth;
}
if (y + boxHeight > viewHeight) {
y = y - boxHeight;
}
// tooltip
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
return [x, y];
},
formatter: (params) => {
if (params.seriesName !== 'mouseoutSeries') {
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}
`;
}
return '';
},
},
xAxis3D: {
min: -1,
max: 1.5,
},
yAxis3D: {
min: -1,
max: 1.5,
},
zAxis3D: {
min: -1,
max: 1.5,
},
itemGap: 20,
grid3D: {
itemGap: 20,
show: false,
boxHeight: 5,
top: '0',
left: '-20%',
viewControl: {
//3d
alpha: 60, //( )
distance: 260, //zoom()
rotateSensitivity: 10, //0
zoomSensitivity: 10, //0
panSensitivity: 10, //0
autoRotate: true, //
autoRotateAfterStill: 2, //, autoRotate
},
},
legend: {
show: true,
right: '5%',
top: '25%',
orient: 'vertical',
icon: 'circle',
itemHeight: 12,
itemWidth: 12,
itemGap: 10,
textStyle: {
color: '#fff',
fontSize: 14,
fontWeight: '400',
},
formatter: (name) => {
if (props.chartData.length) {
const item = props.chartData.filter((item) => item.name === name)[0];
return ` ${name} ${item.value}万亩`;
}
},
},
series,
};
return option;
}
function onClick(params) {
emit('click', params);
}
return { chartRef };
},
};
</script>

View File

@ -20,6 +20,7 @@ import CustomEchartWordCloud from './custom-echart-word-cloud';
import customEchartScatterBlister from './custom-echart-scatter-blister';
import customEchartMaps from './custom-echart-maps';
import customScrollTitle from './custom-scroll-title';
import customEchartHyalineCake from './custom-echart-hyaline-cake';
export {
SvgIcon,
@ -44,4 +45,5 @@ export {
customEchartScatterBlister,
customEchartMaps,
customScrollTitle,
customEchartHyalineCake,
};

View File

@ -60,7 +60,6 @@ watch(
};
});
list.value.sort((a, b) => b.value - a.value);
console.log('list', list.value);
},
{
immediate: true,
@ -83,7 +82,6 @@ function handleAc(val) {
}
const _circleNum = computed(() => {
let s = ((currNum.value / allNum.value) * 100).toFixed(1);
console.log('s----------', currNum.value, allNum.value, s);
return s + '%';
});
</script>

View File

@ -0,0 +1,44 @@
<template>
<customEchartHyalineCake :chart-data="data" height="100%" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
/* --------------- data --------------- */
// #region
const data = ref([
{
name: '小麦',
value: 60.8,
},
{
name: '荞麦',
value: 44.4,
},
{
name: '贡菜',
value: 24.3,
},
{
name: '油菜',
value: 32.7,
},
{
name: '马铃薯',
value: 32.9,
},
{
name: '玉米',
value: 32.1,
},
]);
// #endregion
/* --------------- methods --------------- */
// #region
// #endregion
</script>
<style lang="scss" scoped></style>

View File

@ -5,6 +5,17 @@
import { reactive } from 'vue';
const state = reactive({
data: [
{ value: 20, name: '耿马镇' },
{ value: 15, name: '勐撒镇' },
{ value: 12, name: '勐永镇' },
{ value: 16, name: '孟定镇' },
{ value: 8, name: '勐简乡' },
{ value: 12, name: '贺派乡' },
{ value: 10, name: '四排山乡' },
{ value: 9, name: '芒洪乡' },
{ value: 8, name: '大兴乡' },
],
option: {
grid: {
left: '5%',
@ -28,9 +39,10 @@ const state = reactive({
},
},
barStyle: {
barWidth: 15,
barWidth: 14,
itemStyle: {
borderRadius: [8, 8, 0, 0], //
borderWidth: 14,
borderRadius: [8, 8, 8, 8], //
},
color: {
type: 'linear',
@ -47,76 +59,48 @@ const state = reactive({
},
xAxis: {
type: 'value',
// name: '',
// splitLine: {
// show: false,
// lineStyle: {
// type: 'dashed',
// color: '',
// width: 1,
// },
// },
axisTick: {
splitLine: {
show: false,
alignWithLabel: false,
interval: 'auto',
inside: false,
length: 5,
lineStyle: {
type: 'solid',
width: 1,
color: 'rgba(28, 158, 222, 1)',
type: 'dashed',
color: '#E5E5E5',
},
},
// axisLine: {
// show: true,
// lineStyle: {
// type: 'solid',
// width: 1,
// // color: '#000',
// },
// },
// axisLabel: {
// margin: 8,
// interval: 'auto',
// rotate: 0,
// fontSize: 10,
// color: '#fff',
// },
axisLabel: {
show: false,
textStyle: {
color: '#424242',
},
},
show: false,
axisLine: {
show: true,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'category',
// name: '()',
data: ['耿马镇', '勐撒镇', '勐永镇', '孟定镇', '勐简乡', '贺派乡', '四排山乡', '芒洪乡', '大兴乡'],
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLine: {
show: false,
},
},
// label: {
// show: true,
// position: 'insideTop',
// distance: -10,
// formatter: () => {
// return `{z|}{a|}`;
// },
// rich: {
// a: {
// widht: 18,
// height: 18,
// backgroundColor: {
// image:
// 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAARCAYAAADUryzEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAKUSURBVHgBpVPPaxNBFH4zszubTTY2sSRSrFCC1dIepChoD9JgKwiem6s3vYl4lyb/QS/+wJPnBPQ/0LQ91KsHe5BaWo3Yupqk6WZ3Z3Z2xt2tKUUNHnww8OB775tv3nwP4D8DDQOqqoqh9iuPjlpeVkkxQurvBAoiREGlUcHbpUWcHaWkoGUivAWOPyUt5iiYgbABS/IkCTp5YxMAF1rTui36Rt70acipFmOEcqE8n+vaWZbf74jnl++KAQlOLlcKNZuA6X7JcPw9K2uSPOd68bY1NXtJL0zGeWiO5h3fsbxxk5abNRIrPlawVK8TmGtRx89ZJIVy93NzC9et0sMU6JMxzkF+XXc/1Fbab1+bmuq2RNcZ39jg9UojTBTkSx3spIu6oaHMLevC9E3r4tNBcxwU8NhCeurZg9y1GwRYJucX9e2lRYwi5TiW8nmEYe6FusIsfWfkyjIMiauZ0j2PozRJ92lxi2E1mAGcB8jwjoakQS1EZ4cRxBg1McUMkzNaFqEBgbeTTWYhlZChUs4wghCUw5gh43xnIv75mACBKkxkpKFbARiYtUNnbRhBW7hrUvicUCoK73flsQK7uSlZCgXI892X7uZjEU3992auwr1Xh++eEKr3fY8E9sx8YiiSyHlRhrFvPQT0NOyGP3puwDfO0XwuYseRf9mnoFtfOVx9tM6/fGShOPRhxy/ndsWbWvPI3rGRKtDAkWspQM8MkUpHtk6L0NIlOkAIpRhnro8Mo38Kep493guaUA3j5ydPiCpUAyrS3toMbEFcQke6ppWxteDAlszYV9L7zk9Bh4mWmzTXqlLB0Tr8uY3RTpQjWxcK09gx9hLcYm1l2/OyXF6VVVSViY0RKPhHHJGrpHTo2v8EGgI2uB3r9kQAAAAASUVORK5CYII=',
// },
// },
// },
// },
series: [
{
type: 'bar',
// barWidth: '40%', //
// barMinHeight: 2, //
// barGap: '20%', //
},
],
},
data: [
{ value: 20, name: '耿马镇' },
{ value: 15, name: '勐撒镇' },
{ value: 12, name: '勐永镇' },
{ value: 16, name: '孟定镇' },
{ value: 8, name: '勐简乡' },
{ value: 12, name: '贺派乡' },
{ value: 10, name: '四排山乡' },
{ value: 9, name: '芒洪乡' },
{ value: 8, name: '大兴乡' },
],
});
</script>

View File

@ -44,7 +44,7 @@
<div class="right-charts-item">
<customBack top-title="各地农用地利用面积" :top-postion="'right'">
<template #back>
<landareaCharts></landareaCharts>
<cake />
</template>
</customBack>
</div>
@ -60,6 +60,7 @@ import landCirculation from './components/landCirculation.vue';
import landPlan from './components/landPlan.vue';
import landPatrol from './components/landPatrol.vue';
import LandAera from './components/LandAera.vue';
import cake from './components/cake.vue';
</script>
<style lang="scss" scoped>
.data-home-index {