Files
LanMountainDesktop/mocks/weather-widget-mock.html

210 lines
12 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气组件 Mock V2 - 阑山桌面</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
background: #1a1a2e; color: #fff; padding: 32px 20px; min-height: 100vh;
}
.controls {
display: flex; gap: 12px; align-items: center; justify-content: center;
margin-bottom: 32px; flex-wrap: wrap;
}
.controls button {
padding: 8px 18px; border: 1px solid rgba(255,255,255,0.2);
border-radius: 8px; background: rgba(255,255,255,0.08);
color: #fff; cursor: pointer; font-size: 13px; transition: all 0.2s;
}
.controls button:hover { background: rgba(255,255,255,0.16); }
.controls button.active { background: rgba(79,195,247,0.25); border-color: #4FC3F7; }
.section-title { text-align: center; font-size: 16px; font-weight: 600; margin: 24px 0 12px; color: #888; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px; max-width: 1400px; margin: 0 auto; }
.widget { border-radius: 24px; overflow: hidden; position: relative; height: 280px; box-shadow: 0 8px 32px rgba(0,0,0,0.2); }
.widget-bg { position: absolute; inset: 0; z-index: 0; }
.widget-overlay { position: absolute; inset: 0; z-index: 1; }
.widget-content { position: relative; z-index: 2; padding: 20px 22px; height: 100%; display: flex; flex-direction: column; justify-content: space-between; }
.widget-top { display: flex; justify-content: space-between; align-items: flex-start; }
.temp { font-size: 64px; font-weight: 700; line-height: 1; letter-spacing: -2px; }
.condition { font-size: 17px; font-weight: 600; opacity: 0.88; margin-top: 2px; }
.icon-block { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.weather-icon { width: 72px; height: 72px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 36px; background: rgba(255,255,255,0.12); backdrop-filter: blur(8px); }
.range { font-size: 13px; font-weight: 500; opacity: 0.72; }
.widget-bottom { display: flex; justify-content: space-between; align-items: flex-end; }
.location { font-size: 14px; font-weight: 600; opacity: 0.78; }
.metrics { display: flex; gap: 6px; }
.metric-tag { padding: 3px 8px; border-radius: 8px; font-size: 11px; font-weight: 600; background: rgba(255,255,255,0.12); backdrop-filter: blur(4px); }
</style>
</head>
<body>
<div class="controls">
<button id="btnDay" class="active" onclick="setTime('day')">☀️ 白天</button>
<button id="btnNight" onclick="setTime('night')">🌙 夜晚</button>
<span style="color:#666;margin:0 8px">|</span>
<button id="btnClear" class="active" onclick="setWeather('clear')">☀️ 晴</button>
<button id="btnRain" onclick="setWeather('rain')">🌧️ 雨</button>
<button id="btnCloudy" onclick="setWeather('cloudy')">☁️ 多云</button>
</div>
<div class="section-title">Google Weather — 纯渐变,无装饰</div>
<div class="grid" id="gridGoogle"></div>
<div class="section-title">Geometric — 径向渐变光晕 + 弧线段</div>
<div class="grid" id="gridGeometric"></div>
<div class="section-title">Breezy — 径向渐变光晕 + 波浪线 + 弧线段</div>
<div class="grid" id="gridBreezy"></div>
<div class="section-title">Lemon — 径向渐变光晕 + 天气场景装饰</div>
<div class="grid" id="gridLemon"></div>
<script>
function hexToRgb(hex) {
const r = parseInt(hex.slice(1,3),16), g = parseInt(hex.slice(3,5),16), b = parseInt(hex.slice(5,7),16);
return {r,g,b};
}
function rgba(hex, a) { const c = hexToRgb(hex); return `rgba(${c.r},${c.g},${c.b},${a})`; }
const P = {
google: {
clear: {
day: { top:'#4FC3F7', bottom:'#B3E5FC', text:'#0D47A1', textSec:'#1565C0', overlay:'rgba(255,255,255,0.08)', shapes:[] },
night: { top:'#0D47A1', bottom:'#1A237E', text:'#E8EAF6', textSec:'#9FA8DA', overlay:'rgba(0,0,0,0.12)', shapes:[] },
},
rain: { day: { top:'#78909C', bottom:'#B0BEC5', text:'#263238', textSec:'#37474F', overlay:'rgba(255,255,255,0.06)', shapes:[] }, night: { top:'#263238', bottom:'#37474F', text:'#CFD8DC', textSec:'#90A4AE', overlay:'rgba(0,0,0,0.15)', shapes:[] } },
cloudy: { day: { top:'#90A4AE', bottom:'#CFD8DC', text:'#263238', textSec:'#455A64', overlay:'rgba(255,255,255,0.06)', shapes:[] }, night: { top:'#37474F', bottom:'#455A64', text:'#CFD8DC', textSec:'#90A4AE', overlay:'rgba(0,0,0,0.12)', shapes:[] } },
},
geometric: {
clear: {
day: { top:'#1A237E', bottom:'#3949AB', text:'#E8EAF6', textSec:'#9FA8DA', overlay:'rgba(255,255,255,0.04)',
shapes:[{x:0.78,y:0.20,r:0.55,c:'#5C6BC0',a:0.22},{x:0.12,y:0.68,r:0.42,c:'#3F51B5',a:0.18},{x:0.52,y:0.82,r:0.32,c:'#7986CB',a:0.14},{x:0.35,y:0.12,r:0.28,c:'#7986CB',a:0.08},{x:0.88,y:0.55,r:0.22,c:'#5C6BC0',a:0.10}] },
night: { top:'#0A0E27', bottom:'#1A1A3E', text:'#C5CAE9', textSec:'#7986CB', overlay:'rgba(255,255,255,0.03)',
shapes:[{x:0.78,y:0.20,r:0.55,c:'#1A237E',a:0.25},{x:0.12,y:0.68,r:0.42,c:'#283593',a:0.20},{x:0.52,y:0.82,r:0.32,c:'#3F51B5',a:0.16}] },
},
rain: {
day: { top:'#1A237E', bottom:'#3F51B5', text:'#E8EAF6', textSec:'#9FA8DA', overlay:'rgba(255,255,255,0.04)',
shapes:[{x:0.72,y:0.22,r:0.50,c:'#5C6BC0',a:0.20},{x:0.18,y:0.65,r:0.38,c:'#3F51B5',a:0.16},{x:0.55,y:0.80,r:0.28,c:'#7986CB',a:0.12}] },
night: { top:'#0A0E27', bottom:'#1A1A3E', text:'#C5CAE9', textSec:'#7986CB', overlay:'rgba(255,255,255,0.03)',
shapes:[{x:0.75,y:0.18,r:0.48,c:'#1A237E',a:0.22},{x:0.15,y:0.62,r:0.36,c:'#283593',a:0.18}] },
},
cloudy: {
day: { top:'#37474F', bottom:'#607D8B', text:'#ECEFF1', textSec:'#B0BEC5', overlay:'rgba(255,255,255,0.04)',
shapes:[{x:0.70,y:0.25,r:0.48,c:'#78909C',a:0.18},{x:0.20,y:0.60,r:0.36,c:'#607D8B',a:0.14},{x:0.50,y:0.78,r:0.26,c:'#90A4AE',a:0.10}] },
night: { top:'#1A1A2E', bottom:'#2D2D44', text:'#CFD8DC', textSec:'#90A4AE', overlay:'rgba(255,255,255,0.03)',
shapes:[{x:0.72,y:0.22,r:0.45,c:'#37474F',a:0.20},{x:0.18,y:0.58,r:0.34,c:'#455A64',a:0.16}] },
},
},
breezy: {
clear: {
day: { top:'#4DD0E1', bottom:'#80DEEA', text:'#004D40', textSec:'#00695C', overlay:'rgba(255,255,255,0.08)',
shapes:[{x:0.72,y:0.25,r:0.48,c:'#26C6DA',a:0.20},{x:0.20,y:0.60,r:0.36,c:'#00BCD4',a:0.16},{x:0.50,y:0.80,r:0.28,c:'#B2EBF2',a:0.12}] },
night: { top:'#006064', bottom:'#00838F', text:'#E0F7FA', textSec:'#80DEEA', overlay:'rgba(0,0,0,0.12)',
shapes:[{x:0.72,y:0.25,r:0.48,c:'#4DD0E1',a:0.18},{x:0.20,y:0.60,r:0.36,c:'#00ACC1',a:0.14}] },
},
rain: {
day: { top:'#4DB6AC', bottom:'#80CBC4', text:'#004D40', textSec:'#00695C', overlay:'rgba(255,255,255,0.06)',
shapes:[{x:0.68,y:0.28,r:0.44,c:'#66BB6A',a:0.16},{x:0.22,y:0.58,r:0.32,c:'#4DB6AC',a:0.12}] },
night: { top:'#004D40', bottom:'#00695C', text:'#E0F2F1', textSec:'#80CBC4', overlay:'rgba(0,0,0,0.15)',
shapes:[{x:0.70,y:0.22,r:0.42,c:'#4DB6AC',a:0.14},{x:0.18,y:0.55,r:0.30,c:'#00897B',a:0.10}] },
},
cloudy: {
day: { top:'#80CBC4', bottom:'#B2DFDB', text:'#004D40', textSec:'#00695C', overlay:'rgba(255,255,255,0.06)',
shapes:[{x:0.70,y:0.28,r:0.44,c:'#A7D9D2',a:0.16},{x:0.22,y:0.55,r:0.32,c:'#80CBC4',a:0.12}] },
night: { top:'#37474F', bottom:'#546E7A', text:'#ECEFF1', textSec:'#B0BEC5', overlay:'rgba(0,0,0,0.12)',
shapes:[{x:0.72,y:0.22,r:0.42,c:'#78909C',a:0.14},{x:0.18,y:0.58,r:0.30,c:'#607D8B',a:0.10}] },
},
},
lemon: {
clear: {
day: { top:'#FFB74D', bottom:'#FFF176', text:'#4E342E', textSec:'#6D4C41', overlay:'rgba(255,255,255,0.06)',
shapes:[{x:0.70,y:0.25,r:0.35,c:'#FF9800',a:0.28},{x:0.70,y:0.25,r:0.18,c:'#FFC107',a:0.45},{x:0.15,y:0.70,r:0.30,c:'#FF8A65',a:0.10},{x:0.85,y:0.55,r:0.22,c:'#FFE082',a:0.08}] },
night: { top:'#1A237E', bottom:'#311B92', text:'#E8EAF6', textSec:'#B39DDB', overlay:'rgba(0,0,0,0.12)',
shapes:[{x:0.72,y:0.22,r:0.40,c:'#FFD54F',a:0.15},{x:0.15,y:0.68,r:0.30,c:'#7C4DFF',a:0.10},{x:0.85,y:0.55,r:0.22,c:'#B388FF',a:0.08}] },
},
rain: {
day: { top:'#90A4AE', bottom:'#B0BEC5', text:'#263238', textSec:'#37474F', overlay:'rgba(255,255,255,0.06)',
shapes:[{x:0.65,y:0.25,r:0.38,c:'#78909C',a:0.14},{x:0.30,y:0.50,r:0.30,c:'#607D8B',a:0.10},{x:0.15,y:0.70,r:0.30,c:'#B0BEC5',a:0.10}] },
night: { top:'#1A1A2E', bottom:'#311B92', text:'#D1C4E9', textSec:'#9575CD', overlay:'rgba(0,0,0,0.15)',
shapes:[{x:0.68,y:0.22,r:0.38,c:'#7C4DFF',a:0.12},{x:0.25,y:0.55,r:0.28,c:'#5C6BC0',a:0.08}] },
},
cloudy: {
day: { top:'#BCAAA4', bottom:'#D7CCC8', text:'#3E2723', textSec:'#5D4037', overlay:'rgba(255,255,255,0.06)',
shapes:[{x:0.60,y:0.30,r:0.40,c:'#A1887F',a:0.16},{x:0.35,y:0.55,r:0.32,c:'#8D6E63',a:0.12},{x:0.15,y:0.70,r:0.30,c:'#BCAAA4',a:0.10}] },
night: { top:'#37474F', bottom:'#4E342E', text:'#EFEBE9', textSec:'#BCAAA4', overlay:'rgba(0,0,0,0.12)',
shapes:[{x:0.65,y:0.28,r:0.38,c:'#8D6E63',a:0.12},{x:0.25,y:0.55,r:0.28,c:'#6D4C41',a:0.08}] },
},
},
};
const ICONS = { clear:'☀️', rain:'🌧️', cloudy:'☁️' };
const NAMES = { clear:'晴', rain:'小雨', cloudy:'多云' };
const RANGES = { clear:'18° / 32°', rain:'14° / 22°', cloudy:'16° / 26°' };
const TEMPS = { clear:'28°', rain:'18°', cloudy:'22°' };
let curTime='day', curWeather='clear';
function createWidget(style, time, weather) {
const p = P[style][weather][time];
const icon = ICONS[weather];
let shapesHTML = '';
if (p.shapes && p.shapes.length > 0) {
shapesHTML = p.shapes.map(s => {
const size = s.r * 100;
return `<div style="position:absolute;left:${s.x*100}%;top:${s.y*100}%;width:${size}vmin;height:${size}vmin;transform:translate(-50%,-50%);border-radius:50%;background:radial-gradient(circle,${rgba(s.c,s.a)} 0%,${rgba(s.c,s.a*0.6)} 40%,${rgba(s.c,0)} 100%);z-index:0;pointer-events:none"></div>`;
}).join('');
}
return `
<div class="widget">
<div class="widget-bg" style="background:linear-gradient(135deg,${p.top},${p.bottom})"></div>
${shapesHTML}
<div class="widget-overlay" style="background:${p.overlay}"></div>
<div class="widget-content">
<div class="widget-top">
<div>
<div class="temp" style="color:${p.text}">${TEMPS[weather]}</div>
<div class="condition" style="color:${p.text}">${NAMES[weather]}</div>
</div>
<div class="icon-block">
<div class="weather-icon">${icon}</div>
<div class="range" style="color:${p.textSec}">${RANGES[weather]}</div>
</div>
</div>
<div class="widget-bottom">
<div class="location" style="color:${p.textSec}">📍 北京</div>
<div class="metrics">
<span class="metric-tag" style="color:${p.text}">💧 58%</span>
<span class="metric-tag" style="color:${p.text}">🌬️ 12km/h</span>
<span class="metric-tag" style="color:${p.text}">🌫️ AQI 42</span>
</div>
</div>
</div>
</div>`;
}
function renderAll() {
['google','geometric','breezy','lemon'].forEach(style => {
document.getElementById('grid'+style.charAt(0).toUpperCase()+style.slice(1)).innerHTML = createWidget(style, curTime, curWeather);
});
}
function setTime(t) {
curTime=t;
document.getElementById('btnDay').classList.toggle('active',t==='day');
document.getElementById('btnNight').classList.toggle('active',t==='night');
renderAll();
}
function setWeather(w) {
curWeather=w;
['Clear','Rain','Cloudy'].forEach(n => document.getElementById('btn'+n).classList.toggle('active',w===n.toLowerCase()));
renderAll();
}
renderAll();
</script>
</body>
</html>