Comparar commits
8 commits
ec4fc0c711
...
e8da5e228e
Autor | SHA1 | Fecha | |
---|---|---|---|
|
e8da5e228e | ||
|
458cc6bb37 | ||
|
a25ba87f8b | ||
|
17e172927f | ||
|
cc0e98f94a | ||
|
df50407904 | ||
|
0a81be7765 | ||
|
7a1b040f1a |
S'han modificat 6 arxius amb 40 adicions i 168 eliminacions
|
@ -6,7 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover" class="bg-white dark:bg-gray-900">
|
<body data-sveltekit-preload-data="hover" class="bg-neutral-100 dark:bg-neutral-800 text-black dark:text-white">
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
export let data: {date: string, avgTemp: number}[] = [
|
export let data: {date: string, avgTemp: number}[] = [
|
||||||
{date: "2023-01-01", avgTemp: 22},
|
{date: "2023-01-01", avgTemp: 22},
|
||||||
|
@ -26,156 +27,23 @@ export let data: {date: string, avgTemp: number}[] = [
|
||||||
{date: "2023-01-22", avgTemp: 0},
|
{date: "2023-01-22", avgTemp: 0},
|
||||||
{date: "2023-01-23", avgTemp: -2},
|
{date: "2023-01-23", avgTemp: -2},
|
||||||
];
|
];
|
||||||
let vis;
|
|
||||||
|
|
||||||
let chart = LineChart(data, { x: d.date, y: d.avgTemp, yLabel: 'Daily average temperature', width, height: 500, color: 'steelblue' })
|
let vis: Element;
|
||||||
|
|
||||||
// Copyright 2021 Observable, Inc.
|
onMount(() => {
|
||||||
// Released under the ISC license.
|
const xScale = d3.scaleBand().rangeRound([0, 500]).padding(0.1);
|
||||||
// https://observablehq.com/@d3/line-with-tooltip
|
const yScale = d3.scaleLinear().domain([-10, 40]).range([200, 0]);
|
||||||
function LineChart(data, {
|
const container = d3.select(vis);
|
||||||
x = ([x]) => x, // given d in data, returns the (temporal) x-value
|
container
|
||||||
y = ([, y]) => y, // given d in data, returns the (quantitative) y-value
|
.selectAll('rect')
|
||||||
title, // given d in data, returns the title text
|
.data(data)
|
||||||
defined, // for gaps in data
|
.enter()
|
||||||
curve = d3.curveLinear, // method of interpolation between points
|
.append('rect')
|
||||||
marginTop = 20, // top margin, in pixels
|
.attr('width', xScale.bandwidth())
|
||||||
marginRight = 30, // right margin, in pixels
|
.attr('heigth', (data) => yScale(data.avgTemp))
|
||||||
marginBottom = 30, // bottom margin, in pixels
|
.attr('fill', 'black')
|
||||||
marginLeft = 40, // left margin, in pixels
|
})
|
||||||
width = 640, // outer width, in pixels
|
|
||||||
height = 400, // outer height, in pixels
|
|
||||||
xType = d3.scaleUtc, // type of x-scale
|
|
||||||
xDomain, // [xmin, xmax]
|
|
||||||
xRange = [marginLeft, width - marginRight], // [left, right]
|
|
||||||
yType = d3.scaleLinear, // type of y-scale
|
|
||||||
yDomain, // [ymin, ymax]
|
|
||||||
yRange = [height - marginBottom, marginTop], // [bottom, top]
|
|
||||||
color = "currentColor", // stroke color of line
|
|
||||||
strokeWidth = 1.5, // stroke width of line, in pixels
|
|
||||||
strokeLinejoin = "round", // stroke line join of line
|
|
||||||
strokeLinecap = "round", // stroke line cap of line
|
|
||||||
yFormat, // a format specifier string for the y-axis
|
|
||||||
yLabel, // a label for the y-axis
|
|
||||||
} = {}) {
|
|
||||||
// Compute values.
|
|
||||||
const X = d3.map(data, x);
|
|
||||||
const Y = d3.map(data, y);
|
|
||||||
const O = d3.map(data, d => d);
|
|
||||||
const I = d3.map(data, (_, i) => i);
|
|
||||||
|
|
||||||
// Compute which data points are considered defined.
|
|
||||||
if (defined === undefined) defined = (d, i) => !isNaN(X[i]) && !isNaN(Y[i]);
|
|
||||||
const D = d3.map(data, defined);
|
|
||||||
|
|
||||||
// Compute default domains.
|
|
||||||
if (xDomain === undefined) xDomain = d3.extent(X);
|
|
||||||
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
|
|
||||||
|
|
||||||
// Construct scales and axes.
|
|
||||||
const xScale = xType(xDomain, xRange);
|
|
||||||
const yScale = yType(yDomain, yRange);
|
|
||||||
const xAxis = d3.axisBottom(xScale).ticks(width / 80).tickSizeOuter(0);
|
|
||||||
const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);
|
|
||||||
|
|
||||||
// Compute titles.
|
|
||||||
if (title === undefined) {
|
|
||||||
const formatDate = xScale.tickFormat(null, "%b %-d, %Y");
|
|
||||||
const formatValue = yScale.tickFormat(100, yFormat);
|
|
||||||
title = i => `${formatDate(X[i])}\n${formatValue(Y[i])}`;
|
|
||||||
} else {
|
|
||||||
const O = d3.map(data, d => d);
|
|
||||||
const T = title;
|
|
||||||
title = i => T(O[i], i, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct a line generator.
|
|
||||||
const line = d3.line()
|
|
||||||
.defined(i => D[i])
|
|
||||||
.curve(curve)
|
|
||||||
.x(i => xScale(X[i]))
|
|
||||||
.y(i => yScale(Y[i]));
|
|
||||||
|
|
||||||
const svg = d3.create("svg")
|
|
||||||
.attr("width", width)
|
|
||||||
.attr("height", height)
|
|
||||||
.attr("viewBox", [0, 0, width, height])
|
|
||||||
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
|
|
||||||
.attr("font-family", "sans-serif")
|
|
||||||
.attr("font-size", 10)
|
|
||||||
.style("-webkit-tap-highlight-color", "transparent")
|
|
||||||
.style("overflow", "visible")
|
|
||||||
.on("pointerenter pointermove", pointermoved)
|
|
||||||
.on("pointerleave", pointerleft)
|
|
||||||
.on("touchstart", event => event.preventDefault());
|
|
||||||
|
|
||||||
svg.append("g")
|
|
||||||
.attr("transform", `translate(0,${height - marginBottom})`)
|
|
||||||
.call(xAxis);
|
|
||||||
|
|
||||||
svg.append("g")
|
|
||||||
.attr("transform", `translate(${marginLeft},0)`)
|
|
||||||
.call(yAxis)
|
|
||||||
.call(g => g.select(".domain").remove())
|
|
||||||
.call(g => g.selectAll(".tick line").clone()
|
|
||||||
.attr("x2", width - marginLeft - marginRight)
|
|
||||||
.attr("stroke-opacity", 0.1))
|
|
||||||
.call(g => g.append("text")
|
|
||||||
.attr("x", -marginLeft)
|
|
||||||
.attr("y", 10)
|
|
||||||
.attr("fill", "currentColor")
|
|
||||||
.attr("text-anchor", "start")
|
|
||||||
.text(yLabel));
|
|
||||||
|
|
||||||
svg.append("path")
|
|
||||||
.attr("fill", "none")
|
|
||||||
.attr("stroke", color)
|
|
||||||
.attr("stroke-width", strokeWidth)
|
|
||||||
.attr("stroke-linejoin", strokeLinejoin)
|
|
||||||
.attr("stroke-linecap", strokeLinecap)
|
|
||||||
.attr("d", line(I));
|
|
||||||
|
|
||||||
const tooltip = svg.append("g")
|
|
||||||
.style("pointer-events", "none");
|
|
||||||
|
|
||||||
function pointermoved(event) {
|
|
||||||
const i = d3.bisectCenter(X, xScale.invert(d3.pointer(event)[0]));
|
|
||||||
tooltip.style("display", null);
|
|
||||||
tooltip.attr("transform", `translate(${xScale(X[i])},${yScale(Y[i])})`);
|
|
||||||
|
|
||||||
const path = tooltip.selectAll("path")
|
|
||||||
.data([,])
|
|
||||||
.join("path")
|
|
||||||
.attr("fill", "white")
|
|
||||||
.attr("stroke", "black");
|
|
||||||
|
|
||||||
const text = tooltip.selectAll("text")
|
|
||||||
.data([,])
|
|
||||||
.join("text")
|
|
||||||
.call(text => text
|
|
||||||
.selectAll("tspan")
|
|
||||||
.data(`${title(i)}`.split(/\n/))
|
|
||||||
.join("tspan")
|
|
||||||
.attr("x", 0)
|
|
||||||
.attr("y", (_, i) => `${i * 1.1}em`)
|
|
||||||
.attr("font-weight", (_, i) => i ? null : "bold")
|
|
||||||
.text(d => d));
|
|
||||||
|
|
||||||
const {x, y, width: w, height: h} = text.node().getBBox();
|
|
||||||
text.attr("transform", `translate(${-w / 2},${15 - y})`);
|
|
||||||
path.attr("d", `M${-w / 2 - 10},5H-5l5,-5l5,5H${w / 2 + 10}v${h + 20}h-${w + 20}z`);
|
|
||||||
svg.property("value", O[i]).dispatch("input", {bubbles: true});
|
|
||||||
}
|
|
||||||
|
|
||||||
function pointerleft() {
|
|
||||||
tooltip.style("display", "none");
|
|
||||||
svg.node().value = null;
|
|
||||||
svg.dispatch("input", {bubbles: true});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.assign(svg.node(), {value: null});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<main>
|
<main>
|
||||||
<div bind:this={vis}><svg bind:this={chart}></svg></div>
|
<svg bind:this={vis}></svg>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import highcharts from "./highcharts";
|
import highcharts from "../components/highcharts";
|
||||||
export let ubicacio: string = '';
|
export let ubicacio: string = '';
|
||||||
export let series: Array<any> = [];
|
export let series: Array<any> = [];
|
||||||
|
|
||||||
|
|
|
@ -3,21 +3,23 @@
|
||||||
import { Navbar, NavBrand, NavLi, NavUl, NavHamburger, DarkMode } from 'flowbite-svelte';
|
import { Navbar, NavBrand, NavLi, NavUl, NavHamburger, DarkMode } from 'flowbite-svelte';
|
||||||
export let navobjs: NavbarObject[] = [new NavbarObject('#', 'No nav elements provided')];
|
export let navobjs: NavbarObject[] = [new NavbarObject('#', 'No nav elements provided')];
|
||||||
export let pageTitle: string = "Default Title";
|
export let pageTitle: string = "Default Title";
|
||||||
export let togleDarkModeButton: boolean = true;
|
export let toggleDarkModeButton: boolean = true;
|
||||||
</script>
|
</script>
|
||||||
<Navbar let:hidden let:toggle color="form">
|
<Navbar let:hidden let:toggle color="form" navDivClass="mx-auto flex flex-wrap justify-around items-center" navClass="px-4 md:px-2 py-2.5 w-full bg-zinc-200 dark:bg-zinc-900">
|
||||||
<NavBrand href="/">
|
<NavBrand href="/">
|
||||||
<span class="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
|
<span class="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
|
||||||
{ pageTitle.toUpperCase() }
|
{ pageTitle.toUpperCase() }
|
||||||
</span>
|
</span>
|
||||||
</NavBrand>
|
</NavBrand>
|
||||||
<NavHamburger on:click={toggle} />
|
<NavHamburger on:click={toggle} />
|
||||||
|
<div class="flex">
|
||||||
<NavUl {hidden}>
|
<NavUl {hidden}>
|
||||||
{#each navobjs as navElem}
|
{#each navobjs as navElem}
|
||||||
<NavLi href="{ navElem.link }">{ navElem.text }</NavLi>
|
<NavLi href="{ navElem.link }">{ navElem.text }</NavLi>
|
||||||
{/each}
|
{/each}
|
||||||
</NavUl>
|
</NavUl>
|
||||||
{#if togleDarkModeButton}
|
{#if toggleDarkModeButton}
|
||||||
<DarkMode class='p-0' />
|
<DarkMode class='p-0' />
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
import Navbar from "../lib/navbar.svelte";
|
import Navbar from "../lib/navbar.svelte";
|
||||||
import './styles.css';
|
import './styles.css';
|
||||||
|
|
||||||
|
let pageTitle: string = "pswsm meteo"
|
||||||
let navbarElements: NavbarObject[] = [new NavbarObject('/', 'Home'), new NavbarObject('/abtme', 'Sobre mi'), new NavbarObject('/temps', 'Temps'), new NavbarObject('/xema', 'Estacions'), new NavbarObject('/openmeteo', 'Dades Open Meteo')]
|
let navbarElements: NavbarObject[] = [new NavbarObject('/', 'Home'), new NavbarObject('/abtme', 'Sobre mi'), new NavbarObject('/temps', 'Temps'), new NavbarObject('/xema', 'Estacions'), new NavbarObject('/openmeteo', 'Dades Open Meteo')]
|
||||||
</script>
|
</script>
|
||||||
<Navbar navobjs={navbarElements} pageTitle="pswsm meteo" />
|
<Navbar navobjs={navbarElements} pageTitle={pageTitle} />
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { enhance } from "$app/forms";
|
import { enhance } from "$app/forms";
|
||||||
import { D3LinePlot } from "$lib";
|
import { D3LinePlot } from "$lib";
|
||||||
import Graph from "../../lib/graph.svelte";
|
// import Graph from "../../lib/graph.svelte";
|
||||||
|
|
||||||
let display: string = 'none';
|
let display: string = 'none';
|
||||||
let loading: boolean = false;
|
let loading: boolean = false;
|
||||||
|
@ -23,9 +23,10 @@
|
||||||
<h2>Ubicació actual: { data.ubicacio }</h2>
|
<h2>Ubicació actual: { data.ubicacio }</h2>
|
||||||
<button type="button" on:click={toggleDisplay}>Canviar ubicació</button>
|
<button type="button" on:click={toggleDisplay}>Canviar ubicació</button>
|
||||||
<pre>{ JSON.stringify(data) }</pre>
|
<pre>{ JSON.stringify(data) }</pre>
|
||||||
<Graph ubicacio={data.ubicacio} series={data.temps} />
|
|
||||||
<hr>
|
<hr>
|
||||||
<D3LinePlot />
|
<D3LinePlot />
|
||||||
|
<span>some text</span>
|
||||||
|
<hr>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<p>Dades provinents de:</p>
|
<p>Dades provinents de:</p>
|
||||||
|
|
Loading…
Referencia en una nova incidència