iamerrorgenerator/public/index.html
2021-09-21 23:35:42 -07:00

242 lines
5.9 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>I AM ERROR.</title>
<link rel="icon" type="image/png" href="zelda2-error.png" />
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="I AM ERROR. image generator"/>
<meta property="og:description" content="I AM ERROR. image generator"/>
<meta property="og:title" content="I AM ERROR."/>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: sans-serif;
font-size: 16px;
background-color: #2a2a2a;
color: white;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAAAAABzQ+pjAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAUSURBVAjXY9Rk5GBi+vuPhZ2FEQANXQJDZcY4EgAAAABJRU5ErkJggg==');
background-repeat: repeat;
}
h1 {
text-align: center;
font-size: 1rem;
margin: 1rem 0;
}
canvas {
display: none;
}
.render {
box-shadow:
0 0 1px black,
2px 2px 5px rgba(0, 0, 0, 0.75);
border: 2px solid white;
display: inline-block;
}
.render img {
display: block;
}
.container {
text-align: center;
}
@font-face {
font-family: "Zelda II: The Adventure of Link";
src: url("./font/zelda-ii-the-adventure-of-link.ttf");
}
.iamerror-text {
font-family: "Zelda II: The Adventure of Link", sans-serif;
text-shadow: 2px 2px #4240FF;
color: white;
}
label {
display: block;
margin-bottom: 10px;
}
#text {
width: 256px;
height: 150px;
background-color: black;
border: 4px double white;
padding: 2px 10px;
}
</style>
</head>
<body>
<h1><span class="iamerror-text">I AM ERROR GENERATOR.</span></h1>
<div class="container">
<div class="render">
<img width="256" height="240" />
</div>
<canvas id="iamerror" width="256" height="240"></canvas>
<p>
<textarea id="text" class="iamerror-text" placeholder="I AM ERROR." autofocus maxlength="40"></textarea>
</p>
</div>
<script>
(function() {
const colors = {
text: '#FFFFFF',
textShadow: '#4240FF',
background: '#000000',
};
const dimensions = {
left: 127,
top: 63,
width: 80,
height: 52,
};
const samples = [
'i am error.',
'can i eat your ham?',
'the crow flies at midnight.',
'pull my finger.',
'say hi to dark link for me.',
'are you my mother?',
'you shall not pass.',
'it smells like updog in here.',
'i like mary poppins.',
'oh my god, becky.',
'there is a bustle in my hedgerow.',
'you are the man now, dog.',
'want to see a magic trick?',
'yarp.',
'narp?',
'love is the last bastion of hope.',
'my beard is quite luxurious.',
'it is the springtime of my loving.',
'would you have any grey poupon?',
'come with me if you want to live.',
'my tummy feels funny.',
'are you still touching me?',
'your sound card works perfectly.',
'life is pain.',
'say hello to my little friend.',
'please do not make fun of my shirt.',
'bagu? what a terrible name.',
'i thought you were left- handed?',
];
const charWidth = 8;
const charHeight = charWidth;
const lineHeight = charHeight;
const charsPerLine = Math.floor(dimensions.width / charWidth);
const maxLines = Math.floor(dimensions.height / (charHeight + lineHeight));
const templateImg = document.createElement('img');
templateImg.src = './iamerror-template.png';
const canvas = document.querySelector('#iamerror');
const ctx = canvas.getContext('2d');
let imageLoaded = false;
const render = () => {
const text = input.value || samples[Math.floor(Math.random() * samples.length)];
const width = canvas.width;
const height = canvas.height;
ctx.clearRect(0, 0, width, height);
ctx.drawImage(templateImg, 0, 0, width, height);
ctx.font = '7px "Zelda II: The Adventure of Link"';
ctx.textBaseline = 'middle';
const words = text.split(' ').map(word => word.trim());
let lineNum = 0;
let charPos = 0;
while (words.length) {
let word = words.shift();
if (charPos > 0 && charPos + word.length + 1 > charsPerLine) {
// word goes on next line
charPos = 0;
lineNum++;
}
if (charPos > 0) {
word = ' ' + word;
}
const fragments = [ '' ];
let index = 0;
for (let i = 0; i < word.length; i++) {
if (fragments[index].length >= charsPerLine) {
index++;
fragments[index] = '';
}
fragments[index] += word[i];
}
for (const fragment of fragments) {
if (lineNum > maxLines) {
break;
}
const x = dimensions.left + (charPos * charWidth);
const y = dimensions.top + (lineNum * (charHeight + lineHeight));
ctx.fillStyle = colors.textShadow;
ctx.fillText(fragment, x + 1, y + 1);
ctx.fillStyle = colors.text;
ctx.fillText(fragment, x, y);
charPos += fragment.length;
if (charPos >= charsPerLine) {
charPos = 0;
lineNum++;
}
}
}
document.querySelector('.render img').src = canvas.toDataURL('img/png');
};
const input = document.querySelector('#text');
input.addEventListener('input', () => {
if (imageLoaded && fontLoaded) {
render();
}
});
let fontLoaded = false;
templateImg.addEventListener('load', () => {
imageLoaded = true;
if (fontLoaded) {
setTimeout(render, 1);
}
});
const font = new FontFace('"Zelda II: The Adventure of Link"', `url(./font/zelda-ii-the-adventure-of-link.ttf)`);
font.load()
.then(() => {
fontLoaded = true;
if (imageLoaded) {
setTimeout(render, 1);
}
})
.catch((err) => {
console.error('failed to load custom font', err);
});
}());
</script>
</body>
</html>