Compare commits
10 Commits
fcc9ccb713
...
75e2e10fad
Author | SHA1 | Date |
---|---|---|
Luca | 75e2e10fad | |
Luca | 1364fd793b | |
Luca | eec9d73e61 | |
Stefan Schwarz | fdd6674e15 | |
Florian Sorg | 48e4a254da | |
Luca | a009efe016 | |
Florian Sorg | b62b21df15 | |
Florian Sorg | 260560e753 | |
Stefan Schwarz | e35730d75c | |
Stefan Schwarz | eb30a69ab6 |
|
@ -33,12 +33,20 @@ body {
|
||||||
scroll,
|
scroll,
|
||||||
fixed;
|
fixed;
|
||||||
background-size:
|
background-size:
|
||||||
cover,
|
auto,
|
||||||
cover,
|
cover,
|
||||||
100% 100%,
|
100% 100%,
|
||||||
cover;
|
cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat:
|
||||||
background-position: center;
|
repeat-y,
|
||||||
|
no-repeat,
|
||||||
|
no-repeat,
|
||||||
|
no-repeat;
|
||||||
|
background-position:
|
||||||
|
50% calc(50% + 1px * 0.5 * var(--scrollTop, 0)),
|
||||||
|
50% 50%,
|
||||||
|
50% 50%,
|
||||||
|
50% 50%;
|
||||||
color: $color-text;
|
color: $color-text;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -60,6 +68,21 @@ body {
|
||||||
radial-gradient(transparent, transparent, rgba(0, 0, 0, 0.5));
|
radial-gradient(transparent, transparent, rgba(0, 0, 0, 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
opacity: 0.3;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
background-image: url('layout/fg_pixels.gif');
|
||||||
|
background-repeat: repeat-y;
|
||||||
|
background-position: 50% calc(50% + -1.4px * var(--scrollTop));
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: $small) {
|
@media (min-width: $small) {
|
||||||
background-image:
|
background-image:
|
||||||
url('layout/bg_pixels.gif'),
|
url('layout/bg_pixels.gif'),
|
||||||
|
@ -288,6 +311,9 @@ table {
|
||||||
.box-content {
|
.box-content {
|
||||||
padding: $gap-vertical $gap-horizontal;
|
padding: $gap-vertical $gap-horizontal;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.box-footer {
|
.box-footer {
|
||||||
padding: ($gap-vertical / 2) $gap-horizontal;
|
padding: ($gap-vertical / 2) $gap-horizontal;
|
||||||
|
@ -315,3 +341,31 @@ table {
|
||||||
.overflow-x-auto {
|
.overflow-x-auto {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.infobeamer {
|
||||||
|
h1 {
|
||||||
|
margin: $gap-vertical 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
max-width: 1700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-grid {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-auto-rows: minmax(10px, 1fr);
|
||||||
|
max-height: 75vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
@include aberration(0.1em);
|
||||||
|
border: 1px solid $color-box-frame;
|
||||||
|
height: 1em;
|
||||||
|
|
||||||
|
.fill {
|
||||||
|
background: $color-box-frame;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{ $currentPage := . }}
|
{{ $currentPage := . }}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ .Site.Language.Lang }}">
|
<html lang="{{ .Site.Language.Lang }}" style="--scrollTop: 0;">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
<link rel="icon" href="/franconianNet.svg" sizes="any" type="image/svg+xml">
|
<link rel="icon" href="/franconianNet.svg" sizes="any" type="image/svg+xml">
|
||||||
{{ $style := resources.Get "style.scss" | resources.ToCSS (dict "outputStyle" "compressed") }}
|
{{ $style := resources.Get "style.scss" | resources.ToCSS (dict "outputStyle" "compressed") }}
|
||||||
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
|
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
|
||||||
|
<script src="/layout/scroll.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -53,8 +53,6 @@
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const root = document.querySelector('html');
|
const root = document.querySelector('html');
|
||||||
textEl = document.querySelector('.text');
|
|
||||||
textEl.innerHTML = '';
|
|
||||||
|
|
||||||
if (window.location.search) {
|
if (window.location.search) {
|
||||||
const pairs = window.location.search.slice(1).split('&').map(x => x.split('='));
|
const pairs = window.location.search.slice(1).split('&').map(x => x.split('='));
|
||||||
|
@ -126,7 +124,7 @@
|
||||||
} else {
|
} else {
|
||||||
headline = talk.title;
|
headline = talk.title;
|
||||||
if (talk.persons) {
|
if (talk.persons) {
|
||||||
speaker = talk.persons.map(person => person.public_name).join(' / ');
|
speaker = talk.persons.map(person => person.public_name).join(', ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,164 +133,28 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (speaker && headline) {
|
const headlineEl = document.querySelector('.headline');
|
||||||
headline += ',';
|
headlineEl.innerHTML = '';
|
||||||
}
|
const speakerEl = document.querySelector('.speaker');
|
||||||
|
speakerEl.innerHTML = '';
|
||||||
|
|
||||||
const headlineEl = document.createElement('span');
|
console.log('headline', headline);
|
||||||
headlineEl.classList.add('headline');
|
console.log('speaker', speaker);
|
||||||
const speakerEl = document.createElement('span');
|
|
||||||
speakerEl.classList.add('speaker');
|
|
||||||
|
|
||||||
if (headline) {
|
if (headline) {
|
||||||
Array.from(headline).forEach(letter => {
|
headlineEl .innerText = headline;
|
||||||
const letterEl = document.createElement('span');
|
|
||||||
letterEl.classList.add('letter');
|
|
||||||
letterEl.innerText = letter;
|
|
||||||
headlineEl.appendChild(letterEl);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (speaker) {
|
if (speaker) {
|
||||||
Array.from(speaker).forEach(letter => {
|
speakerEl.innerText = speaker;
|
||||||
const letterEl = document.createElement('span');
|
|
||||||
letterEl.classList.add('letter');
|
|
||||||
letterEl.innerText = letter;
|
|
||||||
speakerEl.appendChild(letterEl);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
textEl.appendChild(headlineEl);
|
|
||||||
textEl.appendChild(document.createTextNode(' '));
|
|
||||||
textEl.appendChild(speakerEl);
|
|
||||||
|
|
||||||
const mainTilesEl = document.querySelector('.background .main-tiles');
|
|
||||||
mainTilesEl.innerHTML = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < 16; i++) {
|
|
||||||
const tile = document.createElement('div');
|
|
||||||
tile.classList.add('tile', 'large');
|
|
||||||
mainTilesEl.appendChild(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
const secondaryTilesEl = document.querySelector('.background .secondary-tiles');
|
|
||||||
secondaryTilesEl.innerHTML = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < 17; i++) {
|
|
||||||
const tile = document.createElement('div');
|
|
||||||
tile.classList.add('tile');
|
|
||||||
if (i === 0 || Math.random() > 0.5) {
|
|
||||||
tile.classList.add('medium');
|
|
||||||
} else {
|
|
||||||
tile.classList.add('small');
|
|
||||||
}
|
|
||||||
secondaryTilesEl.appendChild(tile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function animate() {
|
async function animate() {
|
||||||
if (autoIntro ? isFirstRun : isIntro) {
|
document.querySelector('.container').classList.add('visible');
|
||||||
await Promise.all([
|
|
||||||
slideIn(),
|
|
||||||
fadeInText(),
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
await Promise.all([
|
|
||||||
fadeIn(),
|
|
||||||
fadeInText(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, holdDuration * 1000));
|
await new Promise(r => setTimeout(r, holdDuration * 1000));
|
||||||
await Promise.all([
|
document.querySelector('.container').classList.remove('visible');
|
||||||
fadeOut(),
|
|
||||||
fadeOutText(),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
async function slideIn() {
|
|
||||||
const tiles = document.querySelectorAll('.tile');
|
|
||||||
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.style.animationName = `slide-in-${Math.floor(Math.random() * 10)}`;
|
|
||||||
tile.style.animationDelay = `${Math.random() * 0.4}s`;
|
|
||||||
tile.style.animationDuration = `${0.8 + Math.random() * 0.4}s`;
|
|
||||||
tile.style.animationIterationCount = '1';
|
|
||||||
tile.style.animationTimingFunction = 'ease-in';
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 600));
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.classList.add('visible');
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fadeIn() {
|
|
||||||
const tiles = document.querySelectorAll('.tile');
|
|
||||||
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.style.animationName = `fade-in`;
|
|
||||||
tile.style.animationDelay = `${Math.random() * 0.4}s`;
|
|
||||||
tile.style.animationDuration = `${0.8 + Math.random() * 0.4}s`;
|
|
||||||
tile.style.animationIterationCount = '1';
|
|
||||||
tile.style.animationTimingFunction = 'ease-in';
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 600));
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.classList.add('visible');
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fadeOut() {
|
|
||||||
const tiles = document.querySelectorAll('.tile');
|
|
||||||
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.style.animationName = `fade-out`;
|
|
||||||
tile.style.animationDelay = `${Math.random() * 0.4}s`;
|
|
||||||
tile.style.animationDuration = `${0.8 + Math.random() * 0.4}s`;
|
|
||||||
tile.style.animationIterationCount = '1';
|
|
||||||
tile.style.animationTimingFunction = 'ease-in';
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 600));
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.classList.remove('visible');
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fadeInText() {
|
|
||||||
const letters = document.querySelectorAll('.letter');
|
|
||||||
|
|
||||||
for (const letter of letters) {
|
|
||||||
letter.style.animationName = `fade-in`;
|
|
||||||
letter.style.animationDelay = `${Math.random() * 0.4}s`;
|
|
||||||
letter.style.animationDuration = `${0.8 + Math.random() * 0.4}s`;
|
|
||||||
letter.style.animationIterationCount = 1;
|
|
||||||
letter.style.animationTimingFunction = 'ease-in';
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 600));
|
|
||||||
for (const tile of letters) {
|
|
||||||
tile.classList.add('visible');
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fadeOutText() {
|
|
||||||
const letters = document.querySelectorAll('.letter');
|
|
||||||
|
|
||||||
for (const letter of letters) {
|
|
||||||
letter.style.animationName = `fade-out`;
|
|
||||||
letter.style.animationDelay = `${Math.random() * 0.4}s`;
|
|
||||||
letter.style.animationDuration = `${0.8 + Math.random() * 0.4}s`;
|
|
||||||
letter.style.animationIterationCount = '1';
|
|
||||||
letter.style.animationTimingFunction = 'ease-in';
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 600));
|
|
||||||
for (const tile of letters) {
|
|
||||||
tile.classList.remove('visible');
|
|
||||||
}
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cycle() {
|
async function cycle() {
|
||||||
|
|
|
@ -1,239 +1,60 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Orbitron;
|
font-family: Changa;
|
||||||
src: url('Orbitron-VariableFont_wght.ttf');
|
font-weight: 700;
|
||||||
|
src: url('Changa-SemiBold.ttf');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: SpaceMono;
|
||||||
|
src: url('SpaceMono-Regular.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--large-tile-color: #02fae0;
|
|
||||||
--medium-tile-color: #fff900;
|
|
||||||
--small-tile-color: #0bcb60;
|
|
||||||
--text-color: #252826;
|
|
||||||
--bottom: 9vw;
|
|
||||||
--left: 12.5vw;
|
|
||||||
--width: 67.5vw;
|
|
||||||
--top: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.theme-main {
|
|
||||||
--large-tile-color: #6800e7;
|
|
||||||
--medium-tile-color: #fff;
|
|
||||||
--small-tile-color: #05b9ec;
|
|
||||||
--text-color: #fff;
|
--text-color: #fff;
|
||||||
|
--header-text-color: #252826;
|
||||||
|
--frame-color: #fff;
|
||||||
|
--bottom: 7vw;
|
||||||
|
--left: 25vw;
|
||||||
|
--width: 50vw;
|
||||||
|
--top: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: #000;
|
background-color: #444;
|
||||||
font-family: Orbitron, sans-serif;
|
font-family: SpaceMono, monospace;
|
||||||
font-size: 2vw;
|
font-size: 1.7vw;
|
||||||
line-height: 2vw;
|
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
/*color: #0e1c23;*/
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.1vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.headline {
|
.headline {
|
||||||
font-weight: 900;
|
text-transform: lowercase;
|
||||||
|
font-family: Changa, sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
background: var(--frame-color);
|
||||||
|
color: var(--header-text-color);
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.3;
|
||||||
|
padding: 0 1vw;
|
||||||
|
font-size: 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.speaker {
|
.speaker {
|
||||||
font-size: 0.8em;
|
padding: 0.5vw 1vw 0.7vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
|
transition: opacity 0.3s ease 0s;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: var(--bottom);
|
bottom: var(--bottom);
|
||||||
left: var(--left);
|
left: var(--left);
|
||||||
width: var(--width);
|
width: var(--width);
|
||||||
top: var(--top);
|
top: var(--top);
|
||||||
}
|
border: 0.1vw solid var(--frame-color);
|
||||||
|
|
||||||
.background {
|
|
||||||
z-index: -20;
|
|
||||||
width: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
margin-left: 6.25%;
|
|
||||||
padding: 1vw 1.5vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tiles {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: stretch;
|
|
||||||
justify-content: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-tiles {
|
|
||||||
margin-left: 6.25%;
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tile {
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tile::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
display: block;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tile.large::before {
|
|
||||||
background-color: var(--large-tile-color);
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
box-shadow: 1px 0 0 0 var(--large-tile-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tile.medium::before {
|
|
||||||
background-color: var(--medium-tile-color);
|
|
||||||
width: 50%;
|
|
||||||
padding-top: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tile.small::before {
|
|
||||||
background-color: var(--small-tile-color);
|
|
||||||
width: 35%;
|
|
||||||
padding-top: 35%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.letter {
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.visible {
|
.visible {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slide-in-0 {
|
|
||||||
0% {
|
|
||||||
transform: translate(50vw, -100vw) scale(10);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-1 {
|
|
||||||
0% {
|
|
||||||
transform: translate(-40vw, -20vw) scale(2);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-2 {
|
|
||||||
0% {
|
|
||||||
transform: translate(50vw, 20vw) scale(5);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-3 {
|
|
||||||
0% {
|
|
||||||
transform: translate(80vw, -50vw) scale(3);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-4 {
|
|
||||||
0% {
|
|
||||||
transform: translate(-30vw, -50vw) scale(7.5);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-5 {
|
|
||||||
0% {
|
|
||||||
transform: translate(-30vw, 50vw) scale(4);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-6 {
|
|
||||||
0% {
|
|
||||||
transform: translate(5vw, 30vw) scale(2.5);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-7 {
|
|
||||||
0% {
|
|
||||||
transform: translate(-70vw, 100vw) scale(4);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-8 {
|
|
||||||
0% {
|
|
||||||
transform: translate(-4vw, 2vw) scale(2);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-9 {
|
|
||||||
0% {
|
|
||||||
transform: translate(2vw, -5vw) scale(2);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-in {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-out {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,17 +2,14 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Intro</title>
|
<title>Bauchbinde</title>
|
||||||
<link rel="stylesheet" href="./assets/style.css">
|
<link rel="stylesheet" href="./assets/style.css">
|
||||||
<script src="./assets/script.js"></script>
|
<script src="./assets/script.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="text"></div>
|
<div class="headline"></div>
|
||||||
<div class="background">
|
<div class="speaker"></div>
|
||||||
<div class="secondary-tiles tiles"></div>
|
|
||||||
<div class="main-tiles tiles"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<title>
|
||||||
|
Infobeamer
|
||||||
|
</title>
|
||||||
|
<link rel="stylesheet" href="/style.css">
|
||||||
|
<script>
|
||||||
|
main().then(() => console.log("loaded"));
|
||||||
|
|
||||||
|
function parseDuration(duration) {
|
||||||
|
if (!/^\d+:\d+$/.test(duration)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [hours, minutes] = duration.split(":");
|
||||||
|
return (hours * 60 * 60 + minutes * 60) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitize(unsafe) {
|
||||||
|
const element = document.createElement("div");
|
||||||
|
element.innerHTML = unsafe;
|
||||||
|
return element.innerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(talk) {
|
||||||
|
const now = Date.now();
|
||||||
|
const max = talk.end - talk.start;
|
||||||
|
|
||||||
|
let value = 0;
|
||||||
|
if (talk.start < now && talk.end > now) {
|
||||||
|
value = talk.end - now;
|
||||||
|
value = max - value
|
||||||
|
} else if (talk.end < now) {
|
||||||
|
value = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<li class="box">
|
||||||
|
<h2 class="box-header">${sanitize(talk.title)}</h2>
|
||||||
|
<div class="box-content clamp-height">
|
||||||
|
<p class="date">
|
||||||
|
Speakers: ${sanitize(talk.persons.join(", ") || "---")}<br>
|
||||||
|
Stage: ${sanitize(talk.room)}<br>
|
||||||
|
Time: ${sanitize(talk.start_string)}<br>
|
||||||
|
Duration: ${sanitize(talk.duration)}<br>
|
||||||
|
</p>
|
||||||
|
<p>${sanitize(talk.abstract)}</p>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
<div class="progress"><div class="fill" style="width: ${value / max * 100}%"></div></div>
|
||||||
|
</div>
|
||||||
|
</li>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const resp = await fetch("https://static.rc3.world/schedule/everything.json");
|
||||||
|
const schedule = await resp.json();
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
const upcoming = [];
|
||||||
|
for (const day of schedule.schedule.conference.days) {
|
||||||
|
for (const [channel, talks] of Object.entries(day.rooms)) {
|
||||||
|
for (const talk of talks) {
|
||||||
|
const talk_end = Date.parse(talk.date) + parseDuration(talk.duration);
|
||||||
|
if (talk_end > now) {
|
||||||
|
const parsed = {
|
||||||
|
start: Date.parse(talk.date),
|
||||||
|
date_string: talk.date,
|
||||||
|
end: talk_end,
|
||||||
|
start_string: talk.start,
|
||||||
|
duration: talk.duration,
|
||||||
|
room: talk.room,
|
||||||
|
title: talk.title,
|
||||||
|
abstract: talk.abstract,
|
||||||
|
persons: talk.persons.map(person => person.public_name),
|
||||||
|
};
|
||||||
|
upcoming.push(parsed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = "";
|
||||||
|
upcoming.sort((a, b) => a.end - b.end);
|
||||||
|
for (const talk of upcoming.slice(0, 6)) {
|
||||||
|
content += render(talk);
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = new Date();
|
||||||
|
|
||||||
|
document.getElementById("list").innerHTML = content;
|
||||||
|
const hours = `${time.getHours()}`.padStart(2, '0');
|
||||||
|
const minutes = `${time.getMinutes()}`.padStart(2, '0');
|
||||||
|
document.getElementById("time").innerText = `${hours}:${minutes}`;
|
||||||
|
|
||||||
|
setTimeout(main, (60-time.getSeconds())*1000+500);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="infobeamer">
|
||||||
|
<header>
|
||||||
|
<nav class="nav nav-main">
|
||||||
|
<a class="nav-logo" href="/">
|
||||||
|
<img src="/franconianNet.svg"
|
||||||
|
alt="Logo of franconian.net">
|
||||||
|
franconian.net
|
||||||
|
</a>
|
||||||
|
<a class="nav-link" id="time"></a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<h1>running / upcoming</h1>
|
||||||
|
<ul class="box-grid" id="list">
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Binary file not shown.
After Width: | Height: | Size: 765 KiB |
|
@ -0,0 +1 @@
|
||||||
|
window.addEventListener('scroll', e => document.documentElement.style.setProperty('--scrollTop', window.scrollY));
|
Loading…
Reference in New Issue