-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7c8ffd3
Showing
7 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"htmlWhitespaceSensitivity": "css", | ||
"singleQuote": true, | ||
"bracketSameLine": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |