mattdesl / canvas-sketch-util Goto Github PK
View Code? Open in Web Editor NEWUtilities for sketching in Canvas, WebGL and generative art
License: MIT License
Utilities for sketching in Canvas, WebGL and generative art
License: MIT License
Hey there!
I'd like to report a security issue but cannot find contact instructions on your repository.
If not a hassle, might you kindly add a SECURITY.md
file with an email, or another contact method? GitHub recommends this best practice to ensure security issues are responsibly disclosed, and it would serve as a simple instruction for security researchers in the future.
Thank you for your consideration, and I look forward to hearing from you!
(cc @huntr-helper)
Matt and community, I've tried for a few days now to ensure that I can regen an image based on a seed. Tell me why this scenario does NOT work:
I'm running this example from the /examples folder.
I CMD-R to refresh the images.
I see an image I like - I press CMD+S.
The browser saves the image with the seed as a suffix.
I go back, comment out line 5 and uncomment line 6, then adding the seed to line 6 below (see <----- comment)
I rerun with the hard-coded seed and get a different image than expected.
Have a misread the docs or am I doing something wrong? Thank you!
const canvasSketch = require('canvas-sketch');
const Random = require('canvas-sketch-util/random');
const { lerp } = require('canvas-sketch-util/math');
// We can force a random seed or a specific string/number
Random.setSeed(Random.getRandomSeed());
//Random.setSeed(340593); <--------
const settings = {
pixelsPerInch: 300,
// When exporting, use the seed as the suffix
// This way we can reproduce it more easily later
suffix: Random.getSeed(),
// Standard A4 paper size
dimensions: 'A4',
// We'll work in inches for the rendering
units: 'in'
};
const sketch = ({ width, height }) => {
const margin = 0;
const sliceCount = 50000;
const slices = Array.from(new Array(sliceCount)).map((_, i, list) => {
const t = list.lenth <= 1 ? 0 : i / (list.length - 1);
const noiseAngle = t * Math.PI * 2;
const nx = Math.cos(noiseAngle);
const ny = Math.sin(noiseAngle);
const nf = 0.05 + Random.range(0, 0.5);
const amplitude = 2;
const noise = Random.noise2D(nx * nf, ny * nf);
const noise01 = noise * 0.5 + 0.5;
const tOffset = Random.gaussian(0, 0.01);
const cx = width / 2;
const x = cx + noise * amplitude;
return {
alpha: Random.range(0.75, 1) * (1 - noise01),
color: 'white',
lineWidth: Random.range(0.005, 0.02) * 0.1,
length: Random.gaussian() * noise01 * 0.5,
angle: Random.gaussian(0, 1),
x,
y: lerp(margin, height - margin, t + tOffset)
};
});
return ({ context }) => {
context.globalCompositeOperation = 'source-over';
context.fillStyle = 'black';
context.fillRect(0, 0, width, height);
context.globalCompositeOperation = 'lighter';
slices.forEach(slice => {
context.save();
context.beginPath();
context.translate(slice.x, slice.y);
context.rotate(slice.angle);
context.lineTo(slice.length / 2, 0);
context.lineTo(-slice.length / 2, 0);
context.lineWidth = slice.lineWidth;
context.strokeStyle = slice.color;
context.globalAlpha = slice.alpha;
context.stroke();
context.restore();
});
};
};
canvasSketch(sketch, settings);
Hi,
thank you for the great work.
I see that I can use dynamic sketch props such as time
as a uniform,
but is there a way that I can create my own dynamic uniform that updates every frame?
What I ultimately want to do is to create array uniforms that update in the sketch and send them to the fragment shader that will update each frame.
I appreciate any help you might be able to give.
Below is a simple example code:
const canvasSketch = require("canvas-sketch");
const createShader = require("canvas-sketch-util/shader");
const glsl = require("glslify");
// Setup our sketch
const settings = {
dimensions: [800, 800],
context: "webgl",
animate: true,
duration: 3,
fps: 30,
};
// Your glsl code
const frag = glsl(/* glsl */ `
precision highp float;
varying vec2 vUv;
uniform float sizes[3];
float sdCircle( vec2 p, float r ) {
return length(p) - r;
}
void main () {
vec2 p = vec2(vUv);
p.y = 1.0 - p.y;
vec3 col = vec3(0.1);
for (int i = 0; i < 3; i++) {
float circ = sdCircle(p - vec2(0.25 + float(i)/4., 0.5), sizes[i] * 0.1);
circ = 1.0 - smoothstep(0.0, 0.05, circ);
col += circ;
}
gl_FragColor = vec4(col, 1.);
}
`);
// Your sketch, which simply returns the shader
const sketch = ({ gl, playhead }) => {
let sizes = [0.2, 0.5, 0.8];
// Q: how to update array values each frame and send as uniforms?
sizes = sizes.map((el) => Math.sin(el + playhead));
// regl does not take array uniforms at once, so this is a workaround..
const uniforms = {};
for (let i = 0; i < sizes.length; i++) {
uniforms[`sizes[${i}]`] = sizes[i];
}
return createShader({
gl,
frag,
uniforms: {
...uniforms,
},
});
};
canvasSketch(sketch, settings);
Hi Matt, thank you for canvas-sketch and the penplot helper! I was wondering if it's possible to export an SVG at a particular frame. E.g. I am trying to run a Matter.js simulation and want to pause the sketch at a certain frame and export it to SVG.
Not sure if this is an issue in canvas-sketch-util or arc implementation in d3-path. See example below:
๐ Hey @mattdesl. I've been doing some sketches with triangles recently and I might have some building blocks that would allow for a new random.onTriangle()
feature that will randomly choose n number of random points that fall on the side(s) of the triangle.
given:
a triangle with vertices A, B, and C similar to below.
A
/\
/ \
/ \
/ \
/ \
/ \
/ \
/ \
B /________________\ C
which is made of an array of three coordinate pairs
const triangle = [[xa,ya],[xb,yb],[xc,yc]]
or maybe an object?
const triangle = {
pointA: {
xa: 1,
ya: 0
},
pointB: {
xb: 0,
yb: 1
},
pointC: {
xc: 1,
yc: 1
}
};
choose n number of random points that fall on the side(s) of the triangle.
command:
[x, y] = random.onTriangle(triangle as object or array, n as number, s as int for side number)
valid arguments:
required
triangle object (as above)
optional
number of points to return
default = 1
optional
which "side" of the triangle
default = 0
side options:
future enhancement? 12 as valid argument (side 1 and side 2)
Does this sound like something you'd like to see in the library? If so, I'd love to help. (but I might need a little help helping ๐)
I've attached a gist of my penplot (excuse my long code, options are at the end) https://gist.github.com/typicalTYLER/3fc7b37a76051bb29898fec83ff84472
Basically when an svg is created, all of the collinear line segments that are laid end to end are not ordered/merged as I would expect them to be. (some examples below). This causes my plotter to pick up the pen in non-optimal spots.
A couple things I can think of, my lines might not be perfectly aligned (but I would imagine that my merge threshold would take care of this). Maybe lines get merged together once, but it doesn't keep merging after one loop through? And I don't quite fully understand the optimization code, so this may be expected behavior.
Hi @mattdesl, I've just been watching your Introduction to creative coding class on Frontend Masters, and noticed that when you're using this library your editor is giving you autocomplete and type annotations (pictured below). I've been looking around and can't see any type definitions in the library, is there a different way that you're getting these?
In penplot.js code there is this magic number for pixel per inch:
var DEFAULT_PIXELS_PER_INCH = 90;
Why this number?
Hey,
I just started using your library and was wondering if there was a umd version available from a cdn? I wrote my own little online code editor and was hoping to use your library in that environment here: https://contrived-dev.herokuapp.com/.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.