falsy.cat/index.html
2022-12-01 17:41:32 +09:00

698 lines
20 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="content-language" content="ja">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>falsycat</title>
<meta name="author" content="falsycat">
<meta name="description" content="falsycat's portfolio">
<link rel="icon" href="/pf/img/icon/falsycat.webp">
<meta name="twitter:site" content="@falsycat">
<meta name="twitter:card" content="summary">
<meta property="og:url" content="https://falsy.cat/">
<meta property="og:title" content="falsycat">
<meta property="og:description" content="falsycat's portfolio">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Black+Ops+One&family=Ubuntu&family=Noto+Serif+JP&display=block" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/destyle.css@2.0.2/destyle.css">
<style>
:root {
--color1: #DDD;
--color2: #222831;
--color3: #30475E;
--color4: #f05454;
--color1-disabled: #555;
}
html {
font-size: 12pt;
background-color: var(--color2);
font-family: 'Ubuntu', sans-serif;
}
body {
position: relative;
min-height: 100vh;
}
::-webkit-scrollbar {
display: none;
}
h1, h2, h3, h4 {
font-family: 'Black Ops One', sans-serif;
cursor: default;
}
#background, #frame {
position: absolute;
left: 0;
right: 0;
top: 0;
height: 100%;
z-index: -1;
overflow: hidden;
}
#background svg {
position: absolute;
stroke: var(--color3);
fill: var(--color3);
stroke-width: 1px;
}
#background .text {
font-family: 'Noto Serif JP', serif;
font-size: 3vw;
letter-spacing: 1em;
line-height: 2em;
text-align: right;
white-space: pre;
}
#background:after {
display: block;
content: "";
width: 100%;
height: 100%;
position: relative;
z-index: 0;
background-image: url("/pf/img/tex/clean-gray-paper.webp");
background-size: 512px 512px;
}
#frame {
position: fixed;
left: 0;
right: 0;
top: 0;
height: 100%;
overflow: hidden;
z-index: 1;
pointer-events: none;
}
#frame svg {
position: absolute;
stroke: none;
fill: #000;
}
#foreground {
max-width: 60rem;
min-width: 16rem;
padding: 1rem 0;
margin: 0 auto;
text-align: center;
display: flex;
align-items: center;
flex-direction: column;
overflow-x: hidden;
color: var(--color1);
}
#header {
margin: calc(50vh - 6rem) 0 2rem 0;
}
#header h1 {
font-size: 8rem;
line-height: 1em;
color: var(--color4);
}
#header .role {
font-size: 1rem;
letter-spacing: 2rem;
text-indent: 1em;
line-height: 1em;
}
#header .icons {
margin: 1rem 0;
width: 100%;
}
#header .icons ul {
max-width: 20rem;
margin: 0 auto;
display: flex;
justify-content: space-around;
}
#header .icons ul li {
margin: 0 .2rem;
background-color: var(--color2);
border-radius: 50%;
border: .5em solid var(--color2);
}
#header .icons .icon, #header .icons a {
display: block;
width: 2rem;
height: 2rem;
}
#header .icons .icon-bg {
border-radius: 50%;
background-color: var(--color1);
}
#works p a {
text-decoration: underline;
color: var(--color4);
}
#works h2 {
font-size: 2rem;
}
#works>ul {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
#works>ul>li {
margin: .5rem;
}
#works>ul>li img.thumb {
width: 16rem;
height: 9rem;
border: solid 1px black;
}
#footer {
font-size: .8rem;
margin-top: 1rem;
color: var(--color1-disabled);
}
#footer .note {
font-size: .6rem;
}
#footer .note a {
text-decoration: underline;
}
.popup-wrapper {
display: flex;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 2;
background-color: rgba(0, 0, 0, .7);
flex-direction: column;
justify-content: center;
align-items: center;
transition: opacity .2s, visibility .2s;
opacity: 0;
visibility: hidden;
}
.popup-wrapper.shown {
opacity: 1;
visibility: visible;
}
.popup-wrapper .outside-msg {
color: var(--color4);
cursor: default;
}
.popup {
padding: 2rem;
margin: 0 1rem;
background-color: #DDD;
max-width: 40rem;
max-height: 95%;
width: calc(95% - 1rem);
overflow: auto;
text-align: left;
color: var(--color2);
border: .5rem solid var(--color3);
}
.popup h3 {
font-size: 2rem;
text-align: center;
line-height: 4rem;
}
.popup h4 {
font-size: 1.5rem;
text-align: center;
line-height: 2rem;
}
.popup h4:before, .popup h4:after {
content: " - ";
}
.popup ul {
list-style-type: disc;
margin: 1rem 1rem 1rem 2rem;
line-height: 1.5rem;
}
.popup ul li {
margin: .25rem 0;
}
.popup p {
text-indent: 1rem;
margin: .5rem 0;
line-height: 1.5rem;
}
.popup p.center {
text-align: center;
}
.popup a {
text-decoration: underline;
color: var(--color3);
}
.popup figure.thumb {
text-align: center;
position: relative;
width: 100%;
padding-top: 56.25%;
margin: 0 auto;
}
.popup table {
margin: .5rem;
}
.popup table td {
padding: 0 .5rem;
}
.popup figure.thumb img, .popup figure.thumb iframe {
position: absolute;
top: 0;
right: 0;
width: 100% !important;
height: 100% !important;
}
.slideshow {
position: relative;
}
.slideshow > ul.buttons {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
list-style-type: none;
display: flex;
justify-content: center;
margin: 0;
}
.slideshow > ul.buttons li {
width: .8rem;
height: .8rem;
background-color: var(--color1);
opacity: .5;
transition: opacity .5s;
cursor: pointer;
border-radius: 50%;
margin: .5rem;
}
.slideshow > ul.buttons li.shown, .slideshow > ul.buttons li:hover {
opacity: .8;
}
.slideshow > :not(.shown) {
display: none;
}
@media (max-width: 45rem) {
html {
font-size: 14pt;
}
.hide-on-phone {
display: none;
}
#background .text {
font-size: 1.2rem;
}
#header {
margin: 16vh 0;
}
#header h1 {
font-size: 4rem;
}
#header .role {
letter-spacing: 1rem;
}
#works img.thumb {
width: 90%;
}
.popup {
padding: .5rem;
margin: .5rem;
}
}
</style>
<script>
"use strict";
const lazyLoad = (e) => {
e.querySelectorAll("iframe.lazy, img.lazy").forEach((e) => {
e.classList.remove("lazy");
e.src = e.dataset.src;
});
};
const initPopup = () => {
const reload = (path) => {
/* hide all shown popup */
document.querySelectorAll(".popup-wrapper.shown").forEach(p => {
p.classList.remove("shown");
});
/* beatiful path */
if (path === "/index.html") {
path = "/";
}
if (path.charAt(0) !== "/") {
path = "/"+path;
}
if (path.slice(-1) !== "/") {
path += "/";
}
try {
history.replaceState({}, "", path);
} catch (e) {
path = "";
history.replaceState({}, "", "/");
}
path = path.slice(1, -1);
if (path === "") {
return;
}
/* showing popup */
const targets = document.getElementsByName(path);
if (targets.length === 0) {
reload("/");
return;
}
const target = targets[0];
if (target.classList.contains("popup-wrapper")) {
target.classList.add("shown");
lazyLoad(target);
}
};
document.querySelectorAll(".popup-wrapper").forEach(p => {
p.addEventListener("click", e2 => {
p.querySelectorAll("iframe.youtube").forEach(yt => {
yt.contentWindow.postMessage(JSON.stringify({
event: "command",
func: "pauseVideo",
args: "",
}), "*");
});
reload("/");
});
let text = document.createElement("div");
text.innerText = "CLOSE";
text.classList.add("outside-msg");
p.appendChild(text);
});
document.querySelectorAll(".popup-wrapper .popup").forEach(p => {
p.addEventListener("click", e2 => e2.stopPropagation());
});
document.querySelectorAll("a[href^='/']").forEach(p => {
p.addEventListener("click", ev => {
ev.preventDefault()
reload(p.getAttribute("href"));
});
});
reload(location.pathname);
};
const initSlideshow = () => {
document.querySelectorAll(".slideshow").forEach(s => {
let items = Array.from(s.children);
let buttons = document.createElement("ul");
buttons.classList.add("buttons");
s.appendChild(buttons);
let timeout = null;
let switch_to = (i) => {
if (timeout !== null) clearTimeout(timeout);
i %= items.length;
let old = s.querySelector(":scope > .shown");
if (old !== null) old.classList.remove("shown");
old = buttons.querySelector(":scope > .shown");
if (old !== null) old.classList.remove("shown");
items[i].classList.add("shown");
buttons.children[i].classList.add("shown");
timeout = setTimeout(() => switch_to(i+1), 5000);
};
items.forEach((c, i) => {
let button = document.createElement("li");
buttons.appendChild(button);
button.addEventListener("click", () => { switch_to(i); });
});
switch_to(0);
});
};
const initGraphics = () => {
let circles = document.querySelector("#background svg.circles");
for (let x = 0; x < 15; ++x) {
for (let y = 0; y < 10; ++y) {
let c = document.createElementNS("http://www.w3.org/2000/svg", "circle");
c.setAttributeNS(null, "cx", x*10+5+"");
c.setAttributeNS(null, "cy", y*10+5+"");
c.setAttributeNS(null, "r", "2");
circles.appendChild(c);
}
}
let sinwave = document.querySelector("#background svg.sinwaves");
{
let paths = sinwave.querySelectorAll("path");
let t = 0;
window.setInterval(() => {
paths.forEach((p, i) => {
let verts = "M ";
for (let x = 0; x < 100; ++x) {
verts += x*10+","+(Math.sin(x/4.5/Math.PI+t*.005*(i*(1.08-i*.1)+1)+i)*40+50)+" ";
}
p.setAttributeNS(null, "d", verts);
});
++t;
}, 50);
}
let squares = document.querySelector("#background svg.squares");
for (let i = 0; i < 40; ++i) {
let s = document.createElementNS("http://www.w3.org/2000/svg", "use");
s.setAttributeNS(null, "href", "#svg-background-square");
s.setAttributeNS(null, "transform", "rotate("+i/40*360+")");
squares.appendChild(s);
}
};
window.addEventListener("DOMContentLoaded", e => {
initPopup();
initSlideshow();
initGraphics();
});
</script>
</head>
<body>
<div id="background">
<svg class="circles hide-on-phone"
width="60vh" height="40vh"
viewBox="0 0 150 100"
preserveAspectRatio="none"
style="left: 0; bottom: 10%; stroke: none; opacity: .5">
</svg>
<svg class="sinwaves"
width="max(100vw, 150mm)" height="min(10rem, 40mm)"
viewBox="0 0 1000 100"
preserveAspectRatio="none"
style="left: 0; top: calc(50vh - 5rem); fill: none">
<path></path>
<path></path>
<path></path>
<path></path>
</svg>
<svg class="triangles"
width="60vh" height="60vh"
viewBox="0 0 1000 1000"
preserveAspectRatio="none"
style="max-width: 70vw; max-height: 70vw; right: -10%; top: 10%; stroke: none">
<defs>
<path id="svg-background-triangle" d="M 500,500 0,0 1000,0 Z"></path>
</defs>
<use href="#svg-background-triangle" opacity=".5"></use>
<use href="#svg-background-triangle" opacity=".4" y="100"></use>
<use href="#svg-background-triangle" opacity=".3" y="200"></use>
<use href="#svg-background-triangle" opacity=".2" y="300"></use>
<use href="#svg-background-triangle" opacity=".2" y="400"></use>
<use href="#svg-background-triangle" opacity=".1" y="500"></use>
</svg>
<svg class="squares"
width="100vh" height="100vh"
viewBox="-600 -600 1200 1200"
preserveAspectRatio="none"
style="min-width: 40rem; min-height: 40rem; left: 50vw; top: 50vh; transform: translateX(-50%) translateY(-50%); fill: none; opacity: .6">
<defs>
<rect id="svg-background-square" width="300" height="300" x="100" y="100"></rect>
</defs>
</svg>
<svg class="lines hide-on-phone"
width="80vw" height="30vw"
viewBox="0 0 200 200"
preserveAspectRatio="none"
style="left: 0; top: 0; stroke: none">
<defs>
<path id="svg-background-line" d="M 0,0 18,60 16,60 28,100, 38,100 26,60 28,60 10,0 Z"></path>
</defs>
<use href="#svg-background-line" x="0" ></use>
<use href="#svg-background-line" x="30"></use>
<use href="#svg-background-line" x="60"></use>
<use href="#svg-background-line" x="90"></use>
</svg>
<div class="text hide-on-phone"
style="position: absolute; right: 0; top: 40vh; color: var(--color3); opacity: .6">
色蝣しき切み翳しをり
灰成憬終葉な揺際一
の今た言で唯出の
憧蜉末色揺吐せ
蝣今唯れ終吐
揺翳色言翳
末し色せ
終灰な
贖罪
</div>
</div>
<div id="foreground">
<div id="header">
<h1>falsycat</h1>
<div class="role">PROGRAMMER</div>
<div class="icons">
<ul>
<li>
<a href="https://github.com/falsycat" target="_blank">
<svg class ="icon" viewBox="0 0 160 160" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<path style="fill-rule:evenodd;stroke:none;stroke-width:.13333" d="M80.515 0C36.054 0 0 36.046 0 80.514c0 35.574 23.07 65.754 55.061 76.401 4.024.745 5.501-1.747 5.501-3.873 0-1.92-.074-8.263-.109-14.99-22.4 4.87-27.126-9.5-27.126-9.5-3.662-9.307-8.94-11.782-8.94-11.782-7.305-4.997.551-4.894.551-4.894 8.085.567 12.342 8.297 12.342 8.297 7.182 12.309 18.836 8.75 23.43 6.693.723-5.202 2.81-8.757 5.112-10.766-17.883-2.036-36.683-8.94-36.683-39.791 0-8.79 3.146-15.973 8.296-21.612-.836-2.029-3.592-10.217.78-21.307 0 0 6.761-2.164 22.147 8.253 6.423-1.784 13.31-2.679 20.153-2.71 6.843.031 13.736.926 20.17 2.71 15.368-10.417 22.12-8.253 22.12-8.253 4.382 11.09 1.625 19.278.79 21.307 5.162 5.639 8.286 12.821 8.286 21.612 0 30.924-18.836 37.733-36.765 39.727 2.888 2.498 5.461 7.398 5.461 14.91 0 10.772-.093 19.442-.093 22.095 0 2.143 1.45 4.654 5.53 3.863 31.975-10.658 55.015-40.828 55.015-76.39C161.03 36.046 124.981 0 80.515 0" />
<path style="fill-rule:nonzero;stroke:none;stroke-width:.13333" d="M30.495 115.601c-.177.401-.806.52-1.38.245-.584-.262-.912-.808-.722-1.209.173-.412.804-.525 1.386-.252.586.264.919.815.716 1.216m3.261 3.637c-.384.356-1.134.191-1.643-.372-.527-.561-.626-1.312-.236-1.673.396-.356 1.124-.19 1.651.372.527.568.63 1.313.228 1.673m3.175 4.638c-.493.342-1.3.02-1.799-.695-.493-.716-.493-1.575.011-1.919.5-.344 1.295-.034 1.8.676.492.727.492 1.587-.012 1.938m4.35 4.48c-.442.486-1.382.355-2.07-.309-.704-.649-.9-1.57-.457-2.057.446-.488 1.392-.35 2.085.308.699.648.912 1.576.441 2.057m6 2.602c-.194.63-1.1.917-2.012.649-.91-.276-1.506-1.015-1.322-1.652.189-.635 1.098-.933 2.017-.647.91.275 1.507 1.008 1.317 1.65m6.59.482c.022.664-.751 1.215-1.709 1.226-.962.022-1.74-.515-1.752-1.168 0-.67.756-1.216 1.72-1.232.956-.019 1.74.514 1.74 1.174m6.132-1.044c.115.648-.55 1.314-1.501 1.49-.935.172-1.8-.228-1.919-.87-.116-.665.562-1.33 1.495-1.502.952-.166 1.804.224 1.925.882" />
</svg>
</a>
</li>
<li>
<a href="https://git.falsy.cat/explore" target="_blank">
<img class="icon icon-bg" style="padding: 0.2rem" src="/pf/img/icon/gitea.png">
</a>
</li>
<li>
<a href="https://falsy.cat/admin" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-bg" style="padding: 0.2rem" viewBox="0 0 24 24" fill="var(--color2)" class="w-6 h-6">
<path fill-rule="evenodd" d="M4.848 2.771A49.144 49.144 0 0112 2.25c2.43 0 4.817.178 7.152.52 1.978.292 3.348 2.024 3.348 3.97v6.02c0 1.946-1.37 3.678-3.348 3.97a48.901 48.901 0 01-3.476.383.39.39 0 00-.297.17l-2.755 4.133a.75.75 0 01-1.248 0l-2.755-4.133a.39.39 0 00-.297-.17 48.9 48.9 0 01-3.476-.384c-1.978-.29-3.348-2.024-3.348-3.97V6.741c0-1.946 1.37-3.68 3.348-3.97zM6.75 8.25a.75.75 0 01.75-.75h9a.75.75 0 010 1.5h-9a.75.75 0 01-.75-.75zm.75 2.25a.75.75 0 000 1.5H12a.75.75 0 000-1.5H7.5z" clip-rule="evenodd" />
</svg>
</a>
</li>
<li>
<a href="https://twitter.com/falsycat" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 400 400">
<circle cx="200" cy="200" r="200" fill="#1da1f2"/>
<path d="M163.4 305.5c88.7 0 137.2-73.5 137.2-137.2 0-2.1 0-4.2-.1-6.2a98.79 98.79 0 0 0 24.1-25c-8.6 3.8-17.9 6.4-27.7 7.6 10-6 17.6-15.4 21.2-26.7-9.3 5.5-19.6 9.5-30.6 11.7-8.8-9.4-21.3-15.2-35.2-15.2-26.6 0-48.2 21.6-48.2 48.2 0 3.8.4 7.5 1.3 11-40.1-2-75.6-21.2-99.4-50.4-4.1 7.1-6.5 15.4-6.5 24.2 0 16.7 8.5 31.5 21.5 40.1-7.9-.2-15.3-2.4-21.8-6v.6c0 23.4 16.6 42.8 38.7 47.3a48.07 48.07 0 0 1-12.7 1.7 46.04 46.04 0 0 1-9.1-.9 48.15 48.15 0 0 0 45 33.5c-16.5 12.9-37.3 20.6-59.9 20.6-3.9 0-7.7-.2-11.5-.7 21.1 13.8 46.5 21.8 73.7 21.8" fill="#fff"/>
</svg>
</a>
</li>
</ul>
</div>
</div>
<div id="works">
<h2>WORKS</h2>
<ul>
<li>
<div><a href="/pf/goodmans-invitation"><img class="thumb" src="/pf/img/thumb/goodmans-invitation.webp"></a></div>
<div name="pf/goodmans-invitation" class="popup-wrapper"><div class="popup">
<h3>Goodman's Invitation</h3>
<figure class="thumb"><iframe class="youtube lazy" data-src="https://www.youtube.com/embed/4ZJyPa7GZcE?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure>
<ul>
<li>original song</li>
<li><a href="https://youtu.be/4ZJyPa7GZcE" target="_blank">宗教勧誘 / Goodman's Invitation - YouTube</a></li>
</ul>
</div></div>
</li>
<li>
<div><a href="https://nf7.falsy.cat/" target="_blank"><img class="thumb" src="/pf/img/thumb/nf7.apng"></a></div>
</li>
<li>
<div><a href="/pf/rationalist"><img class="thumb" src="/pf/img/thumb/rationalist.webp"></a></div>
<div name="pf/rationalist" class="popup-wrapper"><div class="popup">
<h3>RATIONALIST - Shione Lt</h3>
<figure class="thumb"><iframe class="youtube lazy" data-src="https://www.youtube.com/embed/VoYQll1F604?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure>
<ul>
<li>original song</li>
<li><a href="https://youtu.be/VoYQll1F604" target="_blank">RATIONALIST - YouTube</a></li>
</ul>
</div></div>
</li>
<li>
<div><a href="/pf/biner"><img class="thumb" src="/pf/img/thumb/biner.webp"></a></div>
<div name="pf/biner" class="popup-wrapper"><div class="popup">
<h3>biner</h3>
<figure class="thumb"><img class="lazy" data-src="/pf/img/thumb/biner.webp"></figure>
<ul>
<li>IDL for binary format</li>
<li><a href="https://github.com/falsycat/biner" target="_blank">falsycat/biner - GitHub</a></li>
</ul>
</div></div>
</li>
<li>
<div><a href="/pf/leftone"><img class="thumb" src="/pf/img/thumb/leftone.webp"></a></div>
<div name="pf/leftone" class="popup-wrapper"><div class="popup">
<h3>LEFTONE</h3>
<figure class="thumb slideshow">
<img class="lazy" data-src="/pf/img/thumb/leftone-1.webp">
<img class="lazy" data-src="/pf/img/thumb/leftone-2.webp">
<img class="lazy" data-src="/pf/img/thumb/leftone-3.webp">
<img class="lazy" data-src="/pf/img/thumb/leftone-4.webp">
</figure>
<ul>
<li>2D action game featuring ray marching in backgrounds</li>
<li>developed by C11+GLSL</li>
<li>got a prize on <a href="https://u22procon.com" target="_blank">2020 41st U22 Programming Contest</a></li>
<li><a href="https://github.com/falsycat/LEFTONE" target="_blank">falsycat/LEFTONE - GitHub</a></li>
</ul>
</div></div>
</li>
</ul>
</div>
<div id="footer">
<div>Copyright 2022 falsycat &lt;&#109;&#101;&commat;&#102;&#97;&#108;&#115;&#121;&period;&#99;&#97;&#116;&gt;</div>
<div class="note">.CAT is a top level domain of <a href="https://domini.cat" target="_blank">Catalunya</a>.</div>
</div>
</div>
<div id="frame">
<svg class="side-triangles hide-on-phone"
width="100%" height="100%"
viewBox="0 0 100 100"
preserveAspectRatio="none"
style="fill: #000">
<path d="M 0,0 10,0 0,100 Z"></path>
<path d="M 100,0 90,100 100,100 Z"></path>
</svg>
</div>
</body>
</html>