Skip to content

Instantly share code, notes, and snippets.

@BretHudson
Last active November 26, 2023 23:51
Show Gist options
  • Select an option

  • Save BretHudson/edceeaea0cd7511ade4b0592d59a2811 to your computer and use it in GitHub Desktop.

Select an option

Save BretHudson/edceeaea0cd7511ade4b0592d59a2811 to your computer and use it in GitHub Desktop.
Creating a "scoped" render that then undoes all the operations so you don't have to store temporary variables for an eventual reset
// whatever your canvas initialization code is
// just creating a canvas in JS and not putting in the DOM since this is just an example
const canvas = document.createElement('canvas');
const ctx = canvas.getContext("2d");
// get previous values
const prevFillStyle = ctx.fillStyle;
const prevFillStyle = ctx.strokeStyle;
// update the values
ctx.fillStyle = '#FFFFFF';
ctx.strokeStyle = '#FFFFFF';
// reset the values
ctx.fillStyle = prevFillStyle;
ctx.strokeStyle = prevStrokeStyle;
// whatever your canvas initialization code is
// just creating a canvas in JS and not putting in the DOM since this is just an example
const canvas = document.createElement('canvas');
const ctx = canvas.getContext("2d");
function scopedRender(ctx, func) {
const updates = {};
func(new Proxy(ctx, {
get: function (target, key) {
return target[key];
},
set: function (target, key, value) {
updates[key] ??= target[key];
target[key] = value;
return true;
}
}));
Object.entries(updates).forEach(([k, v]) => {
ctx[k] = v;
});
}
console.log('before scopedRender: ', ctx.fillStyle); // #000000
scopedRender(ctx, (ctx) => {
console.log('before set: ', ctx.fillStyle); // #000000
ctx.fillStyle = "#FFFFFF";
console.log('after set: ', ctx.fillStyle); // #FFFFFF
})
console.log('after scopedRender: ', ctx.fillStyle); // #000000
// whatever your canvas initialization code is
// just creating a canvas in JS and not putting in the DOM since this is just an example
const canvas = document.createElement('canvas');
const ctx = canvas.getContext("2d");
// First approach, allows for more flexibility but the setup would be messier
// I might come back and make this have access to all props without having to one-by-one define them
class Draw {
static stateStack = [];
static save() {
Draw.stateStack.push({});
}
static pop() {
const obj = Draw.stateStack.pop();
if (!obj) {
console.error('cannot pop an empty stack');
return;
}
Object.entries(obj).forEach(([k, v]) => {
ctx[k] = v;
});
}
static _storeProperty(k, v) {
const curState = Draw.stateStack.at(-1);
if (!curState) return;
curState[k] ??= ctx[k];
ctx[k] = v;
}
static setFill(color) {
Draw._storeProperty('fillStyle', color);
}
}
console.log('before save: ', ctx.fillStyle); // #000000
Draw.save();
console.log('before set: ', ctx.fillStyle); // #000000
Draw.setFill('#FFFFFF');
console.log('after set: ', ctx.fillStyle); // #FFFFFF
Draw.pop();
console.log('after pop: ', ctx.fillStyle); // #000000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment