<!DOCTYPE html>
<html>
<head>
<script src="/content/b6a50f5ba932b0ea7f652d9d28e59eced47bc6f8376c25e02d8b3457bb60ac8fi0"></script>
<!-- artwork by @dmtbillythecats -->
<style>
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
height: 100%;
background-color: #f0f0f0;
overflow: auto;
}
#controls {
width: 100%;
background-color: rgba(255, 255, 255, 0.8);
box-sizing: border-box;
z-index: 10;
position: absolute;
top: 0;
}
#canvas-container {
flex: 1;
width: 100%;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="controls">
<input id="blk" type="number" placeholder="Enter block number" style="display: none;" />
</div>
<div id="canvas-container"></div>
<script>
let canvas;
let blockNumber = 1;
let scaleFactor = 1;
let btcColor;
function setup() {
let canvasSize = min(windowWidth, windowHeight);
canvas = createCanvas(canvasSize, canvasSize);
canvas.parent('canvas-container');
noLoop();
generateArt();
document.getElementById('blk').value = blockNumber;
document.getElementById('blk').addEventListener('input', updateArt);
window.addEventListener('resize', resize, true);
resize();
let mintText = document.getElementById('preview').getAttribute('mint');
if (mintText.includes('MINT_INSCRIPTION_ID')) {
let input = document.getElementById('blk');
input.style.display = 'block';
input.style.position = 'absolute';
input.style.fontSize = '10px';
input.style.margin = '1px';
input.style.top = '0';
input.value = blockNumber;
input.addEventListener('input', () => {
blockNumber = parseInt(input.value) || 1;
updateArt();
});
updateArt();
} else {
const request = new XMLHttpRequest();
try {
request.open('GET', '/content/' + mintText);
request.responseType = 'text';
request.addEventListener('load', () => initialize(request.response));
request.addEventListener('error', () => console.error('XHR error'));
request.send();
} catch (error) {
console.error(`XHR error ${error}`);
}
}
}
function initialize(result) {
if (result) {
try {
console.log('Result', result);
const data = JSON.parse(result);
blockNumber = data.blk;
updateArt();
} catch (error) {
console.error('JSON parsing error', error);
}
}
}
function updateArt() {
blockNumber = parseInt(document.getElementById('blk').value) || 1;
btcColor = getColorFromBlockNumber(blockNumber);
generateArt();
}
function resize() {
let canvasSize = min(windowWidth, windowHeight);
resizeCanvas(canvasSize, canvasSize);
const root = document.getElementById('canvas-container');
root.style.width = window.innerWidth - 300 + 'px';
root.style.height = window.innerHeight + 'px';
const orgWidth = 300;
const orgHeight = 300;
let scaleW = window.innerWidth / orgWidth;
let scaleH = window.innerHeight / orgHeight;
let offsetX = 0;
let offsetY = 0;
if (scaleH < scaleW) {
scaleW = scaleH;
offsetX = (window.innerWidth - orgWidth * scaleW) / 2;
} else {
scaleH = scaleW;
offsetY = (window.innerHeight - orgHeight * scaleH) / 2;
}
canvas.style.zoom = scaleW;
scaleFactor = Math.min(width / 1000, height / 1000);
redraw();
updateArt();
}
function generateArt() {
clear();
let bgColor = color(220, 220, 220);
background(bgColor);
btcColor = getColorFromBlockNumber(blockNumber);
NotebookCover(width / 2, height / 2, width * 0.7, height * 0.85);
Title(width / 2, height * 0.25);
BitcoinLogo(width / 2, height * 0.45, width * 0.2);
TextDetails(width / 2, height * 0.6);
DecorativeElements();
CanvasBorder();
DecorativeBorders();
}
function getColorFromBlockNumber(blockNumber) {
let r = (blockNumber * 37) % 256;
let g = (blockNumber * 73) % 256;
let b = (blockNumber * 97) % 256;
return color(r, g, b);
}
function DecorativeBorders() {
stroke(100, 100, 100);
strokeWeight(2);
noFill();
line(width * 0.1, height * 0.1, width * 0.9, height * 0.1);
line(width * 0.1, height * 0.1, width * 0.1, height * 0.9);
line(width * 0.9, height * 0.1, width * 0.9, height * 0.9);
line(width * 0.1, height * 0.9, width * 0.9, height * 0.9);
}
function CanvasBorder() {
noFill();
stroke(255, 165, 0); // Orange
strokeWeight(75);
rect(0, 0, width, height);
}
function NotebookCover(x, y, w, h) {
noStroke();
fill(0, 0, 0, 30);
rect(x - w/2 + 10, y - h/2 + 10, w, h, 10);
fill(255);
stroke(100);
strokeWeight(2);
rect(x - w/2, y - h/2, w, h, 10);
fill(200);
noStroke();
rect(x - w/2 - 10, y - h/2, 20, h, 5);
let ringCount = 12;
let ringSpacing = h / (ringCount + 1);
for (let i = 0; i < ringCount; i++) {
let ringY = y - h / 2 + ringSpacing * (i + 1);
BindingRing(x - w/2 - 10, ringY, ringSpacing * 0.6);
}
let lineSpacing = h / 25;
stroke(200);
strokeWeight(1);
for (let i = 0; i < 25; i++) {
let lineY = y - h / 2 + lineSpacing * (i + 1);
line(x - w / 2 + 30, lineY, x + w / 2 - 30, lineY);
}
}
function BindingRing(x, y, size) {
stroke(100);
strokeWeight(2);
fill(220);
ellipse(x, y, size, size * 1.2);
}
function Title(x, y) {
textAlign(CENTER, CENTER);
textSize(width * 0.04);
fill(50);
noStroke();
textStyle(BOLD);
text("Bitcoin:", x, y - 20);
textSize(width * 0.035);
textStyle(NORMAL);
text("A Peer-to-Peer Electronic", x, y + 10);
text("Cash System", x, y + 40);
}
function BitcoinLogo(x, y, size) {
push();
translate(x, y);
rotate(-PI/12);
fill(0, 0, 0, 50);
noStroke();
ellipse(5, 5, size * scaleFactor, size * scaleFactor);
fill(btcColor);
noStroke();
ellipse(0, 0, size * scaleFactor, size * scaleFactor);
fill(255);
textSize(size * 0.8 * scaleFactor);
textAlign(CENTER, CENTER);
textStyle(BOLD);
text('\u20BF', 0, size * 0.05 * scaleFactor);
pop();
}
function TextDetails(x, y) {
textAlign(CENTER, TOP);
textSize(width * 0.025);
fill(80);
let textDetails = [
"By Satoshi Nakamoto",
"Published: October 31, 2008",
"20081031"
];
let yOffset = y;
let lineHeight = height * 0.05;
for (let i = 0; i < textDetails.length; i++) {
text(textDetails[i], x, yOffset);
yOffset += lineHeight;
}
}
function DecorativeElements() {
stroke(200);
strokeWeight(1);
noFill();
let circleCount = 8;
let circleSize = width * 0.03;
let startX = width * 0.1;
let endX = width * 0.9;
let y = height * 0.85;
for (let i = 0; i < circleCount; i++) {
let x = map(i, 0, circleCount - 1, startX, endX);
ellipse(x, y, circleSize);
if (i < circleCount - 1) {
line(x + circleSize/2, y, x + (endX - startX)/(circleCount-1) - circleSize/2, y);
}
}
}
window.addEventListener('load', setup);
</script>
<script id="preview" mint="MINT_INSCRIPTION_ID"></script>
</body>
</html>