|
|
@@ -0,0 +1,136 @@
|
|
|
+<template>
|
|
|
+ <div class="hetu">
|
|
|
+ <svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
|
+ <defs>
|
|
|
+ <radialGradient id="bgHetu" cx=".5" cy=".5">
|
|
|
+ <stop offset="0" stop-color="#FFFFFF" />
|
|
|
+ <stop offset=".85" stop-color="#FFFFFF" stop-opacity=".5" />
|
|
|
+ <stop offset="1" stop-color="#FFFFFF" stop-opacity="0" />
|
|
|
+ </radialGradient>
|
|
|
+ </defs>
|
|
|
+
|
|
|
+ <circle cx="200" cy="200" r="180" fill="url(#bgHetu)" class="hetu__ring hetu__ring--strong" />
|
|
|
+ <circle cx="200" cy="200" r="150" fill="none" class="hetu__ring hetu__ring--mid" />
|
|
|
+ <circle cx="200" cy="200" r="195" fill="none" class="hetu__ring hetu__ring--dash" />
|
|
|
+
|
|
|
+ <text v-for="c in directions" :key="c.text"
|
|
|
+ :y="c.y" :x="c.x" text-anchor="middle"
|
|
|
+ class="hetu__label" font-size="13" font-family="'Songti SC',serif"
|
|
|
+ letter-spacing="4" font-weight="500">{{ c.text }}</text>
|
|
|
+
|
|
|
+ <circle v-for="d in dotPoints" :key="`dot-${d.cx}-${d.cy}`"
|
|
|
+ :cx="d.cx" :cy="d.cy" r="3" :fill="d.fill" />
|
|
|
+
|
|
|
+ <g v-for="(g, gi) in groups" :key="gi" :transform="`translate(${g.x},${g.y})`" :fill="g.fill">
|
|
|
+ <circle v-for="(c, ci) in g.circles" :key="ci" :cx="c.x" :cy="c.y" :r="c.r" :fill="c.fill" />
|
|
|
+ </g>
|
|
|
+ <text v-for="(cap, ci) in captions" :key="`cap-${ci}`"
|
|
|
+ :x="cap.x" :y="cap.y" text-anchor="middle"
|
|
|
+ class="hetu__caption" font-size="11" letter-spacing="3" font-weight="500">{{ cap.text }}</text>
|
|
|
+
|
|
|
+ <g class="hetu__center">
|
|
|
+ <circle r="9" fill="var(--login-gold)" />
|
|
|
+ <circle r="6" fill="#FFFFFF" />
|
|
|
+ <text y="4" text-anchor="middle" fill="#8C1810" font-size="11" font-weight="700">五</text>
|
|
|
+ <circle v-for="(c, ci) in centerDots" :key="ci" :cx="c.x" :cy="c.y" r="3.2" />
|
|
|
+ </g>
|
|
|
+
|
|
|
+ <g class="hetu__tick" fill="none">
|
|
|
+ <line x1="200" y1="14" x2="200" y2="22" />
|
|
|
+ <line x1="200" y1="378" x2="200" y2="386" />
|
|
|
+ <line x1="378" y1="200" x2="386" y2="200" />
|
|
|
+ <line x1="14" y1="200" x2="22" y2="200" />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+const directions = [
|
|
|
+ { text: '北', x: 200, y: 38 },
|
|
|
+ { text: '南', x: 200, y: 378 },
|
|
|
+ { text: '东', x: 365, y: 206 },
|
|
|
+ { text: '西', x: 35, y: 206 },
|
|
|
+]
|
|
|
+
|
|
|
+const dotPoints = [
|
|
|
+ { cx: 200, cy: 105, fill: 'var(--login-water)' },
|
|
|
+ { cx: 200, cy: 295, fill: 'var(--login-fire)' },
|
|
|
+ { cx: 295, cy: 200, fill: 'var(--login-wood)' },
|
|
|
+ { cx: 105, cy: 200, fill: 'var(--login-metal)' },
|
|
|
+]
|
|
|
+
|
|
|
+// 河图四象数据:每象 5 黑 + 10 白/金 圆点
|
|
|
+const groups = [
|
|
|
+ { x: 200, y: 100, fill: 'var(--login-ink)', circles: [
|
|
|
+ { x: -12, y: 0, r: 5.5, fill: 'var(--login-ink)' },
|
|
|
+ { x: 0, y: -12, r: 5.5, fill: 'var(--login-ink)' },
|
|
|
+ { x: 0, y: 0, r: 5.5, fill: 'var(--login-ink)' },
|
|
|
+ { x: 0, y: 12, r: 5.5, fill: 'var(--login-ink)' },
|
|
|
+ { x: 12, y: 0, r: 5.5, fill: 'var(--login-ink)' },
|
|
|
+ ...goldDots([-18, -6, -6, -6, 6, 6, 18], [0, -12, 0, 12, -12, 12, 0]),
|
|
|
+ ] },
|
|
|
+ { x: 200, y: 300, fill: 'var(--login-gold)', circles: [
|
|
|
+ { x: -7, y: -7, r: 5.5 }, { x: 7, y: 7, r: 5.5 },
|
|
|
+ ...goldDots([-21, -7, 0, 7, 21, -7, 7], [0, -21, 0, 21, 0, 21, -21]),
|
|
|
+ ] },
|
|
|
+ { x: 300, y: 200, fill: 'var(--login-gold)', circles: [
|
|
|
+ { x: -7, y: 0, r: 5.5 }, { x: 7, y: -7, r: 5.5 }, { x: 7, y: 7, r: 5.5 },
|
|
|
+ ...goldDots([-21, -21, -7, -7, -7, 7, 21, 21], [-7, 7, -21, 0, 21, 0, -7, 7]),
|
|
|
+ ] },
|
|
|
+ { x: 100, y: 200, fill: 'var(--login-gold)', circles: [
|
|
|
+ { x: -7, y: -7, r: 5.5 }, { x: 7, y: -7, r: 5.5 },
|
|
|
+ { x: -7, y: 7, r: 5.5 }, { x: 7, y: 7, r: 5.5 },
|
|
|
+ ...goldDots(
|
|
|
+ [-21, -21, -21, -7, 7, -7, 7, -7, 7, 21, 21, 21],
|
|
|
+ [-12, 0, 12, -21, -21, 0, 0, 21, 21, -12, 0, 12],
|
|
|
+ ),
|
|
|
+ ] },
|
|
|
+]
|
|
|
+
|
|
|
+const captions = [
|
|
|
+ { x: 200, y: 156, text: '一 · 六' },
|
|
|
+ { x: 200, y: 356, text: '二 · 七' },
|
|
|
+ { x: 300, y: 252, text: '三 · 八' },
|
|
|
+ { x: 100, y: 252, text: '四 · 九' },
|
|
|
+]
|
|
|
+
|
|
|
+const centerDots = [
|
|
|
+ { x: -22, y: -22 }, { x: 0, y: -22 }, { x: 22, y: -22 },
|
|
|
+ { x: -22, y: 0 }, { x: 22, y: 0 },
|
|
|
+ { x: -22, y: 22 }, { x: 0, y: 22 }, { x: 22, y: 22 },
|
|
|
+]
|
|
|
+
|
|
|
+function goldDots(xs, ys) {
|
|
|
+ return xs.map((x, i) => ({ x, y: ys[i], r: 4, fill: 'var(--login-gold)' }))
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.hetu {
|
|
|
+ width: clamp(200px, 30vw, 340px);
|
|
|
+ aspect-ratio: 1 / 1;
|
|
|
+ margin: 0 auto;
|
|
|
+}
|
|
|
+
|
|
|
+.hetu svg {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ filter: drop-shadow(0 8px 24px rgba(16, 32, 64, 0.08));
|
|
|
+}
|
|
|
+
|
|
|
+.hetu__ring {
|
|
|
+ stroke: var(--login-gold);
|
|
|
+}
|
|
|
+
|
|
|
+.hetu__ring--strong { stroke-opacity: 0.5; stroke-width: 1.5; fill: url(#bgHetu); }
|
|
|
+.hetu__ring--mid { stroke-opacity: 0.25; stroke-width: 0.6; }
|
|
|
+.hetu__ring--dash { stroke-opacity: 0.18; stroke-width: 0.6; stroke-dasharray: 2 3; }
|
|
|
+
|
|
|
+.hetu__label,
|
|
|
+.hetu__caption { fill: #8C7304; }
|
|
|
+
|
|
|
+.hetu__center circle:last-of-type { fill: var(--login-gold); }
|
|
|
+
|
|
|
+.hetu__tick { stroke: var(--login-gold); stroke-opacity: 0.4; stroke-width: 1.2; }
|
|
|
+</style>
|