mirror of
https://github.com/RGBCube/Site
synced 2025-08-02 14:07:47 +00:00
Compare commits
28 commits
585e171415
...
e22ca700ee
Author | SHA1 | Date | |
---|---|---|---|
e22ca700ee | |||
ea4f34fc95 | |||
c1e7afe666 | |||
879843620a | |||
78415c1da1 | |||
9ec127293a | |||
490886b5f4 | |||
5c35c3b73d | |||
2ccbbf3a17 | |||
217f19841f | |||
0ffe6c39b1 | |||
23bdfef6cc | |||
e25d198cc9 | |||
adeca4879a | |||
b6c3592c2a | |||
70f94588c9 | |||
f889ca595b | |||
638cfff96b | |||
dcca24e7cc | |||
1bb9d9c541 | |||
3732704d74 | |||
5efa81ca2a | |||
6564bd61c7 | |||
ab09647f76 | |||
c96c59ecf5 | |||
e799cc1c45 | |||
a01188e892 | |||
99c21c01c7 |
11 changed files with 454 additions and 168 deletions
2
deno.lock
generated
2
deno.lock
generated
|
@ -666,7 +666,6 @@
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/hex.ts": "828718f24a780ff3ade8d0a8a5b57497cb31c257560ef12af99b6eb1a31e3bbd",
|
"https://deno.land/x/lume@v3.0.2/deps/hex.ts": "828718f24a780ff3ade8d0a8a5b57497cb31c257560ef12af99b6eb1a31e3bbd",
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/highlight.ts": "e8f830a1137ff7e8246ce21518452b8cbf8089db409458c6d9c31040c11d8428",
|
"https://deno.land/x/lume@v3.0.2/deps/highlight.ts": "e8f830a1137ff7e8246ce21518452b8cbf8089db409458c6d9c31040c11d8428",
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/http.ts": "6d9add7c6fe0c0381050aa773ae8590166ccc84c5115d2cde271320c315a110d",
|
"https://deno.land/x/lume@v3.0.2/deps/http.ts": "6d9add7c6fe0c0381050aa773ae8590166ccc84c5115d2cde271320c315a110d",
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/icons.ts": "4379e1443d982ab4f85237342d165ae54c981cdb7e06480c222d208999e21f15",
|
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/init.ts": "05d45af66ebdfe63e43540618f51ece8f99d98dc49de890f10eeb43abe9ed0f3",
|
"https://deno.land/x/lume@v3.0.2/deps/init.ts": "05d45af66ebdfe63e43540618f51ece8f99d98dc49de890f10eeb43abe9ed0f3",
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/jsonc.ts": "79f0eddc3c9e593310eb8e5918eb1506b1c7d7816e4ecb96894f634ecbe626ff",
|
"https://deno.land/x/lume@v3.0.2/deps/jsonc.ts": "79f0eddc3c9e593310eb8e5918eb1506b1c7d7816e4ecb96894f634ecbe626ff",
|
||||||
"https://deno.land/x/lume@v3.0.2/deps/lightningcss.ts": "5f5167c6eb306ef759f0043f8f33f2eaf63c69210aa1aa837505e990ee619c46",
|
"https://deno.land/x/lume@v3.0.2/deps/lightningcss.ts": "5f5167c6eb306ef759f0043f8f33f2eaf63c69210aa1aa837505e990ee619c46",
|
||||||
|
@ -692,7 +691,6 @@
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/code_highlight.ts": "ac6327e688e9e8fbd7798bdcc5f76b46d27db3e22ea3b74f545dc3296e8a1261",
|
"https://deno.land/x/lume@v3.0.2/plugins/code_highlight.ts": "ac6327e688e9e8fbd7798bdcc5f76b46d27db3e22ea3b74f545dc3296e8a1261",
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/extract_date.ts": "38af8e5960d66a74a72977eb19521da4353ab32d3941e97c1526aa3b91175a9e",
|
"https://deno.land/x/lume@v3.0.2/plugins/extract_date.ts": "38af8e5960d66a74a72977eb19521da4353ab32d3941e97c1526aa3b91175a9e",
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/feed.ts": "b07aed4cda270cfaacb26f9974dbb962f936dbfde4d770c53e478e4682c791e1",
|
"https://deno.land/x/lume@v3.0.2/plugins/feed.ts": "b07aed4cda270cfaacb26f9974dbb962f936dbfde4d770c53e478e4682c791e1",
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/icons.ts": "c69428254024d694eca34f9b5c4888aedf83d2d9b38f860533952c28cc814333",
|
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/inline.ts": "737d7de09d196476b55ecbe7ddb0e651ba2d5d39ca5a418cb15ff48e124907c1",
|
"https://deno.land/x/lume@v3.0.2/plugins/inline.ts": "737d7de09d196476b55ecbe7ddb0e651ba2d5d39ca5a418cb15ff48e124907c1",
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/json.ts": "5c49499e56b919ec848d4118ec97dd4fe0a323a6cc4c648dc45ab55297614c12",
|
"https://deno.land/x/lume@v3.0.2/plugins/json.ts": "5c49499e56b919ec848d4118ec97dd4fe0a323a6cc4c648dc45ab55297614c12",
|
||||||
"https://deno.land/x/lume@v3.0.2/plugins/lightningcss.ts": "6b5236cc78c1ae4af5b4a0037a0345797381f5043c667ae1ddeb4f67e445c7c4",
|
"https://deno.land/x/lume@v3.0.2/plugins/lightningcss.ts": "6b5236cc78c1ae4af5b4a0037a0345797381f5043c667ae1ddeb4f67e445c7c4",
|
||||||
|
|
76
site.ts
76
site.ts
|
@ -1,25 +1,25 @@
|
||||||
import lume from "lume/mod.ts";
|
import lume from "lume/mod.ts";
|
||||||
import extract_date from "lume/plugins/extract_date.ts";
|
import extractDate from "lume/plugins/extract_date.ts";
|
||||||
import code_highlight from "lume/plugins/code_highlight.ts";
|
import codeHighlight from "lume/plugins/code_highlight.ts";
|
||||||
import redirects from "lume/plugins/redirects.ts";
|
import redirects from "lume/plugins/redirects.ts";
|
||||||
import tailwindcss from "lume/plugins/tailwindcss.ts";
|
import tailwindcss from "lume/plugins/tailwindcss.ts";
|
||||||
import lightningcss from "lume/plugins/lightningcss.ts";
|
import lightningcss from "lume/plugins/lightningcss.ts";
|
||||||
import resolve_urls from "lume/plugins/resolve_urls.ts";
|
import resolveUrls from "lume/plugins/resolve_urls.ts";
|
||||||
import slugify_urls from "lume/plugins/slugify_urls.ts";
|
import slugifyUrls from "lume/plugins/slugify_urls.ts";
|
||||||
import check_urls from "lume/plugins/check_urls.ts";
|
import checkUrls from "lume/plugins/check_urls.ts";
|
||||||
import inline from "lume/plugins/inline.ts";
|
import inline from "lume/plugins/inline.ts";
|
||||||
import feed from "lume/plugins/feed.ts";
|
import feed from "lume/plugins/feed.ts";
|
||||||
import sitemap from "lume/plugins/sitemap.ts";
|
import sitemap from "lume/plugins/sitemap.ts";
|
||||||
import minify_html from "lume/plugins/minify_html.ts";
|
import minifyHtml from "lume/plugins/minify_html.ts";
|
||||||
|
|
||||||
const site_name = "RGBCube";
|
const siteName = "RGBCube";
|
||||||
const site_description =
|
const siteDescription =
|
||||||
"The home directory and journal of RGBCube and his work.";
|
"The home directory and journal of RGBCube and his work.";
|
||||||
|
|
||||||
const author = "RGBCube";
|
const author = "RGBCube";
|
||||||
const color = "#00FFFF";
|
const color = "#00FFFF";
|
||||||
|
|
||||||
const path_assets = "/assets";
|
const pathAssets = "/assets";
|
||||||
|
|
||||||
const site = lume({
|
const site = lume({
|
||||||
src: "./site",
|
src: "./site",
|
||||||
|
@ -31,9 +31,9 @@ const site = lume({
|
||||||
|
|
||||||
site.data("layout", "default.vto");
|
site.data("layout", "default.vto");
|
||||||
|
|
||||||
site.data("site_name", site_name);
|
site.data("site_name", siteName);
|
||||||
site.data("title", site_name);
|
site.data("title", siteName);
|
||||||
site.data("description", site_description);
|
site.data("description", siteDescription);
|
||||||
site.data("author", author);
|
site.data("author", author);
|
||||||
site.data("color", color);
|
site.data("color", color);
|
||||||
|
|
||||||
|
@ -69,20 +69,52 @@ site.process([".html"], (pages) => {
|
||||||
element.parentNode!.insertBefore(wrapper, element);
|
element.parentNode!.insertBefore(wrapper, element);
|
||||||
wrapper.appendChild(element);
|
wrapper.appendChild(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll(".text-content :where(h1, h2, h3, h4, h5, h6)")
|
||||||
|
.forEach((header) => {
|
||||||
|
if (header.id || header.closest("a") || header.querySelector("a")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textNormalized = header
|
||||||
|
.textContent!
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9\s-]/g, "")
|
||||||
|
.replace(/\s+/g, "-")
|
||||||
|
.replace(/-+/g, "-")
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
let textUnique = textNormalized;
|
||||||
|
let counter = 1;
|
||||||
|
|
||||||
|
while (document.getElementById(textUnique)) {
|
||||||
|
counter++;
|
||||||
|
textUnique = `${textNormalized}-${counter}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.id = textUnique;
|
||||||
|
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.setAttribute("href", "#" + textUnique);
|
||||||
|
|
||||||
|
header.parentNode!.insertBefore(link, header);
|
||||||
|
link.appendChild(header);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
site.use(extract_date());
|
site.use(extractDate());
|
||||||
site.use(redirects());
|
site.use(redirects());
|
||||||
|
|
||||||
site.use(tailwindcss());
|
site.use(tailwindcss());
|
||||||
site.use(code_highlight());
|
site.use(codeHighlight());
|
||||||
|
|
||||||
site.use(resolve_urls());
|
site.use(resolveUrls());
|
||||||
site.use(slugify_urls({
|
site.use(slugifyUrls({
|
||||||
extensions: "*",
|
extensions: "*",
|
||||||
}));
|
}));
|
||||||
site.use(check_urls({
|
site.use(checkUrls({
|
||||||
strict: true,
|
strict: true,
|
||||||
throw: true,
|
throw: true,
|
||||||
}));
|
}));
|
||||||
|
@ -95,12 +127,12 @@ site.use(feed({
|
||||||
limit: Infinity,
|
limit: Infinity,
|
||||||
|
|
||||||
info: {
|
info: {
|
||||||
title: site_name,
|
title: siteName,
|
||||||
description: site_description,
|
description: siteDescription,
|
||||||
authorName: author,
|
authorName: author,
|
||||||
|
|
||||||
image: `${path_assets}/icons/icon.webp`,
|
image: `${pathAssets}/icons/icon.webp`,
|
||||||
icon: `${path_assets}/icons/icon.webp`,
|
icon: `${pathAssets}/icons/icon.webp`,
|
||||||
|
|
||||||
color,
|
color,
|
||||||
|
|
||||||
|
@ -122,7 +154,7 @@ site.use(sitemap({
|
||||||
site.use(lightningcss()); // TODO: LightningCSS doesn't handle inline styles.
|
site.use(lightningcss()); // TODO: LightningCSS doesn't handle inline styles.
|
||||||
site.use(inline());
|
site.use(inline());
|
||||||
|
|
||||||
site.use(minify_html({
|
site.use(minifyHtml({
|
||||||
options: {
|
options: {
|
||||||
// TODO: This breaks tailwind.
|
// TODO: This breaks tailwind.
|
||||||
// minify_css: true,
|
// minify_css: true,
|
||||||
|
|
12
site/404.vto
12
site/404.vto
|
@ -4,10 +4,20 @@ prevent_zoom: true
|
||||||
---
|
---
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
html {
|
||||||
|
font-size: min(9svw, 9svh, 4.5rem);
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
cube-scene {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
cube-face {
|
cube-face {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
grid-template-rows: repeat(2, 1fr);
|
grid-template-rows: repeat(2, 1fr);
|
||||||
|
|
||||||
box-shadow: 0 0 10px var(--foreground);
|
box-shadow: 0 0 10px var(--foreground);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -28,4 +38,6 @@ prevent_zoom: true
|
||||||
{{ set cube_face_top = cube_face }}
|
{{ set cube_face_top = cube_face }}
|
||||||
{{ set cube_face_bottom = cube_face }}
|
{{ set cube_face_bottom = cube_face }}
|
||||||
|
|
||||||
|
{{ set cube_size = "5rem" }}
|
||||||
|
{{ set cube_last = true }}
|
||||||
{{ include "cube.vto" }}
|
{{ include "cube.vto" }}
|
||||||
|
|
|
@ -1,44 +1,43 @@
|
||||||
<style>
|
{{ set cube_minus_px = cube_small ? "" : "- 1px" }}
|
||||||
:root {
|
|
||||||
--cube-width: 5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
{{ if cube_last }}
|
||||||
font-size: min(9svw, 9svh, 4.5rem);
|
<style>
|
||||||
overscroll-behavior: none;
|
cube-face {
|
||||||
|
height: {{ cube_size }};
|
||||||
|
width: {{ cube_size }};
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Guess what? Yeah, you guessed right. Safari can't render shit. */
|
/* Guess what? Yeah, you guessed right. Safari can't render shit. */
|
||||||
.cube-face-front { transform: rotateY(0deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
|
.cube-face-front { transform: rotateY(0deg) translateZ(calc({{ cube_size }} / 2 {{ cube_minus_px }})); }
|
||||||
.cube-face-top { transform: rotateX( 89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
|
.cube-face-top { transform: rotateX( 89.99999999999999deg) translateZ(calc({{ cube_size }} / 2 {{ cube_minus_px }})); }
|
||||||
.cube-face-back { transform: rotateY(180deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
|
.cube-face-back { transform: rotateY(180deg) translateZ(calc({{ cube_size }} / 2 {{ cube_minus_px }})); }
|
||||||
.cube-face-bottom { transform: rotateX(-89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
|
.cube-face-bottom { transform: rotateX(-89.99999999999999deg) translateZ(calc({{ cube_size }} / 2 {{ cube_minus_px }})); }
|
||||||
.cube-face-right { transform: rotateY( 89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
|
.cube-face-right { transform: rotateY( 89.99999999999999deg) translateZ(calc({{ cube_size }} / 2 {{ cube_minus_px }})); }
|
||||||
.cube-face-left { transform: rotateY(-89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
|
.cube-face-left { transform: rotateY(-89.99999999999999deg) translateZ(calc({{ cube_size }} / 2 {{ cube_minus_px }})); }
|
||||||
</style>
|
</style>
|
||||||
|
{{ /if }}
|
||||||
|
|
||||||
<cube-scene class="
|
<cube-scene class="
|
||||||
h-dvh w-dvw
|
|
||||||
flex items-center justify-center
|
flex items-center justify-center
|
||||||
perspective-[calc(var(--cube-width)*3)]
|
perspective-[calc({{ cube_size.replaceAll(" ", "_") }}*3)]
|
||||||
|
overscroll-none
|
||||||
">
|
">
|
||||||
<cube-itself class="
|
<cube-itself class="
|
||||||
size-(--cube-width)
|
size-[{{ cube_size }}]
|
||||||
transform-3d transform-[translateZ(-calc(var(--cube-width)/2-1px))]
|
transform-3d transform-[translateZ(calc({{ cube_size.replaceAll(" ", "_") }}_/_-2))]
|
||||||
">
|
">
|
||||||
{{> const style = `
|
<cube-face draggable="false" class="cube-face-front"> {{ cube_face_front }} </cube-face>
|
||||||
size-(--cube-width) absolute
|
<cube-face draggable="false" class="cube-face-back"> {{ cube_face_back }} </cube-face>
|
||||||
flex items-center justify-center
|
<cube-face draggable="false" class="cube-face-left"> {{ cube_face_left }} </cube-face>
|
||||||
` }}
|
<cube-face draggable="false" class="cube-face-right"> {{ cube_face_right }} </cube-face>
|
||||||
<cube-face draggable="false" class="{{ style }} cube-face-front"> {{ cube_face_front }} </cube-face>
|
<cube-face draggable="false" class="cube-face-top"> {{ cube_face_top }} </cube-face>
|
||||||
<cube-face draggable="false" class="{{ style }} cube-face-back"> {{ cube_face_back }} </cube-face>
|
<cube-face draggable="false" class="cube-face-bottom"> {{ cube_face_bottom }} </cube-face>
|
||||||
<cube-face draggable="false" class="{{ style }} cube-face-left"> {{ cube_face_left }} </cube-face>
|
|
||||||
<cube-face draggable="false" class="{{ style }} cube-face-right"> {{ cube_face_right }} </cube-face>
|
|
||||||
<cube-face draggable="false" class="{{ style }} cube-face-top"> {{ cube_face_top }} </cube-face>
|
|
||||||
<cube-face draggable="false" class="{{ style }} cube-face-bottom"> {{ cube_face_bottom }} </cube-face>
|
|
||||||
</cube-itself>
|
</cube-itself>
|
||||||
</cube-scene>
|
</cube-scene>
|
||||||
|
|
||||||
|
{{ if cube_last }}
|
||||||
<script>
|
<script>
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
@ -61,27 +60,40 @@
|
||||||
|
|
||||||
return Vec(this.x / length, this.y / length, this.z / length);
|
return Vec(this.x / length, this.y / length, this.z / length);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
sum(that) {
|
||||||
|
return Vec(
|
||||||
|
this.x + that.x,
|
||||||
|
this.y + that.y,
|
||||||
|
this.z + that.z,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
sub(that) {
|
||||||
|
return Vec(
|
||||||
|
this.x - that.x,
|
||||||
|
this.y - that.y,
|
||||||
|
this.z - that.z,
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Vec.ZERO = Vec(0, 0, 0);
|
Vec.ZERO = Vec(0, 0, 0);
|
||||||
|
|
||||||
Vec.sum = (a, b) => Vec(
|
|
||||||
a.x + b.x,
|
|
||||||
a.y + b.y,
|
|
||||||
a.z + b.z,
|
|
||||||
);
|
|
||||||
|
|
||||||
Vec.sub = (a, b) => Vec(
|
|
||||||
a.x - b.x,
|
|
||||||
a.y - b.y,
|
|
||||||
a.z - b.z,
|
|
||||||
);
|
|
||||||
|
|
||||||
const Quat = (x, y, z, w) => ({
|
const Quat = (x, y, z, w) => ({
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
w,
|
w,
|
||||||
|
|
||||||
|
mul(that) {
|
||||||
|
return Quat(
|
||||||
|
this.w * that.x + this.x * that.w + this.y * that.z - this.z * that.y,
|
||||||
|
this.w * that.y - this.x * that.z + this.y * that.w + this.z * that.x,
|
||||||
|
this.w * that.z + this.x * that.y - this.y * that.x + this.z * that.w,
|
||||||
|
this.w * that.w - this.x * that.x - this.y * that.y - this.z * that.z,
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Quat.fromAxis = (axis) => {
|
Quat.fromAxis = (axis) => {
|
||||||
|
@ -102,19 +114,12 @@
|
||||||
return Quat(x, y, z, w);
|
return Quat(x, y, z, w);
|
||||||
};
|
};
|
||||||
|
|
||||||
Quat.mul = (a, b) => Quat(
|
|
||||||
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
|
|
||||||
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
|
|
||||||
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
|
|
||||||
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
|
|
||||||
);
|
|
||||||
|
|
||||||
const friction = 3;
|
const friction = 3;
|
||||||
const sensitivityMouse = 0.01;
|
const sensitivityMouse = 0.01;
|
||||||
const sensitivityWheel = 0.006;
|
const sensitivityWheel = 0.006;
|
||||||
|
|
||||||
// One minute.
|
// 15 seconds.
|
||||||
const screensaverTimeoutMs = 1 * 60 * 1000;
|
const screensaverTimeoutMs = 15 * 1000;
|
||||||
|
|
||||||
const mouse = {
|
const mouse = {
|
||||||
down: false,
|
down: false,
|
||||||
|
@ -123,15 +128,16 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const orient = {
|
const orient = {
|
||||||
element: document.querySelector("cube-itself"),
|
elements: document.querySelectorAll("cube-itself"),
|
||||||
quat: Quat(0, 0, 0, 1),
|
quat: Quat(0, 0, 0, 1),
|
||||||
|
|
||||||
set(q) {
|
set(q) {
|
||||||
this.quat = q;
|
this.quat = q;
|
||||||
|
|
||||||
this.element.style.transform = `rotate3d(${q.x}, ${q.y}, ${q.z}, ${
|
for (const element of this.elements) {
|
||||||
Math.acos(q.w) * 2
|
element.style.transform =
|
||||||
}rad)`;
|
`rotate3d(${q.x}, ${q.y}, ${q.z}, ${Math.acos(q.w) * 2}rad)`;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get() {
|
get() {
|
||||||
|
@ -141,6 +147,7 @@
|
||||||
|
|
||||||
let velocity = Vec.ZERO;
|
let velocity = Vec.ZERO;
|
||||||
let impulseThisFrame = Vec.ZERO;
|
let impulseThisFrame = Vec.ZERO;
|
||||||
|
let impulseIdle = Vec(2, 2, -2);
|
||||||
|
|
||||||
const handleUp = () => {
|
const handleUp = () => {
|
||||||
mouse.down = false;
|
mouse.down = false;
|
||||||
|
@ -171,7 +178,7 @@
|
||||||
mouse.previous = newMouse;
|
mouse.previous = newMouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const delta = Vec.sub(newMouse, mouse.previous);
|
const delta = newMouse.sub(mouse.previous);
|
||||||
|
|
||||||
mouse.previous = newMouse;
|
mouse.previous = newMouse;
|
||||||
mouse.lastMove = globalThis.performance.now();
|
mouse.lastMove = globalThis.performance.now();
|
||||||
|
@ -181,10 +188,10 @@
|
||||||
.scale(delta.length())
|
.scale(delta.length())
|
||||||
.scale(sensitivityMouse);
|
.scale(sensitivityMouse);
|
||||||
|
|
||||||
impulseThisFrame = Vec.sum(impulseThisFrame, axis);
|
impulseThisFrame = impulseThisFrame.sum(axis);
|
||||||
|
|
||||||
const rotation = Quat.fromAxis(axis);
|
const rotation = Quat.fromAxis(axis);
|
||||||
orient.set(Quat.mul(rotation, orient.get()));
|
orient.set(rotation.mul(orient.get()));
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("mousemove", handleMove);
|
document.addEventListener("mousemove", handleMove);
|
||||||
|
@ -211,10 +218,10 @@
|
||||||
const axis = Vec(event.deltaY, -event.deltaX, 0)
|
const axis = Vec(event.deltaY, -event.deltaX, 0)
|
||||||
.scale(sensitivityWheel);
|
.scale(sensitivityWheel);
|
||||||
|
|
||||||
impulseThisFrame = Vec.sum(impulseThisFrame, axis);
|
impulseThisFrame = impulseThisFrame.sum(axis);
|
||||||
|
|
||||||
const rotation = Quat.fromAxis(axis);
|
const rotation = Quat.fromAxis(axis);
|
||||||
orient.set(Quat.mul(rotation, orient.get()));
|
orient.set(rotation.mul(orient.get()));
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("wheel", handleWheel, { passive: false });
|
document.addEventListener("wheel", handleWheel, { passive: false });
|
||||||
|
@ -254,8 +261,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalThis.performance.now() - mouse.lastMove > screensaverTimeoutMs) {
|
if (globalThis.performance.now() - mouse.lastMove > screensaverTimeoutMs) {
|
||||||
const impulse = Vec(0.7, 0.7, -0.7);
|
velocity = velocity.sum(impulseIdle.scale(effectiveDelta));
|
||||||
velocity = Vec.sum(impulse.scale(effectiveDelta * 3), velocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const axis = Vec(velocity.x, velocity.y, velocity.z)
|
const axis = Vec(velocity.x, velocity.y, velocity.z)
|
||||||
|
@ -264,10 +270,11 @@
|
||||||
|
|
||||||
const rotation = Quat.fromAxis(axis);
|
const rotation = Quat.fromAxis(axis);
|
||||||
|
|
||||||
orient.set(Quat.mul(rotation, orient.get()));
|
orient.set(rotation.mul(orient.get()));
|
||||||
|
|
||||||
requestAnimationFrame(updateFrame);
|
requestAnimationFrame(updateFrame);
|
||||||
};
|
};
|
||||||
|
|
||||||
updateFrame(0);
|
updateFrame(0);
|
||||||
</script>
|
</script>
|
||||||
|
{{ /if }}
|
||||||
|
|
72
site/_includes/rgbcube.vto
Normal file
72
site/_includes/rgbcube.vto
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<style>
|
||||||
|
cube-face {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
z-index: -1;
|
||||||
|
content: "";
|
||||||
|
|
||||||
|
height: inherit;
|
||||||
|
width: inherit;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cube-face-front {
|
||||||
|
background: linear-gradient(to bottom, cyan, blue);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: linear-gradient(to bottom, white, magenta);
|
||||||
|
mask-image: linear-gradient(to left, magenta, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cube-face-top {
|
||||||
|
background: linear-gradient(to bottom, lime, cyan);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: linear-gradient(to bottom, yellow, white);
|
||||||
|
mask-image: linear-gradient(to left, white, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cube-face-back {
|
||||||
|
background: linear-gradient(to bottom, yellow, red);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: linear-gradient(to bottom, lime, black);
|
||||||
|
mask-image: linear-gradient(to left, black, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cube-face-bottom {
|
||||||
|
background: linear-gradient(to bottom, blue, black);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: linear-gradient(to bottom, magenta, red);
|
||||||
|
mask-image: linear-gradient(to left, red, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cube-face-right {
|
||||||
|
background: linear-gradient(to bottom, white, magenta);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: linear-gradient(to bottom, yellow, red);
|
||||||
|
mask-image: linear-gradient(to left, red, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cube-face-left {
|
||||||
|
background: linear-gradient(to bottom, lime, black);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: linear-gradient(to bottom, cyan, blue);
|
||||||
|
mask-image: linear-gradient(to left, blue, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{{ include "cube.vto" }}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
layout: default.vto
|
layout: default.vto
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center h-[inherit]">
|
||||||
<div class="block text-xl w-[min(100vw,50rem)]">
|
<div class="flex flex-col h-[inherit] w-[min(100dvw,50rem)]">
|
||||||
|
|
||||||
<nav class="
|
<nav class="
|
||||||
transform-[rotateX(180deg)]
|
transform-[rotateX(180deg)]
|
||||||
|
@ -28,16 +28,20 @@ layout: default.vto
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{{> const padding = 4 }} <!-- Keep in sync with -mx-N in default.css. -->
|
{{> const padding = 4 }}
|
||||||
<div class="text-content p-{{ padding }} pt-{{ padding + 12 }}">
|
<div class="text-content text-xl p-{{ padding }} pt-{{ padding + 12 }}">
|
||||||
{{ content }}
|
{{ content }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="border-2 border-black dark:border-white">
|
<footer class="flex justify-center text-sm wrap-anywhere mt-auto p-1.5 pb-2 border-t-4 border-x-4">
|
||||||
|
|
||||||
<footer class="flex justify-center text-sm pt-1 pb-2 wrap-anywhere">
|
|
||||||
Copyright {{ Temporal.Now.plainDateISO().year }} ©
|
Copyright {{ Temporal.Now.plainDateISO().year }} ©
|
||||||
<a href="/"><img class="pl-0.5 pt-0.25 size-5" src="/assets/icons/icon.gif" alt="RGBCube"></a>
|
|
||||||
|
<a draggable="false" class="flex items-center pl-2" href="/">
|
||||||
|
{{ set cube_size = "0.75rem" }}
|
||||||
|
{{ set cube_small = true }}
|
||||||
|
{{ set cube_last = true }}
|
||||||
|
{{ include "rgbcube.vto" }}
|
||||||
|
</a>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -125,6 +125,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100dvh;
|
||||||
|
width: 100dvw;
|
||||||
|
}
|
||||||
|
|
||||||
.text-content {
|
.text-content {
|
||||||
@apply space-y-3;
|
@apply space-y-3;
|
||||||
|
|
||||||
|
@ -160,13 +165,28 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@apply inline-block wrap-anywhere text-[red] dark:text-[yellow] px-1 pb-0.75
|
@apply m-0;
|
||||||
border-2 border-[transparent] border-dashed;
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@apply wrap-anywhere;
|
@apply wrap-anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(:has(> code:only-child)) {
|
||||||
|
@apply px-1;
|
||||||
|
|
||||||
|
&:not(.font-mono) {
|
||||||
|
@apply pb-0.75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:has(h1, h2, h3, h4, h5, h6)) {
|
||||||
|
@apply inline-block wrap-anywhere text-[red] dark:text-[yellow] border-2
|
||||||
|
border-[transparent] border-dashed;
|
||||||
|
|
||||||
|
&:has(> code:only-child) {
|
||||||
|
@apply border-dotted;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@apply border-[red] dark:border-[yellow];
|
@apply border-[red] dark:border-[yellow];
|
||||||
}
|
}
|
||||||
|
@ -176,6 +196,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& :where(h1, h2, h3, h4, h5, h6) {
|
||||||
|
@apply before:underline before:underline-offset-4;
|
||||||
|
|
||||||
|
* {
|
||||||
|
@apply inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover::before {
|
||||||
|
@apply italic text-[red] dark:text-[yellow];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Make it better. */
|
/* TODO: Make it better. */
|
||||||
table {
|
table {
|
||||||
@apply border-collapse whitespace-nowrap;
|
@apply border-collapse whitespace-nowrap;
|
||||||
|
@ -194,12 +227,20 @@
|
||||||
@apply border-black dark:border-white;
|
@apply border-black dark:border-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code:not(pre > code) {
|
||||||
|
@apply border-1 border-dotted px-2 py-0.5 border-black dark:border-white;
|
||||||
|
|
||||||
|
a:hover &, a:active & {
|
||||||
|
@apply border-transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pre code, pre code * {
|
pre code, pre code * {
|
||||||
@apply whitespace-pre;
|
@apply whitespace-pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
div:has(> pre code) {
|
div:has(> pre code) {
|
||||||
@apply outline-1 outline-dotted outline-offset-1 outline-[#444] border-1
|
@apply outline outline-dotted outline-offset-1 outline-[#444] border-1
|
||||||
border-black p-2 bg-[#eee] dark:outline-[#bbb] dark:border-white
|
border-black p-2 bg-[#eee] dark:outline-[#bbb] dark:border-white
|
||||||
dark:bg-[#111];
|
dark:bg-[#111];
|
||||||
}
|
}
|
||||||
|
@ -220,8 +261,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@apply border-1 border-black dark:border-white
|
@apply border-1 border-black dark:border-white;
|
||||||
-mx-4; /* Keep in sync with p-N in text.vto. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
|
181
site/blog.vto
181
site/blog.vto
|
@ -9,8 +9,8 @@ title: about:blog
|
||||||
Blog Articles
|
Blog Articles
|
||||||
|
|
||||||
<span class="whitespace-nowrap overflow-hidden text-sm font-[ecrou]">
|
<span class="whitespace-nowrap overflow-hidden text-sm font-[ecrou]">
|
||||||
<a href="/blog.rss">rss</a>
|
<a id="matrix" href="/blog.rss">rss</a>
|
||||||
<a href="/blog.json">json</a>
|
<a id="matrix" href="/blog.json">json</a>
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
@ -20,14 +20,183 @@ Blog Articles
|
||||||
<ul>
|
<ul>
|
||||||
{{ for article of search.pages("type=article", "order=asc date=desc")}}
|
{{ for article of search.pages("type=article", "order=asc date=desc")}}
|
||||||
<li class="flex">
|
<li class="flex">
|
||||||
<!-- Nope, m-0 doesn't work! -->
|
<a id="matrix" class="text-right font-mono" style="margin-right:calc(var(--spacing)*2)" href="{{ article.url }}">
|
||||||
<code style="margin:0" class="pr-1.25">
|
|
||||||
<a class="text-right" href="{{ article.url }}">
|
|
||||||
{{ article.date.toISOString().slice(2, 10).replaceAll("-", " ") }}
|
{{ article.date.toISOString().slice(2, 10).replaceAll("-", " ") }}
|
||||||
</a>
|
</a>
|
||||||
</code>
|
|
||||||
|
|
||||||
{{ article.title |> md }}
|
{{ article.title |> md }}
|
||||||
</li>
|
</li>
|
||||||
{{ /for }}
|
{{ /for }}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
{
|
||||||
|
let typed = "";
|
||||||
|
const target = "mat";
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
typed += event.key.toLowerCase();
|
||||||
|
|
||||||
|
if (typed.length > target.length) typed = typed.slice(-target.length);
|
||||||
|
|
||||||
|
if (typed === target) {
|
||||||
|
toggle();
|
||||||
|
typed = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let data = null;
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
if (data) {
|
||||||
|
Object.values(data).forEach(({ interval, element, original }) => {
|
||||||
|
clearInterval(interval);
|
||||||
|
|
||||||
|
element.innerHTML = original;
|
||||||
|
|
||||||
|
element.style.color = "";
|
||||||
|
element.style.textShadow = "";
|
||||||
|
element.style.filter = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
data = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {};
|
||||||
|
|
||||||
|
document.querySelectorAll("#matrix").forEach((element, index) => {
|
||||||
|
const original = element.textContent;
|
||||||
|
|
||||||
|
const randomize = () => {
|
||||||
|
const dark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
|
||||||
|
const color = dark ? "#00ff00" : "#00cc00";
|
||||||
|
const glowColor = dark ? "#00ff00" : "#00ff00";
|
||||||
|
|
||||||
|
element.style.color = color;
|
||||||
|
element.style.filter = `drop-shadow(0 0 5px ${glowColor})`;
|
||||||
|
|
||||||
|
element.innerHTML = original.replace(/\d/g, () => `<span${Math.random() > 0.5 ? "" : ` style="text-shadow: 0 0 2px ${glowColor}"`}>${Math.floor(Math.random() * 10)}</span>`);
|
||||||
|
};
|
||||||
|
|
||||||
|
randomize();
|
||||||
|
const interval = setInterval(randomize, 100);
|
||||||
|
|
||||||
|
data[index] = { interval, element, original };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
{
|
||||||
|
let typed = "";
|
||||||
|
const target = "rix";
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
typed += event.key.toLowerCase();
|
||||||
|
|
||||||
|
if (typed.length > target.length) typed = typed.slice(-target.length);
|
||||||
|
|
||||||
|
if (typed === target) {
|
||||||
|
toggle();
|
||||||
|
typed = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const randomStrip = () => ({
|
||||||
|
xFactor: Math.random() * 0.90 + (1 - 0.90) / 2,
|
||||||
|
y: Math.random() * -window.innerHeight - 100,
|
||||||
|
deltaY: Math.random() * 1.7 + 1,
|
||||||
|
size: Math.floor(Math.random() * 16) + 8,
|
||||||
|
});
|
||||||
|
|
||||||
|
const strips = Array.from({ length: 60 }, () => randomStrip());
|
||||||
|
|
||||||
|
let data = null;
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
if (data) {
|
||||||
|
cancelAnimationFrame(data.animationFrameId);
|
||||||
|
data.canvas.remove();
|
||||||
|
|
||||||
|
window.removeEventListener("resize", data.handleResize);
|
||||||
|
|
||||||
|
data = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {};
|
||||||
|
|
||||||
|
data.canvas = document.body.appendChild(document.createElement("canvas"));
|
||||||
|
const { canvas } = data;
|
||||||
|
canvas.style.position = "fixed";
|
||||||
|
canvas.style.top = "0";
|
||||||
|
canvas.style.left = "0";
|
||||||
|
canvas.style.width = "100%";
|
||||||
|
canvas.style.height = "100%";
|
||||||
|
canvas.style.zIndex = "999999999";
|
||||||
|
canvas.style.pointerEvents = "none";
|
||||||
|
|
||||||
|
data.context = canvas.getContext("2d");
|
||||||
|
const { context } = data;
|
||||||
|
context.globalCompositeOperation = "lighter";
|
||||||
|
|
||||||
|
const handleResize = () => {
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
handleResize();
|
||||||
|
window.addEventListener("resize", handleResize);
|
||||||
|
data.handleResize = handleResize;
|
||||||
|
|
||||||
|
const animate = () => {
|
||||||
|
const { canvas, context } = data;
|
||||||
|
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
context.shadowOffsetX = 0;
|
||||||
|
context.shadowOffsetY = 0;
|
||||||
|
context.shadowBlur = 8;
|
||||||
|
context.shadowColor = "#94f475";
|
||||||
|
context.textBaseline = "top";
|
||||||
|
context.textAlign = "center";
|
||||||
|
|
||||||
|
for (const strip of strips) {
|
||||||
|
context.font = `${strip.size}px sans`;
|
||||||
|
|
||||||
|
if (strip.y > canvas.height + (strip.size * 40)) {
|
||||||
|
Object.assign(strip, randomStrip())
|
||||||
|
}
|
||||||
|
|
||||||
|
let { y: yCopy } = strip;
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
switch (true) {
|
||||||
|
case i < 1: context.fillStyle = "#cefbe4"; break;
|
||||||
|
case i < 2: context.fillStyle = "#81ec72"; break;
|
||||||
|
case i < 4: context.fillStyle = "#5cd646"; break;
|
||||||
|
case i < 8: context.fillStyle = "#54d13c"; break;
|
||||||
|
case i < 14: context.fillStyle = "#4ccc32"; break;
|
||||||
|
case i < 18: context.fillStyle = "#43c728"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const characters = ["诶", "比", "西", "迪", "伊", "吉", "艾", "杰", "开", "哦", "屁", "提", "维"];
|
||||||
|
const character = characters[Math.floor(Math.random() * characters.length)];
|
||||||
|
|
||||||
|
context.fillText(character, strip.xFactor * canvas.width, yCopy);
|
||||||
|
|
||||||
|
// Deterministic but still random.
|
||||||
|
yCopy -= strips[i].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
strip.y += strip.deltaY;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.animationFrameId = requestAnimationFrame(animate);
|
||||||
|
};
|
||||||
|
|
||||||
|
animate();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
|
@ -35,5 +35,5 @@ Here are some other useful links as well:
|
||||||
|
|
||||||
const element = document.getElementById("bot-block");
|
const element = document.getElementById("bot-block");
|
||||||
element.href = real;
|
element.href = real;
|
||||||
element.children[0].innerHTML = real.substring(7);
|
element.children[0].textContent = real.substring(7);
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,68 +3,18 @@ prevent_zoom: true
|
||||||
---
|
---
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
cube-face::after {
|
html {
|
||||||
z-index: -1;
|
font-size: min(9svw, 9svh, 4.5rem);
|
||||||
content: "";
|
overscroll-behavior: none;
|
||||||
|
|
||||||
height: inherit;
|
|
||||||
width: inherit;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cube-face-front {
|
cube-scene {
|
||||||
background: linear-gradient(to bottom, cyan, blue);
|
height: 100%;
|
||||||
|
|
||||||
&::after {
|
|
||||||
background: linear-gradient(to bottom, white, magenta);
|
|
||||||
mask-image: linear-gradient(to left, magenta, transparent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cube-face-top {
|
cube-face {
|
||||||
background: linear-gradient(to bottom, lime, cyan);
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
&::after {
|
|
||||||
background: linear-gradient(to bottom, yellow, white);
|
|
||||||
mask-image: linear-gradient(to left, white, transparent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cube-face-back {
|
|
||||||
background: linear-gradient(to bottom, yellow, red);
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
background: linear-gradient(to bottom, lime, black);
|
|
||||||
mask-image: linear-gradient(to left, black, transparent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cube-face-bottom {
|
|
||||||
background: linear-gradient(to bottom, blue, black);
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
background: linear-gradient(to bottom, magenta, red);
|
|
||||||
mask-image: linear-gradient(to left, red, transparent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cube-face-right {
|
|
||||||
background: linear-gradient(to bottom, white, magenta);
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
background: linear-gradient(to bottom, yellow, red);
|
|
||||||
mask-image: linear-gradient(to left, red, transparent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cube-face-left {
|
|
||||||
background: linear-gradient(to bottom, lime, black);
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
background: linear-gradient(to bottom, cyan, blue);
|
|
||||||
mask-image: linear-gradient(to left, blue, transparent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -91,4 +41,6 @@ prevent_zoom: true
|
||||||
<a draggable="false" class="{{ style }}" href="/blog/">blog</a>
|
<a draggable="false" class="{{ style }}" href="/blog/">blog</a>
|
||||||
{{ /set }}
|
{{ /set }}
|
||||||
|
|
||||||
{{ include "cube.vto" }}
|
{{ set cube_size = "5rem" }}
|
||||||
|
{{ set cube_last = true }}
|
||||||
|
{{ include "rgbcube.vto" }}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue