Last active
May 30, 2019 21:13
-
-
Save mattdesl/230d151530e9e62488a14e5205f46173 to your computer and use it in GitHub Desktop.
see this gist for 'hooks.js' dependency: https://gist.github.com/mattdesl/e956aaf557f8ab349c690560ca504e05
This file contains hidden or 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
const { | |
canvasSketch, | |
GUI, | |
KeyPress, | |
FaviconRenderer | |
} = require('./hooks'); | |
const settings = { | |
animate: true, | |
scaleToView: true, | |
fps: 30, | |
duration: 4, | |
dimensions: [64, 64] | |
}; | |
const sketch = ({ register }) => { | |
// Register key presses | |
const keyPress = register(KeyPress); | |
// Register GUI controls | |
const params = register(GUI, { | |
background: '#000' | |
}); | |
// Render into favicon | |
register(FaviconRenderer); | |
return ({ context, width, height, playhead }) => { | |
// Clear background | |
context.clearRect(0, 0, width, height); | |
// Draw circle | |
const radius = Math.min(width, height) * 0.5; | |
context.fillStyle = params.background; | |
context.beginPath(); | |
context.arc(width / 2, height / 2, radius, 0, Math.PI * 2); | |
context.fill(); | |
// Draw letter | |
context.font = `${width * 0.65}px "Andale Mono"`; | |
context.textBaseline = 'middle'; | |
context.textAlign = 'center'; | |
context.fillStyle = 'white'; | |
context.save(); | |
context.translate(width / 2, height / 2); | |
context.rotate(playhead * Math.PI * 2); | |
context.fillText(keyPress.key || 'a', 0, 0); | |
context.restore(); | |
}; | |
}; | |
canvasSketch(sketch, settings); |
This file contains hidden or 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
const dat = require('dat.gui'); | |
const Color = require('canvas-sketch-util/color'); | |
const canvasSketch = require('canvas-sketch'); | |
module.exports.GUI = GUI; | |
function GUI (props, opt) { | |
const gui = new dat.GUI(); | |
const output = {}; | |
Object.keys(opt).forEach(key => { | |
let control = opt[key]; | |
const parsedColor = Color.parse(control); | |
if (parsedColor != null) { | |
control = { | |
type: 'color', | |
value: parsedColor.hex | |
}; | |
} | |
let field; | |
if (control && control.type) { | |
if (control.type === 'color') { | |
output[key] = control.value; | |
field = gui.addColor(output, key); | |
} else if (control.type === 'number') { | |
output[key] = control.value; | |
field = gui.add(output, key, control.min, control.max, control.step); | |
} | |
} else { | |
output[key] = control; | |
field = gui.add(output, key); | |
} | |
field.onChange(() => { | |
props.update(); | |
}); | |
}); | |
return { | |
output, | |
unload () { | |
console.log('destroy') | |
gui.destroy(); | |
} | |
}; | |
} | |
GUI.Color = (value = 'black') => { | |
return { | |
type: 'color', | |
value | |
}; | |
}; | |
GUI.Number = (value = 0, min = -Infinity, max = Infinity, step = 0.001) => { | |
return { | |
type: 'number', | |
value, | |
min, | |
max, | |
step | |
}; | |
}; | |
module.exports.FaviconRenderer = FaviconRenderer; | |
function FaviconRenderer (props) { | |
// TODO: gotta make this cleanup on unload() | |
const link = document.createElement('link'); | |
link.setAttribute('rel', 'icon'); | |
link.setAttribute('type', 'image/ico'); | |
document.head.appendChild(link); | |
update(props); | |
return { | |
postRender (props) { | |
update(props); | |
} | |
}; | |
function update (props) { | |
link.setAttribute('href', props.canvas.toDataURL('image/png')); | |
} | |
} | |
module.exports.KeyPress = KeyPress; | |
function KeyPress (props, defaultKey) { | |
const output = { | |
key: undefined, | |
...defaultKey | |
}; | |
window.addEventListener('keypress', keypress); | |
return { | |
output, | |
unload () { | |
window.removeEventListener('keypress', keypress); | |
} | |
}; | |
function keypress (ev) { | |
output.key = ev.key; | |
props.update(); | |
} | |
} | |
module.exports.MousePosition = MousePosition; | |
function MousePosition (props) { | |
const output = [ 0, 0 ]; | |
const element = props.canvas; | |
element.addEventListener('mousemove', update); | |
return { | |
output, | |
unload () { | |
element.removeEventListener('mousemove', update); | |
} | |
}; | |
function update (ev) { | |
const rect = props.canvas.getBoundingClientRect(); | |
output[0] = (ev.clientX - rect.left) / props.styleWidth * props.width; | |
output[1] = (ev.clientY - rect.top) / props.styleHeight * props.height; | |
props.update(); | |
} | |
} | |
module.exports.canvasSketch = (sketch, settings) => { | |
const sketchImpl = async (props) => { | |
const registered = []; | |
const register = (plugin, ...args) => { | |
const impl = plugin(props, ...args) || {}; | |
registered.push(impl); | |
return impl.output; | |
}; | |
props.register = register; | |
const renderer = await sketch(props); | |
return { | |
render (props) { | |
registered.forEach(r => r.preRender && r.preRender(props)); | |
let ret; | |
if (typeof renderer === 'function') ret = renderer(props); | |
else if (renderer && typeof renderer.render === 'function') ret = renderer.render(props); | |
registered.forEach(r => r.postRender && r.postRender(props)); | |
return ret; | |
}, | |
unload (props) { | |
registered.forEach(r => r.unload && r.unload(props)); | |
if (renderer && typeof renderer.unload === 'function') return renderer.unload(props); | |
registered.forEach(r => r.unloaded && r.unloaded(props)); | |
} | |
}; | |
}; | |
return canvasSketch(sketchImpl, settings); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment