feat: change curve function in computer chart

This commit is contained in:
trafficlunar 2025-12-31 00:02:30 +00:00
parent 377e1c1db7
commit 5b1a43a814

View file

@ -1,8 +1,16 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import { Area, Axis, Chart, Highlight, LinearGradient, Svg, Tooltip } from "layerchart"; import {
Area,
Axis,
Chart,
Highlight,
LinearGradient,
Svg,
Tooltip,
} from "layerchart";
import { scaleTime } from "d3-scale"; import { scaleTime } from "d3-scale";
import { curveBasis } from "d3-shape"; import { curveCatmullRom } from "d3-shape";
import { computerData } from "../states.svelte"; import { computerData } from "../states.svelte";
type GraphData = { type GraphData = {
@ -70,14 +78,19 @@
ram: point.ram / 100, ram: point.ram / 100,
})); }));
const totalClicks = chartData.reduce((sum, point) => sum + point.clicks, 0); const totalClicks = chartData.reduce(
(sum, point) => sum + point.clicks,
0
);
const totalKeys = chartData.reduce((sum, point) => sum + point.keys, 0); const totalKeys = chartData.reduce((sum, point) => sum + point.keys, 0);
clicksPerMinute = totalClicks / 60; // 60 minutes (max graph data) clicksPerMinute = totalClicks / 60; // 60 minutes (max graph data)
keysPerMinute = totalKeys / 60; keysPerMinute = totalKeys / 60;
// Uptime // Uptime
const diff = data.online ? Math.floor((Date.now() - data.uptimeStart * 1000) / 1000) : 0; const diff = data.online
? Math.floor((Date.now() - data.uptimeStart * 1000) / 1000)
: 0;
const allTime = diff + data.totals.uptime; const allTime = diff + data.totals.uptime;
allTimeUptime = formatTime(allTime); allTimeUptime = formatTime(allTime);
@ -98,10 +111,16 @@
}); });
</script> </script>
<div class="relative transition-all duration-300 delay-200 starting:opacity-0 starting:translate-y-4"> <div
class="relative transition-all duration-300 delay-200 starting:opacity-0 starting:translate-y-4"
>
<div class="flex justify-center items-center absolute -top-2 right-2 z-0"> <div class="flex justify-center items-center absolute -top-2 right-2 z-0">
<div class="w-4 h-4 rounded-full {online ? 'bg-green' : 'bg-red'}"></div> <div class="w-4 h-4 rounded-full {online ? 'bg-green' : 'bg-red'}"></div>
<div class="w-4 h-4 rounded-full absolute animate-duration-2s animate-delay-2s {online ? 'bg-green animate-ping' : 'bg-red'}"></div> <div
class="w-4 h-4 rounded-full absolute animate-duration-2s animate-delay-2s {online
? 'bg-green animate-ping'
: 'bg-red'}"
></div>
</div> </div>
<section class="mb-0!"> <section class="mb-0!">
@ -116,7 +135,10 @@
<span class="text-xs font-bold text-peach">{currentCPU}%</span> <span class="text-xs font-bold text-peach">{currentCPU}%</span>
</div> </div>
<div class="h-1.5 w-full rounded-full overflow-hidden bg-surface0/50"> <div class="h-1.5 w-full rounded-full overflow-hidden bg-surface0/50">
<div class="h-full rounded-full bg-peach transition-all duration-300" style="width: {Math.min(100, currentCPU)}%;"></div> <div
class="h-full rounded-full bg-peach transition-all duration-300"
style="width: {Math.min(100, currentCPU)}%;"
></div>
</div> </div>
</div> </div>
@ -126,7 +148,10 @@
<span class="text-xs font-bold text-yellow">{currentRAM}%</span> <span class="text-xs font-bold text-yellow">{currentRAM}%</span>
</div> </div>
<div class="h-1.5 w-full rounded-full overflow-hidden bg-surface0/50"> <div class="h-1.5 w-full rounded-full overflow-hidden bg-surface0/50">
<div class="h-full rounded-full bg-yellow transition-all duration-300" style="width: {Math.min(100, currentRAM)}%;"></div> <div
class="h-full rounded-full bg-yellow transition-all duration-300"
style="width: {Math.min(100, currentRAM)}%;"
></div>
</div> </div>
</div> </div>
</div> </div>
@ -134,19 +159,32 @@
<!-- Stats Grid --> <!-- Stats Grid -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4"> <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<!-- Uptime Card --> <!-- Uptime Card -->
<div class="bg-surface0/30 rounded-lg p-3 border border-surface0 shadow-sm"> <div
class="bg-surface0/30 rounded-lg p-3 border border-surface0 shadow-sm"
>
<div class="flex mb-1"> <div class="flex mb-1">
<div class="relative"> <div class="relative">
<svg width="20" height="20" viewBox="0 0 20 20" fill-rule="evenodd" class="absolute -bottom-0.5 fill-overlay1"> <svg
<path d="M10 5.5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11M2.5 11a7.5 7.5 0 1 1 15 0 7.5 7.5 0 0 1-15 0" /> width="20"
height="20"
viewBox="0 0 20 20"
fill-rule="evenodd"
class="absolute -bottom-0.5 fill-overlay1"
>
<path
d="M10 5.5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11M2.5 11a7.5 7.5 0 1 1 15 0 7.5 7.5 0 0 1-15 0"
/>
<path <path
d="M2.793 3.793a1 1 0 0 1 1.414 0l1.5 1.5c.91.943-.471 2.324-1.414 1.414l-1.5-1.5a1 1 0 0 1 0-1.414m11.5 2.914a1 1 0 0 0 1.414 0l1.5-1.5c.91-.943-.471-2.324-1.414-1.414l-1.5 1.5a1 1 0 0 0 0 1.414M9 4V2h2v2z" d="M2.793 3.793a1 1 0 0 1 1.414 0l1.5 1.5c.91.943-.471 2.324-1.414 1.414l-1.5-1.5a1 1 0 0 1 0-1.414m11.5 2.914a1 1 0 0 0 1.414 0l1.5-1.5c.91-.943-.471-2.324-1.414-1.414l-1.5 1.5a1 1 0 0 0 0 1.414M9 4V2h2v2z"
/> />
<path d="M7.5 2a1 1 0 0 1 1-1h3a1 1 0 1 1 0 2h-3a1 1 0 0 1-1-1" /> <path
d="M7.5 2a1 1 0 0 1 1-1h3a1 1 0 1 1 0 2h-3a1 1 0 0 1-1-1"
/>
<!-- Hand --> <!-- Hand -->
<path <path
d="m 13.28,8.375 c 0.345578,0.4310223 0.276171,1.0606079 -0.155,1.406 l -2.5,2 C 9.583667,12.614333 8.333667,11.052333 9.375,10.219 l 2.5,-2 c 0.431286,-0.3453463 1.060907,-0.2754879 1.406,0.156" d="m 13.28,8.375 c 0.345578,0.4310223 0.276171,1.0606079 -0.155,1.406 l -2.5,2 C 9.583667,12.614333 8.333667,11.052333 9.375,10.219 l 2.5,-2 c 0.431286,-0.3453463 1.060907,-0.2754879 1.406,0.156"
style="transform: rotate({stopwatchDeg - 52}deg); transform-origin: 10px 11px; transition: transform 1s linear;" style="transform: rotate({stopwatchDeg -
52}deg); transform-origin: 10px 11px; transition: transform 1s linear;"
/> />
</svg> </svg>
</div> </div>
@ -157,22 +195,32 @@
</div> </div>
<!-- Activity Card --> <!-- Activity Card -->
<div class="bg-surface0/30 rounded-lg p-3 border border-surface0 shadow-sm"> <div
<div class="font-black text-xs text-overlay1 mb-2">ACTIVITY / MIN</div> class="bg-surface0/30 rounded-lg p-3 border border-surface0 shadow-sm"
>
<div class="font-black text-xs text-overlay1 mb-2">
ACTIVITY / MIN
</div>
<div class="space-y-1.5"> <div class="space-y-1.5">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-xs text-overlay1">Clicks</span> <span class="text-xs text-overlay1">Clicks</span>
<span class="font-bold text-teal">{clicksPerMinute.toFixed(1)}</span> <span class="font-bold text-teal"
>{clicksPerMinute.toFixed(1)}</span
>
</div> </div>
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-xs text-overlay1">Keys</span> <span class="text-xs text-overlay1">Keys</span>
<span class="font-bold text-green">{keysPerMinute.toFixed(1)}</span> <span class="font-bold text-green"
>{keysPerMinute.toFixed(1)}</span
>
</div> </div>
</div> </div>
</div> </div>
<!-- All Time Card --> <!-- All Time Card -->
<div class="bg-surface0/30 rounded-lg p-3 border border-surface0 shadow-sm"> <div
class="bg-surface0/30 rounded-lg p-3 border border-surface0 shadow-sm"
>
<div class="font-black text-xs text-overlay1 mb-2">ALL TIME</div> <div class="font-black text-xs text-overlay1 mb-2">ALL TIME</div>
<div class="space-y-1.5"> <div class="space-y-1.5">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
@ -188,7 +236,9 @@
</div> </div>
</div> </div>
<div class="relative h-96 rounded-md bg-mantle border border-surface0 p-2 shadow-sm"> <div
class="relative h-96 rounded-md bg-mantle border border-surface0 p-2 shadow-sm"
>
<Chart <Chart
data={chartData} data={chartData}
x="timestamp" x="timestamp"
@ -204,47 +254,85 @@
placement="left" placement="left"
grid grid
rule rule
classes={{ tickLabel: "fill-overlay1 font-medium stroke-none", rule: "stroke-surface0/50", tick: "stroke-surface0/50" }} classes={{
tickLabel: "fill-overlay1 font-medium stroke-none",
rule: "stroke-surface0/50",
tick: "stroke-surface0/50",
}}
format="percentRound" format="percentRound"
/> />
<Axis <Axis
placement="bottom" placement="bottom"
rule rule
classes={{ tickLabel: "fill-overlay1 font-medium stroke-none", rule: "stroke-surface0/50", tick: "stroke-surface0/50" }} classes={{
tickLabel: "fill-overlay1 font-medium stroke-none",
rule: "stroke-surface0/50",
tick: "stroke-surface0/50",
}}
/> />
<!-- RAM --> <!-- RAM -->
<LinearGradient class="from-peach/50 to-peach/1" vertical> <LinearGradient class="from-peach/50 to-peach/1" vertical>
{#snippet children({ gradient })} {#snippet children({ gradient })}
<Area y1={(d) => d.ram} fill={gradient} line={{ class: "stroke-2 stroke-peach" }} curve={curveBasis} /> <Area
y1={(d) => d.ram}
fill={gradient}
line={{ class: "stroke-2 stroke-peach" }}
curve={curveCatmullRom}
/>
{/snippet} {/snippet}
</LinearGradient> </LinearGradient>
<!-- CPU --> <!-- CPU -->
<LinearGradient class="from-yellow/50 to-yellow/1" vertical> <LinearGradient class="from-yellow/50 to-yellow/1" vertical>
{#snippet children({ gradient })} {#snippet children({ gradient })}
<Area y1={(d) => d.cpu} fill={gradient} line={{ class: "stroke-2 stroke-yellow" }} curve={curveBasis} /> <Area
y1={(d) => d.cpu}
fill={gradient}
line={{ class: "stroke-2 stroke-yellow" }}
curve={curveCatmullRom}
/>
{/snippet} {/snippet}
</LinearGradient> </LinearGradient>
<Highlight lines={{ class: "stroke-peach [stroke-dasharray:unset]" }} /> <Highlight
lines={{ class: "stroke-peach [stroke-dasharray:unset]" }}
/>
<Highlight y={(d) => d.ram} points={{ class: "fill-peach" }} /> <Highlight y={(d) => d.ram} points={{ class: "fill-peach" }} />
<Highlight y={(d) => d.cpu} points={{ class: "fill-yellow" }} /> <Highlight y={(d) => d.cpu} points={{ class: "fill-yellow" }} />
</Svg> </Svg>
<Tooltip.Root class="border border-peach bg-peach/10! text-white/85 backdrop-blur-lg!"> <Tooltip.Root
class="border border-peach bg-peach/10! text-white/85 backdrop-blur-lg!"
>
{#snippet children({ data })} {#snippet children({ data })}
<Tooltip.Header value={data.timestamp} format="time" classes={{ root: "border-peach" }} /> <Tooltip.Header
value={data.timestamp}
format="time"
classes={{ root: "border-peach" }}
/>
<Tooltip.List> <Tooltip.List>
<Tooltip.Item label="RAM (%)" value={data.ram} format="percentRound" classes={{ value: "font-mono font-black text-peach" }} /> <Tooltip.Item
<Tooltip.Item label="CPU (%)" value={data.cpu} format="percentRound" classes={{ value: "font-mono font-black text-yellow" }} /> label="RAM (%)"
value={data.ram}
format="percentRound"
classes={{ value: "font-mono font-black text-peach" }}
/>
<Tooltip.Item
label="CPU (%)"
value={data.cpu}
format="percentRound"
classes={{ value: "font-mono font-black text-yellow" }}
/>
</Tooltip.List> </Tooltip.List>
{/snippet} {/snippet}
</Tooltip.Root> </Tooltip.Root>
</Chart> </Chart>
</div> </div>
<div class="relative h-48 rounded-md bg-mantle border border-surface0 p-2 mt-2 shadow-sm"> <div
class="relative h-48 rounded-md bg-mantle border border-surface0 p-2 mt-2 shadow-sm"
>
<Chart <Chart
data={chartData} data={chartData}
x="timestamp" x="timestamp"
@ -259,40 +347,77 @@
<Axis <Axis
placement="left" placement="left"
rule rule
classes={{ tickLabel: "fill-overlay1 font-medium stroke-none", rule: "stroke-surface0/50", tick: "stroke-surface0/50" }} classes={{
tickLabel: "fill-overlay1 font-medium stroke-none",
rule: "stroke-surface0/50",
tick: "stroke-surface0/50",
}}
/> />
<Axis <Axis
placement="bottom" placement="bottom"
grid grid
rule rule
classes={{ tickLabel: "fill-overlay1 font-medium stroke-none", rule: "stroke-surface0/50", tick: "stroke-surface0/50" }} classes={{
tickLabel: "fill-overlay1 font-medium stroke-none",
rule: "stroke-surface0/50",
tick: "stroke-surface0/50",
}}
/> />
<!-- Keys --> <!-- Keys -->
<LinearGradient class="from-green/50 to-green/1" vertical> <LinearGradient class="from-green/50 to-green/1" vertical>
{#snippet children({ gradient })} {#snippet children({ gradient })}
<Area y1={(d) => d.keys} fill={gradient} line={{ class: "stroke-2 stroke-green" }} curve={curveBasis} /> <Area
y1={(d) => d.keys}
fill={gradient}
line={{ class: "stroke-2 stroke-green" }}
curve={curveCatmullRom}
/>
{/snippet} {/snippet}
</LinearGradient> </LinearGradient>
<!-- Clicks --> <!-- Clicks -->
<LinearGradient class="from-teal/50 to-teal/1" vertical> <LinearGradient class="from-teal/50 to-teal/1" vertical>
{#snippet children({ gradient })} {#snippet children({ gradient })}
<Area y1={(d) => d.clicks} fill={gradient} line={{ class: "stroke-2 stroke-teal" }} curve={curveBasis} /> <Area
y1={(d) => d.clicks}
fill={gradient}
line={{ class: "stroke-2 stroke-teal" }}
curve={curveCatmullRom}
/>
{/snippet} {/snippet}
</LinearGradient> </LinearGradient>
<Highlight lines={{ class: "stroke-peach [stroke-dasharray:unset]" }} /> <Highlight
lines={{ class: "stroke-peach [stroke-dasharray:unset]" }}
/>
<Highlight y={(d) => d.keys} points={{ class: "fill-green" }} /> <Highlight y={(d) => d.keys} points={{ class: "fill-green" }} />
<Highlight y={(d) => d.clicks} points={{ class: "fill-teal" }} /> <Highlight y={(d) => d.clicks} points={{ class: "fill-teal" }} />
</Svg> </Svg>
<Tooltip.Root classes={{ container: "border border-peach bg-peach/10! text-white/85 backdrop-blur-lg!" }}> <Tooltip.Root
classes={{
container:
"border border-peach bg-peach/10! text-white/85 backdrop-blur-lg!",
}}
>
{#snippet children({ data })} {#snippet children({ data })}
<Tooltip.Header value={data.timestamp} format="time" classes={{ root: "border-peach" }} /> <Tooltip.Header
value={data.timestamp}
format="time"
classes={{ root: "border-peach" }}
/>
<Tooltip.List> <Tooltip.List>
<Tooltip.Item label="Keys" value={data.keys} classes={{ value: "font-mono font-black text-green" }} /> <Tooltip.Item
<Tooltip.Item label="Clicks" value={data.clicks} classes={{ value: "font-mono font-black text-teal" }} /> label="Keys"
value={data.keys}
classes={{ value: "font-mono font-black text-green" }}
/>
<Tooltip.Item
label="Clicks"
value={data.clicks}
classes={{ value: "font-mono font-black text-teal" }}
/>
</Tooltip.List> </Tooltip.List>
{/snippet} {/snippet}
</Tooltip.Root> </Tooltip.Root>