Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Created May 29, 2019 18:40
Show Gist options
  • Save mattdesl/e956aaf557f8ab349c690560ca504e05 to your computer and use it in GitHub Desktop.
Save mattdesl/e956aaf557f8ab349c690560ca504e05 to your computer and use it in GitHub Desktop.

canvas-sketch + hooks test

Inspired by React hooks, seeing how it could work within canvas-sketch.

The hooks.js includes some limited features (mostly just registering unload() event and passing props to hooks), and also exports three basic hook examples: MousePosition, GUI, and KeyPress.

const {
canvasSketch,
GUI,
MousePosition
} = require('./hooks');
const settings = {
animate: true,
scaleToView: true,
dimensions: [512, 512]
};
const sketch = ({ register }) => {
// Returns current mouse position as [ x, y ] array in working units
const mouse = register(MousePosition);
// Attaches GUI parameters to the sketch
const params = register(GUI, {
background: '#e1e1e1',
foreground: 'tomato',
radius: GUI.Number(50, 0.5, 100, 0.001),
fill: true
});
return ({ context, width, height }) => {
// Draw background
context.fillStyle = params.background;
context.fillRect(0, 0, width, height);
// Draw a circle at mouse position
context.fillStyle = params.foreground;
context.strokeStyle = params.foreground;
context.beginPath();
context.arc(mouse[0], mouse[1], params.radius, 0, Math.PI * 2);
context.lineWidth = width * 0.01;
if (params.fill) context.fill();
else context.stroke();
};
};
canvasSketch(sketch, settings);
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.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.render && r.render(props));
if (typeof renderer === 'function') return renderer(props);
else if (renderer && typeof renderer.render === 'function') return renderer.render(props);
},
unload (props) {
registered.forEach(r => r.unload && r.unload(props));
if (renderer && typeof renderer.unload === 'function') return renderer.unload(props);
}
};
};
return canvasSketch(sketchImpl, settings);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment