feat: implement Material 3 expressive design
This commit is contained in:
+23
-23
@@ -34,7 +34,7 @@ export default {
|
||||
systemGain: 1.0,
|
||||
params: cloneDefaultParams(),
|
||||
// 模式切換
|
||||
isDarkMode: true,
|
||||
isDarkMode: false,
|
||||
// 係數倍率微調
|
||||
baseB: [0.5, 0.5, 0, 0, 0, 0, 0],
|
||||
baseA: [1, 0, 0, 0, 0, 0, 0],
|
||||
@@ -846,13 +846,13 @@ export default {
|
||||
shapes.push({
|
||||
type: 'line', x0: xVal, x1: xVal, y0: 0, y1: 1,
|
||||
xref: row === 1 ? 'x' : 'x2', yref: yref + ' domain',
|
||||
line: { color: isDark ? 'rgba(255,0,0,0.5)' : 'rgba(220,0,0,0.6)', width: 1.5, dash: 'dash' }
|
||||
line: { color: isDark ? 'rgba(242,184,181,0.72)' : 'rgba(186,26,26,0.72)', width: 1.4, dash: 'dash' }
|
||||
});
|
||||
if (text) {
|
||||
annotations.push({
|
||||
x: Math.log10(xVal), y: 1, text: text,
|
||||
xref: row === 1 ? 'x' : 'x2', yref: yref + ' domain',
|
||||
showarrow: false, font: { color: isDark ? 'rgba(255,100,100,0.8)' : 'rgba(180,50,50,1)', size: isSmallScreen ? 10 : 12 },
|
||||
showarrow: false, font: { color: isDark ? '#f2b8b5' : '#ba1a1a', size: isSmallScreen ? 10 : 12 },
|
||||
yshift: isSmallScreen ? 15 : 12,
|
||||
xanchor: 'center',
|
||||
yanchor: isSmallScreen ? 'middle' : 'bottom',
|
||||
@@ -869,7 +869,7 @@ export default {
|
||||
for (let p = pStart; p <= pEnd; p++) {
|
||||
const v = Math.pow(10, p);
|
||||
if (v >= fMin && v <= fMax) {
|
||||
const gridColor = isDark ? 'rgba(128,128,128,0.5)' : 'rgba(100,100,100,0.3)';
|
||||
const gridColor = isDark ? 'rgba(198,204,216,0.24)' : 'rgba(63,95,159,0.14)';
|
||||
shapes.push(
|
||||
{ type: 'line', x0: v, x1: v, y0: 0, y1: 1, xref: 'x', yref: 'y domain', line: { color: gridColor, width: 1.5 } },
|
||||
{ type: 'line', x0: v, x1: v, y0: 0, y1: 1, xref: 'x2', yref: 'y2 domain', line: { color: gridColor, width: 1.5 } }
|
||||
@@ -877,10 +877,10 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
const gridColor = isDark ? 'rgba(128,128,128,0.2)' : 'rgba(0,0,0,0.1)';
|
||||
const zeroLineColor = isDark ? '#4b5563' : '#cbd5e1';
|
||||
const textColor = isDark ? '#9ca3af' : '#475569';
|
||||
const titleColor = isDark ? '#d1d5db' : '#1e293b';
|
||||
const gridColor = isDark ? 'rgba(198,204,216,0.14)' : 'rgba(63,95,159,0.08)';
|
||||
const zeroLineColor = isDark ? 'rgba(198,204,216,0.24)' : 'rgba(70,75,85,0.18)';
|
||||
const textColor = isDark ? '#c6ccd8' : '#38404c';
|
||||
const titleColor = isDark ? '#e4e7ef' : '#1a1b1f';
|
||||
|
||||
const xAxisCommon = {
|
||||
type: 'log', title: { text: 'Freq (Hz)', font: { size: isSmallScreen ? 12 : 14 } },
|
||||
@@ -896,21 +896,21 @@ export default {
|
||||
margin: isSmallScreen ? { t: 80, b: 120, l: 55, r: 15 } : { t: 70, b: 120, l: 70, r: 30 },
|
||||
showlegend: false,
|
||||
grid: { rows: 2, columns: 1, pattern: 'independent', roworder: 'top to bottom', ygap: isSmallScreen ? 0.35 : 0.3 },
|
||||
font: { color: textColor, family: 'Inter, sans-serif' },
|
||||
font: { color: textColor, family: 'Google Sans, Roboto, sans-serif' },
|
||||
annotations: [
|
||||
{ text: 'Magnitude Response (dB)', xref: 'x domain', yref: 'y domain', x: 0.5, y: isSmallScreen ? 1.25 : 1.15, showarrow: false, font: { size: isSmallScreen ? 14 : 16, color: titleColor, weight: 'bold' } },
|
||||
{ text: 'Phase Response (Deg)', xref: 'x2 domain', yref: 'y2 domain', x: 0.5, y: isSmallScreen ? 1.25 : 1.15, showarrow: false, font: { size: isSmallScreen ? 14 : 16, color: titleColor, weight: 'bold' } },
|
||||
|
||||
// 手動 Magnitude 圖例 (位於上方圖表下方)
|
||||
{ xref: 'paper', yref: 'paper', x: 0.35, y: isSmallScreen ? 0.52 : 0.54, text: '一一一', font: { color: isDark ? '#3b82f6' : '#2563eb', size: 10 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.35, y: isSmallScreen ? 0.52 : 0.54, text: '一一一', font: { color: isDark ? '#b9c6ff' : '#3f5f9f', size: 10 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.42, y: isSmallScreen ? 0.52 : 0.54, text: 'Ideal (Float)', font: { color: textColor, size: 11 }, showarrow: false, xanchor: 'left' },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.58, y: isSmallScreen ? 0.52 : 0.54, text: '· · · ·', font: { color: isDark ? '#10b981' : '#059669', size: 14 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.58, y: isSmallScreen ? 0.52 : 0.54, text: '· · · ·', font: { color: isDark ? '#d7da7d' : '#6d702b', size: 14 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.63, y: isSmallScreen ? 0.52 : 0.54, text: `Fixed (b Q${this.shiftBitsB}, a Q${this.shiftBitsA})`, font: { color: textColor, size: 11 }, showarrow: false, xanchor: 'left' },
|
||||
|
||||
// 手動 Phase 圖例 (位於下方圖表下方)
|
||||
{ xref: 'paper', yref: 'paper', x: 0.35, y: -0.15, text: '一一一', font: { color: isDark ? '#f97316' : '#ea580c', size: 10 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.35, y: -0.15, text: '一一一', font: { color: isDark ? '#c4c9d8' : '#4f6f80', size: 10 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.42, y: -0.15, text: 'Ideal Phase', font: { color: textColor, size: 11 }, showarrow: false, xanchor: 'left' },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.58, y: -0.15, text: '· · · ·', font: { color: isDark ? '#f43f5e' : '#e11d48', size: 14 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.58, y: -0.15, text: '· · · ·', font: { color: isDark ? '#f2b8b5' : '#ba1a1a', size: 14 }, showarrow: false },
|
||||
{ xref: 'paper', yref: 'paper', x: 0.63, y: -0.15, text: 'Fixed Phase', font: { color: textColor, size: 11 }, showarrow: false, xanchor: 'left' },
|
||||
|
||||
...annotations
|
||||
@@ -922,11 +922,11 @@ export default {
|
||||
shapes: shapes
|
||||
};
|
||||
|
||||
const traceMagIdeal = { x: freq, y: magIdeal, name: 'Ideal (Float)', type: 'scatter', line: { color: isDark ? '#3b82f6' : '#2563eb', width: 2.5 } };
|
||||
const traceMagFixed = { x: freq, y: magFixed, name: `Fixed (b Q${this.shiftBitsB}, a Q${this.shiftBitsA})`, type: 'scatter', line: { color: isDark ? '#10b981' : '#059669', width: 2, dash: 'dot' } };
|
||||
const traceMagIdeal = { x: freq, y: magIdeal, name: 'Ideal (Float)', type: 'scatter', line: { color: isDark ? '#b9c6ff' : '#3f5f9f', width: 2.8 } };
|
||||
const traceMagFixed = { x: freq, y: magFixed, name: `Fixed (b Q${this.shiftBitsB}, a Q${this.shiftBitsA})`, type: 'scatter', line: { color: isDark ? '#d7da7d' : '#6d702b', width: 2.4, dash: 'dot' } };
|
||||
|
||||
const tracePhaseIdeal = { x: freq, y: phaseIdeal, name: 'Ideal Phase', type: 'scatter', line: { color: isDark ? '#f97316' : '#ea580c', width: 2.5 }, xaxis: 'x2', yaxis: 'y2' };
|
||||
const tracePhaseFixed = { x: freq, y: phaseFixed, name: 'Fixed Phase', type: 'scatter', line: { color: isDark ? '#f43f5e' : '#e11d48', width: 2, dash: 'dot' }, xaxis: 'x2', yaxis: 'y2' };
|
||||
const tracePhaseIdeal = { x: freq, y: phaseIdeal, name: 'Ideal Phase', type: 'scatter', line: { color: isDark ? '#c4c9d8' : '#4f6f80', width: 2.8 }, xaxis: 'x2', yaxis: 'y2' };
|
||||
const tracePhaseFixed = { x: freq, y: phaseFixed, name: 'Fixed Phase', type: 'scatter', line: { color: isDark ? '#f2b8b5' : '#ba1a1a', width: 2.4, dash: 'dot' }, xaxis: 'x2', yaxis: 'y2' };
|
||||
|
||||
Plotly.react('bodePlot', [traceMagIdeal, traceMagFixed, tracePhaseIdeal, tracePhaseFixed], layout, { responsive: true });
|
||||
},
|
||||
@@ -1077,21 +1077,21 @@ export default {
|
||||
drawTimePlot(data) {
|
||||
const isDark = this.isDarkMode;
|
||||
const isSmallScreen = window.innerWidth < 768;
|
||||
const gridColor = isDark ? 'rgba(128,128,128,0.2)' : 'rgba(0,0,0,0.1)';
|
||||
const zeroLineColor = isDark ? '#4b5563' : '#cbd5e1';
|
||||
const textColor = isDark ? '#9ca3af' : '#475569';
|
||||
const gridColor = isDark ? 'rgba(198,204,216,0.14)' : 'rgba(63,95,159,0.08)';
|
||||
const zeroLineColor = isDark ? 'rgba(198,204,216,0.24)' : 'rgba(70,75,85,0.18)';
|
||||
const textColor = isDark ? '#c6ccd8' : '#38404c';
|
||||
|
||||
const layout = {
|
||||
paper_bgcolor: 'transparent', plot_bgcolor: 'transparent',
|
||||
margin: isSmallScreen ? { t: 60, b: 60, l: 45, r: 15 } : { t: 40, b: 55, l: 60, r: 20 },
|
||||
font: { color: textColor, family: 'Inter, sans-serif' },
|
||||
font: { color: textColor, family: 'Google Sans, Roboto, sans-serif' },
|
||||
xaxis: { title: { text: 'Sample Index', font: { size: isSmallScreen ? 10 : 11 } }, gridcolor: gridColor, zerolinecolor: zeroLineColor, tickfont: { color: textColor, size: isSmallScreen ? 9 : 11 } },
|
||||
yaxis: { title: { text: 'Amplitude', font: { size: isSmallScreen ? 10 : 11 } }, gridcolor: gridColor, zerolinecolor: zeroLineColor, tickfont: { color: textColor, size: isSmallScreen ? 9 : 11 } },
|
||||
legend: { orientation: 'h', y: 1.02, yanchor: 'bottom', x: 1, xanchor: 'right', font: { color: textColor, size: isSmallScreen ? 9 : 10 } }
|
||||
};
|
||||
Plotly.react('timePlot', [
|
||||
{ x: data.index, y: data.original, name: '原始輸入訊號 (Input)', type: 'scatter', line: { color: isDark ? '#00cc96' : '#059669' }, opacity: 0.7 },
|
||||
{ x: data.index, y: data.filtered, name: '濾波後輸出 (Output)', type: 'scatter', line: { color: isDark ? '#ef553b' : '#dc2626' }, opacity: 0.9 }
|
||||
{ x: data.index, y: data.original, name: '原始輸入訊號 (Input)', type: 'scatter', line: { color: isDark ? '#b9c6ff' : '#3f5f9f', width: 2.4 }, opacity: 0.9 },
|
||||
{ x: data.index, y: data.filtered, name: '濾波後輸出 (Output)', type: 'scatter', line: { color: isDark ? '#d7da7d' : '#6d702b', width: 2.4 }, opacity: 0.95 }
|
||||
], layout, { responsive: true });
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user