Files
----/前端源码/uni-app/components/SixDimensionRadar.vue

246 lines
5.3 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="sixdim-section">
<!-- 顶部图标 + 标题 -->
<!-- <view class="sixdim-bar">
<view class="sixdim-icon-grid">
<view v-for="n in 9" :key="n" class="sixdim-icon-dot"></view>
</view>
<text class="sixdim-bar-title">六维格局</text>
</view> -->
<!-- 卡片主体 -->
<view class="sixdim-card">
<view class="sixdim-info">
<view class="sixdim-info-icon">i</view>
</view>
<view class="sixdim-radar">
<!-- SVG 绘制六边形网格线 -->
<svg class="sixdim-radar-svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<!-- 中圈六边形 -->
<polygon
points="50,22 78,36 78,64 50,78 22,64 22,36"
fill="none"
stroke="rgba(255, 255, 255, 0.4)"
stroke-width="0.8"
/>
</svg>
<view
v-for="(label, idx) in labels"
:key="idx"
class="sixdim-label"
:class="'sixdim-label-' + idx"
>
<text>{{ label }}</text>
</view>
<view class="sixdim-radar-fill" :style="fillStyle"></view>
</view>
<view class="sixdim-remark sixdim-remark-center">
<text class="sixdim-remark-label">大师的批注</text>
<text class="sixdim-remark-text">{{ remark }}</text>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Props {
labels: string[]; // 六维文字数组,如 ['事业', '财运', '健康', '家庭', '社交', '智慧']
values: number[]; // 六维数据数组,范围 0-100
remark: string; // 大师批注
}
const props = withDefaults(defineProps<Props>(), {
labels: () => ['事业', '财运', '健康', '家庭', '社交', '智慧'],
values: () => [100, 92, 86, 80, 75, 90],
remark: '此名天格人格地格配置上佳,主事业运亨通。水木相生,智慧超群,唯需注意社交圆融。'
});
// 根据 values 计算填充区域的 clip-path
// 六边形顶点位置从顶部开始顺时针0°(上), 60°(右上), 120°(右下), 180°(下), 240°(左下), 300°(左上)
const fillStyle = computed(() => {
const maxValue = 100;
const centerX = 50; // 中心点 x 百分比
const centerY = 50; // 中心点 y 百分比
const baseRadius = 44; // 基础半径(从中心到外圈的百分比,约 44%
// 计算每个维度的实际半径0-100 映射到 0-baseRadius
const points = props.values.map((value: number, idx: number) => {
const angle = (idx * 60 - 90) * (Math.PI / 180); // 转换为弧度,-90° 使顶部为起点
const radius = (value / maxValue) * baseRadius;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
return { x, y };
});
// 生成 clip-path polygon 字符串
const path = points.map((p: { x: any; y: any; }) => `${p.x}% ${p.y}%`).join(', ');
return {
clipPath: `polygon(${path})`
};
});
</script>
<style scoped>
.sixdim-section {
margin-bottom: 64rpx;
}
.sixdim-bar {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 24rpx;
padding: 0 8rpx;
}
.sixdim-icon-grid {
width: 28rpx;
height: 28rpx;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 2rpx;
}
.sixdim-icon-dot {
width: 6rpx;
height: 6rpx;
border-radius: 2rpx;
background: #d4af37;
opacity: 0.85;
}
.sixdim-bar-title {
font-size: 24rpx;
font-weight: bold;
color: #e2e2e2;
letter-spacing: 0.24em;
}
.sixdim-card {
position: relative;
background: rgba(255, 255, 255, 0.05);
border-radius: 20rpx;
border: 1px solid rgba(255, 255, 255, 0.06);
padding: 28rpx 24rpx 32rpx;
backdrop-filter: blur(12px);
overflow: hidden;
}
.sixdim-info {
position: absolute;
top: 16rpx;
right: 16rpx;
}
.sixdim-info-icon {
width: 28px;
height: 28px;
border-radius: 999rpx;
border: 1px solid rgba(255, 255, 255, 0.16);
color: rgba(255, 255, 255, 0.45);
font-size: 18px;
text-align: center;
line-height: 28rpx;
}
.sixdim-radar {
position: relative;
width: 100%;
max-width: 380rpx;
margin: 0 auto;
padding-top: 65%;
background: radial-gradient(circle at 50% 50%, rgba(255, 193, 7, 0.04), transparent 70%);
border-radius: 24rpx;
overflow: hidden;
}
.sixdim-radar-svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 3;
pointer-events: none;
}
.sixdim-radar-fill {
position: absolute;
inset: 24%;
margin: auto;
background: linear-gradient(to bottom, rgba(255, 193, 7, 0.75), rgba(255, 87, 34, 0.55));
opacity: 0.85;
transition: clip-path 0.5s ease-out;
z-index: 2;
}
.sixdim-label {
position: absolute;
font-size: 20rpx;
color: #cfd2dc;
}
.sixdim-label-0 {
top: 6%;
left: 50%;
transform: translateX(-50%);
}
.sixdim-label-1 {
top: 26%;
right: 6%;
}
.sixdim-label-2 {
bottom: 28%;
right: 4%;
}
.sixdim-label-3 {
bottom: 4%;
left: 50%;
transform: translateX(-50%);
}
.sixdim-label-4 {
bottom: 28%;
left: 4%;
}
.sixdim-label-5 {
top: 26%;
left: 6%;
}
.sixdim-remark {
font-size: 20rpx;
line-height: 1.8;
color: #a0a4b8;
}
.sixdim-remark-center {
margin-top: 24rpx;
text-align: center;
padding: 0 24rpx;
}
.sixdim-remark-label {
color: #fdd835;
}
.sixdim-remark-text {
color: #c0c3d0;
}
</style>