Inline mjs

This commit is contained in:
b12f 2024-08-24 21:55:39 +02:00
parent 5060412835
commit 140c3f9d7c
Signed by: b12f
GPG key ID: 729956E1124F8F26

View file

@ -7,158 +7,315 @@
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1.0" /> <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1.0" />
<style> <style>
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
html { html {
--accent: #ed1c24; --accent: #ed1c24;
--foreground: #000; --foreground: #000;
--background: #fff; --background: #fff;
--background-alt: #f5f5f5; --background-alt: #f5f5f5;
font-family: 'Open Sans', Arial, sans-serif; font-family: 'Open Sans', Arial, sans-serif;
font-weight: 800; font-weight: 800;
background: var(--background); background: var(--background);
color: var(--foreground); color: var(--foreground);
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
box-sizing: border-box; box-sizing: border-box;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
margin: 0; margin: 0;
font-size: 1vw; font-size: 1vw;
} }
body { body {
margin: 0; margin: 0;
} }
.video { .video {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
object-fit: cover; object-fit: cover;
position: fixed; position: fixed;
z-index: -1; z-index: -1;
top: 0%; top: 0%;
left: 0; left: 0;
} }
@keyframes bling { @keyframes bling {
0% { 0% {
text-shadow: 0px 0px 0.0rem gold; text-shadow: 0px 0px 0.0rem gold;
} }
30% { 30% {
text-shadow: 0px 0px 0.0rem gold; text-shadow: 0px 0px 0.0rem gold;
} }
50% { 50% {
text-shadow: 0px 0px 0.5rem gold; text-shadow: 0px 0px 0.5rem gold;
} }
70% { 70% {
text-shadow: 0px 0px 0.0rem gold; text-shadow: 0px 0px 0.0rem gold;
} }
100% { 100% {
text-shadow: 0px 0px 0.0rem gold; text-shadow: 0px 0px 0.0rem gold;
} }
} }
@keyframes scale { @keyframes scale {
0% { 0% {
transform: scale(1); transform: scale(1);
} }
50% { 50% {
transform: scale(2); transform: scale(2);
} }
100% { 100% {
transform: scale(1); transform: scale(1);
} }
} }
#ad { #ad {
position: fixed; position: fixed;
z-index: 1; z-index: 1;
bottom: 0; bottom: 0;
right: 0; right: 0;
left: 0; left: 0;
padding: 0 16px; padding: 0 16px;
color: gold; color: gold;
font-size: 5vh; font-size: 5vh;
text-shadow: 0px 0px 0.5rem gold; text-shadow: 0px 0px 0.5rem gold;
animation-name: bling; animation-name: bling;
animation-duration: 1s; animation-duration: 1s;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: infinite; animation-iteration-count: infinite;
white-space: nowrap; white-space: nowrap;
} }
@keyframes rotate { @keyframes rotate {
from { from {
transform: rotateY(0deg); transform: rotateY(0deg);
} }
to { to {
transform: rotateY(360deg); transform: rotateY(360deg);
} }
} }
@keyframes depth { @keyframes depth {
0% { text-shadow: 0 0 #5b5015; } 0% { text-shadow: 0 0 #5b5015; }
25% { text-shadow: 4px 0 #5b5015, 8px 0 #5b5015, 12px 0 #5b5015, 16px 0 #5b5015, 20px 0 #5b5015; } 25% { text-shadow: 4px 0 #5b5015, 8px 0 #5b5015, 12px 0 #5b5015, 16px 0 #5b5015, 20px 0 #5b5015; }
50% { text-shadow: 0 0 #5b5015; } 50% { text-shadow: 0 0 #5b5015; }
75% { text-shadow: -4px 0 #5b5015, -8px 0 #5b5015, -12px 0 #5b5015, -16px 0 #5b5015, -20px 0 #5b5015; } 75% { text-shadow: -4px 0 #5b5015, -8px 0 #5b5015, -12px 0 #5b5015, -16px 0 #5b5015, -20px 0 #5b5015; }
100% { text-shadow: 0 0 #5b5015; } 100% { text-shadow: 0 0 #5b5015; }
} }
.money { .money {
position: fixed; position: fixed;
top: 5vh; top: 5vh;
left: 5vw; left: 5vw;
z-index: 1; z-index: 1;
color: gold; color: gold;
font-size: 20vw; font-size: 20vw;
animation-name: rotate, depth; animation-name: rotate, depth;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: infinite; animation-iteration-count: infinite;
animation-duration: 5s; animation-duration: 5s;
} }
</style> </style>
<script <script
defer defer
type="module" type="module"
src="/scripts/money.mjs" >
></script> import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
<body>
<video // Copyright 2021 Observable, Inc.
class="video" // Released under the ISC license.
src="/assets/money-rains.mp4" // https://observablehq.com/@d3/candlestick-chart
autoplay="true" function CandlestickChart(data, {
loop="true" date = d => d.date, // given d in data, returns the (temporal) x-value
muted="true" open = d => d.open, // given d in data, returns a (quantitative) y-value
></video> close = d => d.close, // given d in data, returns a (quantitative) y-value
<div id="charts"></div> high = d => d.high, // given d in data, returns a (quantitative) y-value
<marquee low = d => d.low, // given d in data, returns a (quantitative) y-value
id="ad" title, // given d in data, returns the title text
scrolldelay="10" marginTop = 20, // top margin, in pixels
truespeed="true" marginRight = 30, // right margin, in pixels
behavior="scroll" marginBottom = 30, // bottom margin, in pixels
> marginLeft = 40, // left margin, in pixels
mezza width = 640, // outer width, in pixels
nineninenine // height = 400, // outer height, in pixels
here for YOUR business // xDomain, // array of x-values (defaults to every weekday)
we make that line go UP // xRange = [marginLeft, width - marginRight], // [left, right]
NEVER settle for less // xPadding = 0.2,
call NOW to talk to your personal finance savior xTicks, // array of x-values to label (defaults to every other Monday)
</marquee> yType = d3.scaleLinear, // type of y-scale
<div class="money">$</div> yDomain, // [ymin, ymax]
</body> yRange = [height - marginBottom, marginTop], // [bottom, top]
xFormat = "%b %-d", // a format specifier for the date on the x-axis
yFormat = "~f", // a format specifier for the value on the y-axis
yLabel, // a label for the y-axis
stroke = "gold", // stroke color for the daily rule
strokeLinecap = "round", // stroke line cap for the rules
colors = ["gold", "white", "black"] // [up, no change, down]
} = {}) {
// Compute values.
const X = d3.map(data, date);
const Yo = d3.map(data, open);
const Yc = d3.map(data, close);
const Yh = d3.map(data, high);
const Yl = d3.map(data, low);
const I = d3.range(X.length);
const weeks = (start, stop, stride) => d3.utcMonday.every(stride).range(start, +stop + 1);
const weekdays = (start, stop) => d3.utcDays(start, +stop + 1).filter(d => d.getUTCDay() !== 0 && d.getUTCDay() !== 6);
// Compute default domains and ticks.
if (xDomain === undefined) xDomain = weekdays(d3.min(X), d3.max(X));
if (yDomain === undefined) yDomain = [d3.min(Yl), d3.max(Yh)];
if (xTicks === undefined) xTicks = weeks(d3.min(xDomain), d3.max(xDomain), 2);
// Construct scales and axes.
// If you were to plot a stock using d3.scaleUtc, youd see distracting gaps
// every weekend. This chart therefore uses a d3.scaleBand whose domain is every
// weekday in the dataset. A few gaps remain for holiday weekdays, such as
// Christmas, but these are infrequent and allow the labeling of Mondays. As a
// band scale, we specify explicit tick values.
const xScale = d3.scaleBand(xDomain, xRange).padding(xPadding);
const yScale = yType(yDomain, yRange);
// Compute titles.
if (title === undefined) {
const formatDate = d3.utcFormat("%B %-d, %Y");
const formatValue = d3.format(".2f");
const formatChange = (f => (y0, y1) => f((y1 - y0) / y0))(d3.format("+.2%"));
title = i => `${formatDate(X[i])}
Open: ${formatValue(Yo[i])}
Close: ${formatValue(Yc[i])} (${formatChange(Yo[i], Yc[i])})
Low: ${formatValue(Yl[i])}
High: ${formatValue(Yh[i])}`;
} else if (title !== null) {
const T = d3.map(data, title);
title = i => T[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;");
const g = svg.append("g")
.attr("stroke", stroke)
.attr("stroke-linecap", strokeLinecap)
.selectAll("g")
.data(I)
.join("g")
.attr("transform", i => {
return `translate(${xScale.step() * i},0)`;
});
g.append("line")
.attr("y1", i => yScale(Yl[i]))
.attr("y2", i => yScale(Yh[i]));
g.append("line")
.attr("y1", i => yScale(Yo[i]))
.attr("y2", i => yScale(Yc[i]))
.attr("stroke-width", xScale.bandwidth())
.attr("stroke", i => colors[1 + Math.sign(Yo[i] - Yc[i])]);
if (title) g.append("title")
.text(title);
return svg.node();
}
const getNewDataPoint = (oldPoint) => ({
date: new Date(+oldPoint.date + (24 * 60 * 60 * 1000)),
open: oldPoint.close,
high: oldPoint.close + Math.random() * 5000 - 1000,
low: oldPoint.close - Math.random() * 2000 + 1000,
close: oldPoint.close + Math.random() * 2000 - Math.random() * 1000,
volume: Math.random() * 21899500 / 2 + 4229132,
});
const open = Math.random() * 200;
const initialPoint = {
date: new Date(),
open,
high: open + Math.random() * 400,
low: open - Math.random() * 200,
close: open + Math.random() * 2000 - Math.random() * 1000,
volume: 21899500,
};
const baseArray = new Array(200)
.fill(null)
.reduce((list, _, i) => [
...list,
getNewDataPoint(list[i]),
], [initialPoint]);
const createChart = () => {
const svgs = document.body.getElementsByTagName('svg');
for (let svg of svgs) {
document.body.removeChild(svg);
}
const chart = CandlestickChart(baseArray, {
date: d => d.date,
high: d => d.high,
low: d => d.low,
open: d => d.open,
close: d => d.close,
yLabel: "↑ Price ($)",
width: window.innerWidth,
height: window.innerHeight,
});
document.body.appendChild(chart);
}
createChart();
setInterval(() => {
baseArray.shift();
baseArray.push(getNewDataPoint(baseArray[baseArray.length - 1]));
createChart();
}, 500);
</script>
<body>
<video
class="video"
src="/assets/money-rains.mp4"
autoplay="true"
loop="true"
muted="true"
></video>
<div id="charts"></div>
<marquee
id="ad"
scrolldelay="10"
truespeed="true"
behavior="scroll"
>
mezza
nineninenine //
here for YOUR business //
we make that line go UP //
NEVER settle for less //
call NOW to talk to your personal finance savior
</marquee>
<div class="money">$</div>
</body>
</html> </html>