Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe
243 lines
20 KiB
HTML
243 lines
20 KiB
HTML
<title>个人封面样稿</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600&display=swap">
|
||
<style>
|
||
:root{
|
||
--ground:#f3f2ee; --surface:#fbfaf7; --ink:#1d1d1f; --ink-2:#5b5750; --ink-3:#8c877e;
|
||
--line:#dedad2; --accent:#8a5a2b; --accent-soft:#efe6da;
|
||
--serif:"Noto Serif SC","Songti SC","STSong",serif;
|
||
--sans:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
|
||
}
|
||
@media (prefers-color-scheme:dark){
|
||
:root:not([data-theme="light"]){
|
||
--ground:#1a1917; --surface:#22211e; --ink:#ece9e2; --ink-2:#b7b1a6; --ink-3:#88837a;
|
||
--line:#35332f; --accent:#d2a06b; --accent-soft:#2e2923; color-scheme:dark;
|
||
}
|
||
}
|
||
:root[data-theme="dark"]{
|
||
--ground:#1a1917; --surface:#22211e; --ink:#ece9e2; --ink-2:#b7b1a6; --ink-3:#88837a;
|
||
--line:#35332f; --accent:#d2a06b; --accent-soft:#2e2923; color-scheme:dark;
|
||
}
|
||
*{box-sizing:border-box}
|
||
body{background:var(--ground);color:var(--ink);font-family:var(--sans);font-size:15px;line-height:1.65;padding:0 20px}
|
||
.wrap{max-width:1180px;margin:0 auto;padding-block:48px 72px}
|
||
header{max-width:680px}
|
||
h1{font-family:var(--serif);font-weight:600;font-size:clamp(26px,4vw,34px);line-height:1.3;margin:0 0 12px;text-wrap:balance}
|
||
.lede{color:var(--ink-2);margin:0}
|
||
.facts{display:flex;flex-wrap:wrap;gap:8px 28px;margin:28px 0 40px;padding:14px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);font-size:13px;color:var(--ink-2)}
|
||
.facts b{color:var(--ink);font-weight:600;margin-left:6px;font-variant-numeric:tabular-nums}
|
||
.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:36px 28px}
|
||
@media (max-width:940px){.grid{grid-template-columns:1fr;max-width:460px;margin:0 auto}}
|
||
figure{margin:0;display:flex;flex-direction:column;gap:18px}
|
||
.poster{width:100%;aspect-ratio:3/4;max-width:100%;display:block;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.06),0 12px 32px -12px rgba(40,30,20,.22)}
|
||
.cap h2{font-family:var(--serif);font-size:19px;font-weight:600;margin:0 0 4px;display:flex;align-items:center;gap:10px}
|
||
.pick{font-family:var(--sans);font-size:12px;font-weight:500;color:var(--accent);background:var(--accent-soft);padding:1px 9px;border-radius:99px;letter-spacing:.04em}
|
||
.cap p{margin:0 0 10px;color:var(--ink-2);font-size:14px}
|
||
.cap dl{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;margin:0;font-size:13.5px}
|
||
.cap dt{color:var(--ink-3)}
|
||
.cap dd{margin:0;color:var(--ink-2)}
|
||
.scrub{display:flex;align-items:center;gap:12px;font-size:13px;color:var(--ink-2)}
|
||
.scrub input{flex:1;accent-color:var(--accent)}
|
||
.scrub output{font-variant-numeric:tabular-nums;min-width:4.5em;text-align:right;color:var(--ink)}
|
||
footer{margin-top:56px;color:var(--ink-3);font-size:13px;max-width:680px}
|
||
</style>
|
||
|
||
<div class="wrap">
|
||
<header>
|
||
<h1>一张盘的封面,三种画法</h1>
|
||
<p class="lede">下面三张都是用同一张<strong>虚构</strong>星盘真实算出来的(瑞士星历表,Lahiri 岁差,整宫制),没有一笔是装饰。今天按 2026 年 9 月算“此刻”。</p>
|
||
</header>
|
||
|
||
<div class="facts" aria-label="样稿所用数据">
|
||
<span>上升<b>双子 10°58′</b></span>
|
||
<span>月亮<b>巨蟹 26°12′(也是 AK)</b></span>
|
||
<span>当前大运<b>太阳 2026.03–2032.03</b></span>
|
||
<span>分运<b>月亮 至 2026.12</b></span>
|
||
</div>
|
||
|
||
<div class="grid">
|
||
<figure>
|
||
<svg class="poster" id="pA" viewBox="0 0 600 800" role="img" aria-label="年轮封面"></svg>
|
||
<div class="scrub">
|
||
<label for="year">拖动看“你在这里”怎么走</label>
|
||
<input id="year" type="range" min="1995" max="2113" step="0.25" value="2026.75">
|
||
<output id="yearOut">2026</output>
|
||
</div>
|
||
<div class="cap">
|
||
<h2>A · 年轮 <span class="pick">推荐</span></h2>
|
||
<p>一生 120 年的大运画成树的横截面。一圈是一段大运,宽窄等于年数,纹理随主星不同。走过的圈是墨色,没走的圈是浅色,赭色小点是“此刻”。</p>
|
||
<dl>
|
||
<dt>用到</dt><dd>大运起止、当前分运、上升度数(小点所在的那条线)</dd>
|
||
<dt>好在</dt><dd>讲时间不讲类型;换大运时画面真的会变,有理由回来看</dd>
|
||
<dt>顾虑</dt><dd>第一眼要读出“这是年轮”,需要底下那行小字帮忙</dd>
|
||
</dl>
|
||
</div>
|
||
</figure>
|
||
|
||
<figure>
|
||
<svg class="poster" id="pB" viewBox="0 0 600 800" role="img" aria-label="一笔画封面"></svg>
|
||
<div class="cap">
|
||
<h2>B · 一笔画</h2>
|
||
<p>九颗星按出生时的恒星黄道经度落在圆上,上升在左侧,按“日月火水木金土罗计”的顺序用一根手绘线连起来。</p>
|
||
<dl>
|
||
<dt>用到</dt><dd>九星经度、上升位置、上升与月亮星座(那一句话)</dd>
|
||
<dt>好在</dt><dd>最像一幅画;每个人的形状都不同,也都说得出来历</dd>
|
||
<dt>顾虑</dt><dd>不懂的人看不出和自己的关系;那句话容易滑向“贴标签”</dd>
|
||
</dl>
|
||
</div>
|
||
</figure>
|
||
|
||
<figure>
|
||
<svg class="poster" id="pC" viewBox="0 0 600 800" role="img" aria-label="出生时刻天空封面"></svg>
|
||
<div class="cap">
|
||
<h2>C · 那一刻的天空</h2>
|
||
<p>出生地、出生那一刻头顶的真实天空,天顶在圆心,东在左。地平线以上的行星点亮,亮星与北斗、仙后照实画。</p>
|
||
<dl>
|
||
<dt>用到</dt><dd>行星与亮星的真实高度、方位(需要出生地经纬度)</dd>
|
||
<dt>好在</dt><dd>最诚实、最浪漫,不做任何判断</dd>
|
||
<dt>顾虑</dt><dd>市面已有“出生星空图”;画面本身就泄露出生时间段与地点</dd>
|
||
</dl>
|
||
</div>
|
||
</figure>
|
||
</div>
|
||
|
||
<footer>样稿说明:星盘资料为虚构(1994 年 5 月,杭州),仅用于演示画法;文字是为样稿临时写的,正式版要对照文案口径再定。</footer>
|
||
</div>
|
||
|
||
<script>
|
||
const NS="http://www.w3.org/2000/svg";
|
||
const C={paper:"#f7f4ee",ink:"#2b2723",ink2:"#6e675d",faint:"#c9bda9",ochre:"#b0763a",night:"#1f1d1b",cream:"#efe7d8"};
|
||
function rng(seed){return function(){seed|=0;seed=seed+0x6D2B79F5|0;let t=Math.imul(seed^seed>>>15,1|seed);t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296}}
|
||
function el(tag,attrs,parent){const e=document.createElementNS(NS,tag);for(const k in attrs)e.setAttribute(k,attrs[k]);if(parent)parent.appendChild(e);return e}
|
||
function txt(parent,x,y,s,o={}){const t=el("text",Object.assign({x,y,fill:C.ink,"font-family":"Noto Serif SC, Songti SC, serif","font-size":14},o),parent);t.textContent=s;return t}
|
||
function closedPath(pts){let d="";const n=pts.length;for(let i=0;i<n;i++){const p0=pts[(i-1+n)%n],p1=pts[i],p2=pts[(i+1)%n],p3=pts[(i+2)%n];if(i===0)d+=`M${p1[0].toFixed(1)},${p1[1].toFixed(1)}`;const c1=[p1[0]+(p2[0]-p0[0])/6,p1[1]+(p2[1]-p0[1])/6],c2=[p2[0]-(p3[0]-p1[0])/6,p2[1]-(p3[1]-p1[1])/6];d+=`C${c1[0].toFixed(1)},${c1[1].toFixed(1)} ${c2[0].toFixed(1)},${c2[1].toFixed(1)} ${p2[0].toFixed(1)},${p2[1].toFixed(1)}`}return d+"Z"}
|
||
function openPath(pts){let d=`M${pts[0][0].toFixed(1)},${pts[0][1].toFixed(1)}`;for(let i=0;i<pts.length-1;i++){const p0=pts[Math.max(0,i-1)],p1=pts[i],p2=pts[i+1],p3=pts[Math.min(pts.length-1,i+2)];const c1=[p1[0]+(p2[0]-p0[0])/6,p1[1]+(p2[1]-p0[1])/6],c2=[p2[0]-(p3[0]-p1[0])/6,p2[1]-(p3[1]-p1[1])/6];d+=`C${c1[0].toFixed(1)},${c1[1].toFixed(1)} ${c2[0].toFixed(1)},${c2[1].toFixed(1)} ${p2[0].toFixed(1)},${p2[1].toFixed(1)}`}return d}
|
||
function paperGrain(svg,id,base){const defs=el("defs",{},svg);const f=el("filter",{id,x:0,y:0,width:"100%",height:"100%"},defs);el("feTurbulence",{type:"fractalNoise",baseFrequency:.85,numOctaves:2,seed:7,result:"n"},f);el("feColorMatrix",{type:"matrix",values:"0 0 0 0 0.45 0 0 0 0 0.38 0 0 0 0 0.3 0 0 0 .07 0"},f);el("rect",{width:600,height:800,fill:base},svg);el("rect",{width:600,height:800,filter:`url(#${id})`},svg)}
|
||
|
||
/* ---------- data (computed with Swiss Ephemeris, Lahiri) ---------- */
|
||
const P={Sun:33.04,Moon:116.20,Mars:1.73,Mercury:51.47,Jupiter:193.83,Venus:62.52,Saturn:317.56,Rahu:210.06,Ketu:30.06};
|
||
const ASC=70.98, BIRTH=1994.38;
|
||
const ZH={Sun:"太阳",Moon:"月亮",Mars:"火星",Mercury:"水星",Jupiter:"木星",Venus:"金星",Saturn:"土星",Rahu:"罗睺",Ketu:"计都"};
|
||
const DASHA=[["Mercury",BIRTH,1999.17],["Ketu",1999.17,2006.17],["Venus",2006.17,2026.17],["Sun",2026.17,2032.17],["Moon",2032.17,2042.17],["Mars",2042.17,2049.17],["Rahu",2049.17,2067.17],["Jupiter",2067.17,2083.17],["Saturn",2083.17,2102.17],["Mercury",2102.17,BIRTH+120]];
|
||
const LINE={
|
||
Sun:"这一圈,轮到你自己站到光里。",Moon:"这一圈,先照顾好心里那个家。",Mars:"这一圈,力气要花在一件事上。",
|
||
Mercury:"这一圈,学、写、说,都会被听见。",Jupiter:"这一圈,有人愿意为你把门打开。",Venus:"这一圈,美和关系是你的功课。",
|
||
Saturn:"这一圈,慢,但每一步都算数。",Rahu:"这一圈,你会想走到更远的地方。",Ketu:"这一圈,放下的会比拿到的多。"};
|
||
const fmt=y=>{const yr=Math.floor(y),m=Math.round((y-yr)*12)+1;return `${yr}.${String(Math.min(m,12)).padStart(2,"0")}`};
|
||
|
||
/* ---------- A · 年轮 ---------- */
|
||
function drawA(now){
|
||
const svg=document.getElementById("pA");svg.innerHTML="";paperGrain(svg,"gA",C.paper);
|
||
const R=rng(19940518);const cx=300,cy=392,K=218/120;
|
||
const ph=[R()*6.28,R()*6.28,R()*6.28,R()*6.28];
|
||
const shape=(t,r)=>1+.035*Math.sin(t+ph[0])+.022*Math.sin(2*t+ph[1])+.012*Math.sin(3*t+ph[2])+(.8/Math.max(r,20))*Math.sin(7*t+ph[3]);
|
||
const ringPts=(r,jit,rr)=>{const pts=[];for(let i=0;i<96;i++){const t=i/96*Math.PI*2,k=r*shape(t,r)+jit*(rr()-.5);pts.push([cx+Math.cos(t)*k+r*.05,cy+Math.sin(t)*k*.97])}return pts};
|
||
const tex={Saturn:2.1,Mercury:3,Sun:3.4,Moon:4,Venus:5,Mars:4.6,Jupiter:7,Rahu:3.4,Ketu:4.2};
|
||
const g=el("g",{fill:"none"},svg);
|
||
const age=now-BIRTH;
|
||
DASHA.forEach(([lord,s,e])=>{
|
||
const r0=6+(s-BIRTH)*K,r1=6+(e-BIRTH)*K,lived=e<=now,cur=s<=now&&now<e;
|
||
const col=lived||cur?C.ink:C.faint;
|
||
const rr=rng(Math.round(s*100));
|
||
for(let r=r0+tex[lord];r<r1-1;r+=tex[lord]){
|
||
const inner=el("path",{d:closedPath(ringPts(r,lord==="Moon"?2.4:.9,rr)),stroke:col,"stroke-width":lord==="Venus"?.5:.4,opacity:lived||cur?.55:.75},g);
|
||
if(lord==="Rahu")inner.setAttribute("stroke-dasharray","6 3");
|
||
if(lord==="Ketu")inner.setAttribute("stroke-dasharray","1 3.2");
|
||
}
|
||
if(lord==="Mars"){for(let i=0;i<9;i++){const t=rr()*6.28,a=r0+2,b=r1-2;el("path",{d:`M${cx+Math.cos(t)*a},${cy+Math.sin(t)*a}L${cx+Math.cos(t+.01)*b},${cy+Math.sin(t+.01)*b}`,stroke:col,"stroke-width":.5,opacity:.6},g)}}
|
||
el("path",{d:closedPath(ringPts(r1,.6,rr)),stroke:col,"stroke-width":lived||cur?1.15:.9},g);
|
||
el("path",{d:closedPath(ringPts(r1+.6,1.4,rr)),stroke:col,"stroke-width":.35,opacity:.5},g);
|
||
});
|
||
el("circle",{cx:cx+.3,cy,r:3.2,fill:C.ink},g);
|
||
// 上升方向的细线 + 此刻
|
||
const th=Math.PI+ (ASC%30)/30*Math.PI*.5; // 双子 10°58′ → 左上方
|
||
const rNow=6+age*K;const shp=shape(th,rNow);
|
||
const px=cx+Math.cos(th)*rNow*shp+rNow*.05,py=cy+Math.sin(th)*rNow*shp*.97;
|
||
const rEnd=6+120*K+6;
|
||
el("path",{d:`M${cx},${cy}L${cx+Math.cos(th)*rEnd*1.04},${cy+Math.sin(th)*rEnd*1.02}`,stroke:C.ink2,"stroke-width":.5,"stroke-dasharray":"2 3"},svg);
|
||
el("circle",{cx:px,cy:py,r:9,fill:C.ochre,opacity:.18},svg);
|
||
el("circle",{cx:px,cy:py,r:4.2,fill:C.ochre},svg);
|
||
const [lord,s,e]=DASHA.find(([,s,e])=>s<=now&&now<e);
|
||
txt(svg,48,64,"JYOTISHA · 年 轮",{"font-size":12,fill:C.ink2,"letter-spacing":2});
|
||
txt(svg,552,64,`${Math.floor(now)}`,{"font-size":12,fill:C.ink2,"text-anchor":"end","letter-spacing":1});
|
||
el("line",{x1:48,y1:80,x2:552,y2:80,stroke:C.faint,"stroke-width":.8},svg);
|
||
txt(svg,48,146,LINE[lord],{"font-size":30,"font-weight":600,fill:C.ink});
|
||
el("line",{x1:48,y1:650,x2:552,y2:650,stroke:C.faint,"stroke-width":.8},svg);
|
||
const yrIn=Math.floor(now-s)+1,tot=Math.round(e-s);
|
||
txt(svg,48,686,`${ZH[lord]}大运`,{"font-size":16,"font-weight":600});
|
||
txt(svg,48,712,`${fmt(s)} — ${fmt(e)} · 第 ${yrIn} 年,共 ${tot} 年`,{"font-size":13,fill:C.ink2});
|
||
txt(svg,552,686,"墨色是走过的,浅色是还没走的",{"font-size":12,fill:C.ink2,"text-anchor":"end"});
|
||
txt(svg,552,712,"赭点:此刻",{"font-size":12,fill:C.ochre,"text-anchor":"end"});
|
||
txt(svg,300,764,"仅供自我探索,不替你做决定。",{"font-size":11,fill:C.ink2,"text-anchor":"middle"});
|
||
}
|
||
|
||
/* ---------- B · 一笔画 ---------- */
|
||
function drawB(){
|
||
const svg=document.getElementById("pB");paperGrain(svg,"gB",C.paper);
|
||
const cx=300,cy=400,Rr=190;const R=rng(51871);
|
||
const pos=lon=>{const a=Math.PI+(lon-ASC)*Math.PI/180;return[cx+Math.cos(a)*Rr,cy-Math.sin(a)*Rr]}; // 上升在左,逆时针
|
||
// 铅笔导引圆
|
||
for(let k=0;k<2;k++){const pts=[];for(let i=0;i<120;i++){const t=i/120*6.283;const r=Rr+(R()-.5)*1.4+k*1.2;pts.push([cx+Math.cos(t)*r,cy+Math.sin(t)*r])}el("path",{d:closedPath(pts),fill:"none",stroke:C.faint,"stroke-width":.7},svg)}
|
||
const order=["Sun","Moon","Mars","Mercury","Jupiter","Venus","Saturn","Rahu","Ketu"];
|
||
const pts=order.map(k=>pos(P[k]));
|
||
// 在相邻点之间加一个略向圆心弯的控制点,让线条有呼吸
|
||
const path=[];pts.forEach((p,i)=>{path.push(p);if(i<pts.length-1){const q=pts[i+1];const m=[(p[0]+q[0])/2,(p[1]+q[1])/2];const pull=.18+R()*.12;path.push([m[0]+(cx-m[0])*pull+(R()-.5)*14,m[1]+(cy-m[1])*pull+(R()-.5)*14])}});
|
||
const g=el("g",{fill:"none","stroke-linecap":"round","stroke-linejoin":"round"},svg);
|
||
[[0,0,1.6,.9],[1.2,-.8,.7,.45],[-.9,1.1,.5,.35]].forEach(([dx,dy,w,o])=>{el("path",{d:openPath(path.map(p=>[p[0]+dx,p[1]+dy])),stroke:C.ink,"stroke-width":w,opacity:o},g)});
|
||
const SH={Sun:"日",Moon:"月",Mars:"火",Mercury:"水",Jupiter:"木",Venus:"金",Saturn:"土",Rahu:"罗",Ketu:"计"};
|
||
const placed=[];
|
||
order.map((k,i)=>[k,i]).sort((a,b)=>P[a[0]]-P[b[0]]).forEach(([k,i])=>{const [x,y]=pts[i];el("circle",{cx:x,cy:y,r:k==="Moon"?4.5:2.6,fill:k==="Moon"?C.ochre:C.ink},svg);
|
||
const a=Math.atan2(y-cy,x-cx);let d=22;while(placed.some(([px,py])=>Math.hypot(px-(cx+Math.cos(a)*(Rr+d)),py-(cy+Math.sin(a)*(Rr+d)))<15))d+=15;
|
||
const lx=cx+Math.cos(a)*(Rr+d),ly=cy+Math.sin(a)*(Rr+d);placed.push([lx,ly]);txt(svg,lx,ly+4,SH[k],{"font-size":12,fill:C.ink2,"text-anchor":"middle"})});
|
||
// 上升记号
|
||
el("line",{x1:cx-Rr-10,y1:cy,x2:cx-Rr+10,y2:cy,stroke:C.ochre,"stroke-width":1.4},svg);
|
||
txt(svg,cx-Rr-16,cy+4,"升",{"font-size":12,fill:C.ochre,"text-anchor":"end"});
|
||
txt(svg,48,64,"JYOTISHA · 一 笔",{"font-size":12,fill:C.ink2,"letter-spacing":2});
|
||
el("line",{x1:48,y1:80,x2:552,y2:80,stroke:C.faint,"stroke-width":.8},svg);
|
||
txt(svg,48,146,"脑子先出门,心留在家里。",{"font-size":30,"font-weight":600});
|
||
el("line",{x1:48,y1:650,x2:552,y2:650,stroke:C.faint,"stroke-width":.8},svg);
|
||
txt(svg,48,686,"双子上升 · 巨蟹月亮",{"font-size":16,"font-weight":600});
|
||
txt(svg,48,712,"九星按出生时的位置落在圆上,依日月火水木金土罗计连成一笔",{"font-size":12.5,fill:C.ink2});
|
||
txt(svg,552,686,"赭点:月亮,也是 AK",{"font-size":12,fill:C.ochre,"text-anchor":"end"});
|
||
txt(svg,300,764,"仅供自我探索,不替你做决定。",{"font-size":11,fill:C.ink2,"text-anchor":"middle"});
|
||
}
|
||
|
||
/* ---------- C · 那一刻的天空 ---------- */
|
||
function drawC(){
|
||
const svg=document.getElementById("pC");paperGrain(svg,"gC",C.night);
|
||
const cx=300,cy=400,Rr=200,LAT=30.27*Math.PI/180,LST=350.59;
|
||
const proj=(alt,az)=>{const r=(90-alt)/90*Rr,a=az*Math.PI/180;return[cx-r*Math.sin(a),cy-r*Math.cos(a)]}; // 北上东左
|
||
const altaz=(raH,dec)=>{const H=(LST-raH*15)*Math.PI/180,d=dec*Math.PI/180;const sa=Math.sin(d)*Math.sin(LAT)+Math.cos(d)*Math.cos(LAT)*Math.cos(H);const alt=Math.asin(sa);let az=Math.atan2(-Math.cos(d)*Math.sin(H),Math.sin(d)*Math.cos(LAT)-Math.cos(d)*Math.sin(LAT)*Math.cos(H));return[alt*180/Math.PI,(az*180/Math.PI+360)%360]};
|
||
const S={Sirius:[6.752,-16.72,-1.4],Arcturus:[14.261,19.18,0],Vega:[18.616,38.78,0],Capella:[5.278,46,.1],Rigel:[5.242,-8.2,.1],Procyon:[7.655,5.22,.4],Betelgeuse:[5.919,7.41,.5],Altair:[19.846,8.87,.8],Aldebaran:[4.599,16.51,.9],Antares:[16.49,-26.43,1],Spica:[13.42,-11.16,1],Pollux:[7.755,28.03,1.1],Fomalhaut:[22.961,-29.62,1.2],Deneb:[20.69,45.28,1.3],Regulus:[10.14,11.97,1.4],Castor:[7.577,31.89,1.6],Polaris:[2.53,89.26,2],Hamal:[2.12,23.46,2],Alpheratz:[0.14,29.09,2.1],Mirfak:[3.405,49.86,1.8],Algol:[3.136,40.96,2.1],Denebola:[11.818,14.57,2.1],Alphard:[9.46,-8.66,2],Rasalhague:[17.582,12.56,2.1],Enif:[21.736,9.88,2.4],Markab:[23.079,15.21,2.5],Scheat:[23.063,28.08,2.4],Algenib:[0.22,15.18,2.8],Sadr:[20.37,40.26,2.2],Albireo:[19.512,27.96,3],
|
||
Dubhe:[11.062,61.75,1.8],Merak:[11.031,56.38,2.4],Phecda:[11.897,53.69,2.4],Megrez:[12.257,57.03,3.3],Alioth:[12.9,55.96,1.8],Mizar:[13.399,54.93,2.2],Alkaid:[13.792,49.31,1.9],
|
||
Caph:[0.153,59.15,2.3],Schedar:[0.675,56.54,2.2],Navi:[0.945,60.72,2.4],Ruchbah:[1.43,60.24,2.7],Segin:[1.907,63.67,3.4]};
|
||
const lines=[["Dubhe","Merak","Phecda","Megrez","Alioth","Mizar","Alkaid"],["Megrez","Dubhe"],["Caph","Schedar","Navi","Ruchbah","Segin"]];
|
||
const clip=el("clipPath",{id:"sky"},el("defs",{},svg));el("circle",{cx,cy,r:Rr},clip);
|
||
const g=el("g",{"clip-path":"url(#sky)"},svg);
|
||
// 高度圈
|
||
[30,60].forEach(a=>el("circle",{cx,cy,r:(90-a)/90*Rr,fill:"none",stroke:C.cream,"stroke-width":.4,opacity:.18,"stroke-dasharray":"1 4"},g));
|
||
const XY={};
|
||
for(const k in S){const[ra,dec,m]=S[k];const[al,az]=altaz(ra,dec);if(al<0)continue;XY[k]=proj(al,az);el("circle",{cx:XY[k][0],cy:XY[k][1],r:Math.max(.7,2.4-m*.55),fill:C.cream,opacity:.85},g)}
|
||
lines.forEach(L=>{const p=L.filter(k=>XY[k]).map(k=>XY[k]);if(p.length>1)el("path",{d:"M"+p.map(q=>q.join(",")).join("L"),fill:"none",stroke:C.cream,"stroke-width":.5,opacity:.4},g)});
|
||
// 行星(真实高度、方位;swisseph 方位自南起算,已换成自北)
|
||
const PL={Sun:[31.71,84.69],Mars:[52.33,117.24],Mercury:[17.78,71.14],Venus:[7.95,65.88],Saturn:[50.31,191.14]};
|
||
for(const k in PL){const[x,y]=proj(...PL[k]);if(k==="Sun"){el("circle",{cx:x,cy:y,r:16,fill:C.ochre,opacity:.18},g);el("circle",{cx:x,cy:y,r:6,fill:"none",stroke:C.ochre,"stroke-width":1.4},g);el("circle",{cx:x,cy:y,r:1.6,fill:C.ochre},g)}else el("circle",{cx:x,cy:y,r:3.2,fill:C.cream},g);
|
||
txt(svg,x+(k==="Venus"?-9:9),y+(k==="Venus"?14:-7),ZH[k],{"font-size":11,fill:k==="Sun"?C.ochre:C.cream,opacity:.9,"text-anchor":k==="Venus"?"end":"start"})}
|
||
el("circle",{cx,cy,r:Rr,fill:"none",stroke:C.cream,"stroke-width":.9,opacity:.6},svg);
|
||
[["北",0,-1],["南",0,1],["东",-1,0],["西",1,0]].forEach(([s,dx,dy])=>txt(svg,cx+dx*(Rr+18),cy+dy*(Rr+18)+4,s,{"font-size":12,fill:C.cream,opacity:.6,"text-anchor":"middle"}));
|
||
txt(svg,48,64,"JYOTISHA · 那 一 刻",{"font-size":12,fill:C.cream,opacity:.6,"letter-spacing":2});
|
||
el("line",{x1:48,y1:80,x2:552,y2:80,stroke:C.cream,"stroke-width":.6,opacity:.25},svg);
|
||
txt(svg,48,146,"星星都在,只是还看不见。",{"font-size":30,"font-weight":600,fill:C.cream});
|
||
el("line",{x1:48,y1:650,x2:552,y2:650,stroke:C.cream,"stroke-width":.6,opacity:.25},svg);
|
||
txt(svg,48,686,"你出生时,太阳已经升起两个多小时",{"font-size":15,"font-weight":600,fill:C.cream});
|
||
txt(svg,48,712,"月亮与木星在脚下,土星正悬在南方",{"font-size":12.5,fill:C.cream,opacity:.65});
|
||
txt(svg,300,764,"仅供自我探索,不替你做决定。",{"font-size":11,fill:C.cream,opacity:.5,"text-anchor":"middle"});
|
||
}
|
||
|
||
drawA(2026.75);drawB();drawC();
|
||
const yr=document.getElementById("year"),out=document.getElementById("yearOut");
|
||
yr.addEventListener("input",()=>{const v=+yr.value;out.textContent=Math.floor(v);drawA(v)});
|
||
if(document.fonts)document.fonts.ready.then(()=>{drawA(+yr.value)});
|
||
</script>
|