Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
vhf committed Apr 2, 2024
0 parents commit 7c8ffd3
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 0 deletions.
Empty file added .nojekyll
Empty file.
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"htmlWhitespaceSensitivity": "css",
"singleQuote": true,
"bracketSameLine": false
}
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# objkt.com generative art snippet

This repo tracks the development of [objkt.com](https://objkt.com)'s generative art snippet.

The generative art snippet is a small JavaScript script that artists include in their generators.
It provides utilities to generate random numbers based on a seed, interface with objkt.com to capture previews, etc.
19 changes: 19 additions & 0 deletions generator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<script src="./snippet.js"></script>
<script src="./generator.js"></script>
<style>
#my-canvas {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="my-canvas" width="300" height="300"></canvas>
</body>
</html>
61 changes: 61 additions & 0 deletions generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
let canvas;

document.addEventListener('DOMContentLoaded', () => {
initialize();
});

function initialize() {
canvas = document.getElementById('my-canvas');

window.addEventListener('resize', () => draw(), false);
draw();
}

function draw(width = window.innerWidth, height = window.innerHeight) {
canvas.width = width;
canvas.height = height;

const ctx = canvas.getContext('2d');

ctx.clearRect(0, 0, width, height);

ctx.fillStyle = 'lightgreen';
ctx.strokeStyle = 'black';
ctx.fillRect(0, 0, width, height);
ctx.save();

ctx.ellipse(
width / 2,
height / 2,
width / 6,
width / 8,
Math.PI / 4,
0,
2 * Math.PI
);
ctx.fillStyle = 'lightblue';
ctx.fill();
ctx.stroke();

// here's how the artist must trigger the capture, it will use the `default` exporter with the provided resolution
$objkt.capture();
}

async function pngExport({ resolution: { x: x, y: y } }) {
draw(x, y);
const blob = await new Promise((resolve) => {
canvas.toBlob((blob) => resolve(blob), 'image/png');
});
draw();

return new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}

$objkt.registerExport(
{ mime: 'image/png', resolution: { x: 1024, y: 1024 }, default: true },
pngExport
);
42 changes: 42 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!-- the "host" page, showing a generator in an iframe -->
<!DOCTYPE html>
<html>
<head>
<style>
iframe {
width: 100%;
height: 80vh;
border: 2px dashed brown;
}
</style>
<script>
const exporters = [];

function registerExport(exporter) {
createExporter(exporter);
exporters.push(exporter);
}

function createExporter(exporter) {
const button = document.createElement('button');
button.textContent = `Export ${exporter.mime}, res: ${exporter.resolution.x}x${exporter.resolution.y}`;
document.body.appendChild(button);

button.onclick = async () => {
const link = document.createElement('a');
link.download = `image.${exporter.mime.split('/')[1]}`;

exporter.fn(exporter).then((dataURL) => {
link.href = dataURL;
link.click();
});
};
}
</script>
</head>
<body>
<p>Here's a sample generator in an iframe:</p>
<iframe id="generator" src="./generator.html"></iframe>
<p>Here are the exporters it registered:</p>
</body>
</html>
43 changes: 43 additions & 0 deletions snippet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// the JS snippet provided by objkt, to be included by the artist in their generators
const query = new URLSearchParams(window.location.search);

const $objkt = {
version: '0.0.1',
registerExport,
_exports: {},
_exported: {},
isCapture() {
return query.has('capture');
},
capture,
};
window.$objkt = $objkt;

function registerExport(args, fn) {
const err = new Error(`Cannot register export for ${JSON.stringify(args)}`);
if (typeof fn !== 'function') throw err;
if (typeof args?.mime !== 'string') throw err;
if ($objkt._exports[args.mime]) throw err;

$objkt._exports[args.mime] = { ...args, fn };

if (parent && parent.registerExport) {
parent.registerExport($objkt._exports[args.mime]);
}

return true;
}

async function capture(args) {
if ($objkt.isCapture()) {
const exporter = Object.values(this._exports).find(
(o) => o.default === true
);
if (!exporter) throw new Error(`No default exporter found`);
const exported = await exporter.fn(args);

$objkt._exported = { mime: exporter.mime, exported };
window.dispatchEvent(new Event('exported'));
console.log('exported', exported);
}
}

0 comments on commit 7c8ffd3

Please sign in to comment.