vance.land/index.html

318 lines
9.9 KiB
HTML
Raw Normal View History

2022-10-27 19:21:06 +00:00
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta content='width=device-width, initial-scale=1, minimum-scale=1' name='viewport'>
2022-10-27 19:21:06 +00:00
<title>vance.land</title>
<meta content='vance.land' name='description'>
<meta content='vance' name='author'>
2022-10-27 19:21:06 +00:00
<base target='_blank'>
<style>
@font-face {
font-family: 'VT323';
src: url('VT323.ttf');
}
2023-04-01 02:11:20 +00:00
2022-10-27 19:21:06 +00:00
* {
color: #20C20E;
font-family: 'VT323', monospace;
font-size: 16pt;
2024-05-08 03:25:03 +00:00
cursor: none;
2022-10-27 19:21:06 +00:00
}
2023-04-01 02:05:23 +00:00
html {
2023-04-01 02:05:23 +00:00
width: 100%;
height: 100%;
}
body {
2022-10-27 19:21:06 +00:00
background: #000000;
overflow: hidden;
}
2022-10-27 19:21:06 +00:00
a {
text-decoration: none;
white-space: nowrap;
overflow: hidden;
}
2022-10-27 19:21:06 +00:00
p {
padding: 0;
margin: 0;
font-size: 1rem;
white-space: normal;
width: 420px;
}
2022-10-27 19:21:06 +00:00
span {
font-size: 1rem;
}
2024-05-08 03:25:03 +00:00
#banana {
position: absolute;
z-index: 2;
pointer-events: none;
}
2024-05-05 22:52:18 +00:00
#bonzi {
position: absolute;
2024-05-05 22:52:18 +00:00
transition: transform 0.8s;
transform-style: preserve-3d;
z-index: 1;
pointer-events: none;
}
2022-10-27 19:21:06 +00:00
#live {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 0;
}
</style>
</head>
<body>
2024-05-08 03:25:03 +00:00
<img alt='banana' id='banana' src='banana.png'/>
2024-05-05 22:52:18 +00:00
<img alt='bonzi' id='bonzi' src='bonzi.png'/>
2024-05-08 03:25:03 +00:00
<video autoplay height='360px' playsinline id='live' width='640px'>
</video>
<script src="https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js"></script>
<script>
const email = (function () {
var p = Array.prototype.slice.call(arguments),
V = p.shift();
return p.reverse().map(function (o, i) {
return String.fromCharCode(o - V - 36 - i)
}).join('')
})(59, 164, 200, 197, 207, 193, 213) + (40559).toString(36).toLowerCase() + (function () {
var Q = Array.prototype.slice.call(arguments),
O = Q.shift();
return Q.reverse().map(function (e, u) {
return String.fromCharCode(e - O - 57 - u)
}).join('')
})(20, 125, 179, 176) + (766).toString(36).toLowerCase() + (function () {
var E = Array.prototype.slice.call(arguments),
f = E.shift();
return E.reverse().map(function (s, C) {
return String.fromCharCode(s - f - 33 - C)
}).join('')
})(24, 158, 167);
const socials = {
'matrix': {
'text': '💊 @vance:vance.land',
'link': 'https://matrix.to/#/@vance:vance.land'
},
'feed': {
'text': `🥫 @${email}`,
'link': 'https://feed.vance.land/@vance'
},
'live': {
'text': '🎥 live.vance.land',
'link': 'https://live.vance.land/vance/'
},
'email': {
'text': `📧 ${email}`,
'link': `mailto:${email}`
},
'urbit': {
'text': '🌐 ~sarsup-figput',
'link': 'https://sarsup-figput.vance.land/blog'
},
'telegram': {
'text': '💬 @vanceland',
'link': 'https://t.me/vanceland'
},
'code': {
'text': '🐱‍💻 code.vance.land',
'link': 'https://code.vance.land/vance'
},
'music': {
'text': '🎶 @SMOOTHAPPLIANCE',
'link': 'https://soundcloud.com/smoothappliance'
},
'haram': {
'text': '🕋',
'link': 'https://dreamsinco.de'
2022-10-27 19:21:06 +00:00
}
};
2024-05-05 22:52:18 +00:00
// bonzi
2024-05-08 03:25:03 +00:00
const banana = document.getElementById('banana');
const bonzi = document.getElementById('bonzi');
2024-05-05 22:52:18 +00:00
let mouseTop = 0;
let mouseLeft = 0;
let bonziTop = 0;
let bonziLeft = 0;
const speed = 0.02;
2024-05-08 03:25:03 +00:00
(function moveBonzi() {
2024-05-05 22:52:18 +00:00
bonzi.style.transform = bonziLeft > mouseLeft ? 'translate(5%, -35%) scaleX(-1)' : 'translate(-80%, -35%)';
bonziTop = bonziTop + ((mouseTop - bonziTop) * speed);
bonziLeft = bonziLeft + ((mouseLeft - bonziLeft) * speed);
bonzi.style.top = `${bonziTop}px`;
bonzi.style.left = `${bonziLeft}px`;
requestAnimationFrame(moveBonzi);
2024-05-08 03:25:03 +00:00
})();
2024-05-03 04:16:10 +00:00
['mousemove', 'touchstart', 'touchmove'].forEach(type => {
window.addEventListener(type, event => {
2024-05-05 22:52:18 +00:00
mouseTop = event.clientY || event.touches[0].clientY;
mouseLeft = event.clientX || event.touches[0].clientX;
2024-05-08 03:25:03 +00:00
banana.style.top = `${mouseTop}px`;
banana.style.left = `${mouseLeft}px`;
2024-05-03 04:16:10 +00:00
});
});
2024-05-08 03:25:03 +00:00
//live
const live = document.getElementById('live');
const liveSrc = new URL('index.m3u8', socials.live.link).toString();
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
// resize iframe if view width is smaller than frame
2024-05-03 04:47:14 +00:00
if (parseInt(live.width, 10) > vw) {
2024-05-05 22:52:18 +00:00
live.width = `${vw}px`;
live.height = `${vw * (9 / 16)}px`;
}
2024-05-08 03:25:03 +00:00
(function loadStream() {
// remove stream if embedded
if (window.self !== window.top) {
live.remove();
return;
}
if (Hls.isSupported()) {
const hls = new Hls({
maxLiveSyncPlaybackRate: 1.5,
});
2024-05-08 03:25:03 +00:00
hls.on(Hls.Events.ERROR, (event, data) => {
if (data.fatal) {
live.style.display = 'none';
hls.destroy();
}
setTimeout(loadStream, 5000);
});
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
hls.loadSource(liveSrc);
});
hls.on(Hls.Events.MANIFEST_PARSED, () => {
live.style.display = 'inline';
live.play();
});
hls.attachMedia(live);
} else if (live.canPlayType('application/vnd.apple.mpegurl')) {
fetch(liveSrc)
.then(() => {
live.src = liveSrc;
live.play();
});
}
})();
// animated anchors
2024-05-08 03:25:03 +00:00
const minSpeed = 10;
const maxSpeed = 20;
let anchors = 0;
const maxAnchors = Math.floor(vw / 30);
function animateAnchor(anchor) {
let flag = parseInt(anchor.style.left, 10);
setInterval(() => {
2024-05-08 03:25:03 +00:00
anchor.style.left = `${--flag}px`;
2024-05-08 03:25:03 +00:00
if (anchor.offsetWidth <= -flag) {
flag = vw + Math.floor(anchor.offsetWidth / 2);
let posy = Math.floor(Math.random() * vh) - Math.floor(anchor.offsetHeight / 2);
anchor.style.top = `${posy}px`;
2022-10-27 19:21:06 +00:00
}
2024-05-08 03:25:03 +00:00
}, Math.floor(Math.random() * (maxSpeed - minSpeed) + minSpeed));
}
2022-10-27 19:21:06 +00:00
function createAnchor(link, content) {
2024-05-08 03:25:03 +00:00
if (anchors >= maxAnchors) {
return;
2022-10-27 19:21:06 +00:00
}
2024-05-08 03:25:03 +00:00
const anchor = document.createElement('a');
anchor.href = link;
anchor.target = '_blank';
anchor.innerHTML = content;
const posTop = Math.floor(Math.random() * vh) - Math.floor(anchor.offsetHeight / 2);
const posLeft = Math.floor(Math.random() * vw) - Math.floor(anchor.offsetWidth / 2);
let zIndex = Math.floor(anchors - maxAnchors / 2);
zIndex = (zIndex >= 0) ? zIndex + 1 : zIndex;
anchor.style.position = 'absolute';
anchor.style.top = `${posTop}px`;
anchor.style.left = `${posLeft}px`;
anchor.style.zIndex = `${zIndex}`;
document.body.prepend(anchor);
++anchors;
animateAnchor(anchor);
}
// Always have socials
2024-05-08 03:25:03 +00:00
while (anchors < maxAnchors / 4) {
for (const key in socials) {
createAnchor(socials[key].link, socials[key].text);
2022-10-27 19:21:06 +00:00
}
}
// feed
fetch(`${socials.feed.link}.rss`)
.then(response => response.text())
.then(str => new DOMParser().parseFromString(str, 'text/xml'))
.then(data => {
const items = data.querySelectorAll('item');
items.forEach(element => {
2024-05-03 04:06:18 +00:00
const text = document.createElement('p');
text.innerHTML = (element.getElementsByTagName('content:encoded')[0] ?? element.getElementsByTagName('title')[0]).textContent;
createAnchor(element.querySelector('link').innerHTML, text.outerHTML);
2022-10-27 19:21:06 +00:00
});
});
// code + helpers
function absoluteURL(data, query, url) {
data.querySelectorAll(query).forEach(element => {
element.setAttribute('href', new URL(element.getAttribute('href'), url));
element.removeAttribute('rel');
});
return data;
}
function htmlDecode(input) {
let doc = new DOMParser().parseFromString(input, 'text/html');
doc = new DOMParser().parseFromString(doc.documentElement.textContent, 'text/html');
return doc;
}
fetch(`${socials.code.link}.atom`)
.then(response => response.text())
.then(str => new DOMParser().parseFromString(str, 'text/xml'))
.then(data => {
data = absoluteURL(data, 'link', socials.code.link);
const items = data.querySelectorAll('entry');
items.forEach(element => {
const title = absoluteURL(htmlDecode(element.querySelector('title').innerHTML), 'a', socials.code.link);
createAnchor(element.querySelector('link').getAttribute('href'), title.body.innerHTML);
2022-10-27 19:21:06 +00:00
});
});
</script>
2022-10-27 19:21:06 +00:00
</body>
</html>