{"id":16513720,"url":"https://github.com/nitin42/generative-art-tools","last_synced_at":"2025-03-21T08:31:31.445Z","repository":{"id":57246270,"uuid":"164252550","full_name":"nitin42/generative-art-tools","owner":"nitin42","description":"Utilities for creating generative art","archived":false,"fork":false,"pushed_at":"2019-04-28T18:19:11.000Z","size":691,"stargazers_count":27,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-17T06:48:40.573Z","etag":null,"topics":["generative-art","graphics","javascript","reactjs","shaders","web"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nitin42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-05T21:28:22.000Z","updated_at":"2023-05-31T03:22:58.000Z","dependencies_parsed_at":"2022-08-24T16:10:46.594Z","dependency_job_id":null,"html_url":"https://github.com/nitin42/generative-art-tools","commit_stats":null,"previous_names":["nitin42/react-generative-tools"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitin42%2Fgenerative-art-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitin42%2Fgenerative-art-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitin42%2Fgenerative-art-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitin42%2Fgenerative-art-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nitin42","download_url":"https://codeload.github.com/nitin42/generative-art-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244765127,"owners_count":20506764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generative-art","graphics","javascript","reactjs","shaders","web"],"created_at":"2024-10-11T16:10:02.618Z","updated_at":"2025-03-21T08:31:29.685Z","avatar_url":"https://github.com/nitin42.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# generative-art-tools\n\n\u003e Utilities for creating generative art\n\n## Table of contents\n\n- [What](#what)\n- [Install](#install)\n- [Functions](#functions)\n  - [Processing (p5.js)](#processing-p5js)\n  - [Two.js](#twojs)\n  - [Shaders](#shaders)\n  - [random](#random)\n  - [Shaping functions](https://github.com/nitin42/generative-art-tools#shaping-functions)\n    - [Introduction](https://github.com/nitin42/generative-art-tools#reference)\n    - [gain](https://github.com/nitin42/generative-art-tools#gain)\n    - [impulse](https://github.com/nitin42/generative-art-tools#impulse)\n    - [parabola](https://github.com/nitin42/generative-art-tools#parabola)\n    - [sine curve](https://github.com/nitin42/generative-art-tools#sine)\n    - [power curve](https://github.com/nitin42/generative-art-tools#power)\n    - [exponential step](https://github.com/nitin42/generative-art-tools#exponential-step)\n    - [cubic pulse](https://github.com/nitin42/generative-art-tools#cubic-pulse)\n\n## What\n\n`generative-art-tools` is a collection of utility functions to create generative art. It provides -\n\n- a set of helper functions to create generative art using React\n\n- and math functions that can be use to animate the sketches\n\n## Install\n\n```bash\nnpm install --save generative-art-tools\n```\n\n## Functions\n\n### Processing (p5.js)\n\n```js\nimport { createP5Sketch } from \"generative-art-tools\";\n```\n\nRender p5.js sketches using React.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample usage\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { createP5Sketch } from \"generative-art-tools\";\n\nfunction sketch(p5Instance, componentProps, wrapperElement) {\n  let pause = true;\n\n  p5Instance.setup = function() {\n    p5Instance.createCanvas(500, 500);\n    p5Instance.noFill();\n    p5Instance.background(255);\n    p5Instance.stroke(0, 15);\n    p5Instance.frameRate(30);\n  };\n\n  p5Instance.mousePressed = function() {\n    pause = !pause;\n  };\n\n  p5Instance.draw = function() {\n    if (!pause) {\n      p5Instance.push();\n      p5Instance.translate(p5Instance.width / 2, p5Instance.height / 2);\n      p5Instance.rotate(p5Instance.frameCount);\n\n      const circleResolution = parseInt(\n        p5Instance.map(p5Instance.mouseY + 50, 0, p5Instance.height, 2, 10)\n      );\n      const radius = p5Instance.mouseX - p5Instance.width / 2;\n      const angle = (2 * Math.PI) / circleResolution;\n\n      p5Instance.beginShape();\n\n      for (let i = 0; i \u003c= circleResolution; i++) {\n        const x = Math.cos(angle * i) * radius;\n        const y = Math.sin(angle * i) * radius;\n\n        p5Instance.strokeWeight(i / 2);\n        p5Instance.vertex(x, y);\n      }\n\n      p5Instance.endShape(p5Instance.CLOSE);\n\n      p5Instance.pop();\n    }\n  };\n}\n\nconst Shapes = createP5Sketch(sketch);\n\nfunction App(props) {\n  return \u003cShapes id=\"Shapes\" /\u003e;\n}\n\nReactDOM.render(\u003cApp /\u003e, document.getElementById(\"element-id\"));\n```\n\n  \u003c/p\u003e\n\u003c/details\u003e\n\n**`createP5Sketch`**\n\n```js\ncreateP5Sketch(sketchFunction: (p5Instance: Object, props: Object wrapperEl: HTMLElement) =\u003e void) =\u003e ReactComponent\n```\n\nThis function accepts only one argument which is `p5.js` sketch function and returns a React component. The sketch function receives three parameters, the `p5.js` instance, the returned component's props and the wrapper element that wraps the sketch.\n\nThe returned React component accepts the following props -\n\n- `width` - Canvas width\n\n- `height` - Canvas height\n\n- `id` - A unique element id (useful if you're rendering multiple sketch components)\n\n- `callback: (p5Instance) =\u003e void` - A callback function that receives the p5.js instance. Use this callback to do some extra stuff with the sketch\n\n[![Edit 6z855jq5or](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/6z855jq5or?fontsize=14)\n\n### Two.js\n\n```js\nimport { createTwoJSDesign } from \"generative-art-tools\";\n```\n\nRender Two.js sketches using React\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample usage\u003c/summary\u003e\n  \u003cp\u003e\n\n```jsx\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { createTwoJSDesign, random } from \"generative-art-tools\";\n\nconst colors = {\n  CIRCLE_ONE: \"#ebedee\",\n  CIRCLE_TWO: \"#7f8a93\",\n  CIRCLE_THREE: \"#374047\"\n};\n\nconst drawCircle = (offset, color, instance) =\u003e {\n  const circles = [];\n\n  for (let x = 20; x \u003c= instance.width - 5; x += 15) {\n    const circle = instance.makeCircle(offset, x, random(0, 10));\n    circle.fill = color;\n    circle.stroke = \"#dee1e3\";\n\n    circles.push(circle);\n  }\n\n  return circles;\n};\n\nconst drawPattern = (instance, props) =\u003e {\n  let renderedCircles = [];\n\n  for (let x = 20; x \u003c= instance.width - 28; x += props.positionOffsetOne) {\n    renderedCircles.push(drawCircle(x, colors.CIRCLE_THREE, instance));\n    x += props.positionOffsetTwo;\n\n    renderedCircles.push(drawCircle(x, colors.CIRCLE_TWO, instance));\n    x += props.positionOffsetThree;\n\n    renderedCircles.push(drawCircle(x, colors.CIRCLE_ONE, instance));\n  }\n\n  return renderedCircles;\n};\n\nconst offsets = {\n  positionOffsetOne: 10,\n  positionOffsetTwo: 25,\n  positionOffsetThree: 30\n};\n\n// On each update/page refresh, it displaces the circles randomly\nconst renderCircles = (twoJSInstance, componentProps, wrapperElement) =\u003e {\n  const circles = drawPattern(twoJSInstance, offsets);\n\n  twoJSInstance.render();\n};\n\nconst Circles = createTwoJSDesign(renderCircles);\n\nfunction App(props) {\n  return \u003cCircles id=\"Shapes\" width={500} height={500} /\u003e;\n}\n\nReactDOM.render(\u003cApp /\u003e, document.getElementById(\"element-id\"));\n```\n\n  \u003c/p\u003e\n\u003c/details\u003e\n\n[![Edit w6j4vj2wv7](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/w6j4vj2wv7?fontsize=14)\n\n**`createTwoJSDesign`**\n\n```js\ncreateTwoJSDesign(sketchFunction: (twoJsInstance: Object, props: Object wrapperEl: HTMLElement) =\u003e void) =\u003e ReactComponent\n```\n\nThis function accepts only one argument, a `two.js` sketch function and it returns a React component.\n\nThe `two.js` sketch function receives three parameters. The `Two.js` instance, the returned component's props and the wrapper element that wraps the artwork.\n\nThe returned React component accepts the following props -\n\n- `width` - Canvas width\n\n- `height` - Canvas height\n\n- `id` - A unique element id (useful if you're rendering multiple sketch components)\n\n- `callback: (twoJSInstance) =\u003e void` - A callback function that receives the Two.js instance. Use this callback to do extra work with the sketch\n\n### Shaders\n\n```js\nimport { createShaderCanvas } from \"generative-art-tools\";\n```\n\nRender shaders using React\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample usage\u003c/summary\u003e\n  \u003cp\u003e\n\n```jsx\nimport React, { Component } from \"react\";\n\nimport { createShaderCanvas } from \"generative-art-tools\";\n\nconst shader = props =\u003e `\n  #ifdef GL_ES\n  precision mediump float;\n  #endif\n\n  uniform float u_time;\n  uniform vec2 u_mouse;\n  uniform vec2 u_resolution;\n  \n  float expStep( float x, float k, float n ){\n    return exp( -k*pow(x,n) );\n  }\n  \n  void main() {\n    vec2 point = gl_FragCoord.xy / u_resolution.xy;\n    float px = 1.0 / u_resolution.y;\n    vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;\n  \n    float l = expStep(point.x, ${props.timeSync ? \"cp.x * u_time\" : \"cp.x\"}, ${\n  props.timeSync ? \"cp.y * u_time\" : \"cp.y\"\n});\n    \n    vec3 color = vec3(smoothstep(l, l+px, point.y), sin(u_time), cos(cp.y) * 0.5);\n      \n    gl_FragColor = vec4(color, 1.0);\n  }\n`;\n\nconst ShaderComponent = createShaderCanvas(shader);\n\nclass App extends Component {\n  state = {\n    timeSync: false\n  };\n\n  updateState = e =\u003e this.setState(state =\u003e ({ timeSync: !state.timeSync }));\n\n  render() {\n    const { timeSync } = this.state;\n\n    return (\n      \u003cdiv onClick={this.updateState}\u003e\n        \u003cShaderComponent id=\"exponential-step-curve\" timeSync={timeSync} /\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\n  \u003c/p\u003e\n\u003c/details\u003e\n\n[![Edit wopqzj7o77](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/wopqzj7o77)\n\n**`createShaderCanvas`**\n\n```js\ncreateShaderCanvas(shader: (props) =\u003e string) =\u003e ReactComponent\n```\n\n`createShaderCanvas` takes a shader as an input and returns a React component which renders the shader. The shader function gets passed the component props.\n\nThe returned React component accepts the following props -\n\n- `id` (Required) - `id` of the canvas element. This is required to render the canvas\n\n- `height` (Optional) - height of the canvas.\n\n- `width` (Optional) - width of the canvas.\n\n- `style` (Optional) - canvas style.\n\n### Random\n\nReturns a random number between a range.\n\n```js\nimport { random } from \"generative-art-tools\";\n\nrandom(10, 18);\n```\n\n### Shaping functions\n\nShaping functions are mathematical functions that lets you control the flow of values. These functions can be used to interpolate values between a defined range for example.\n\n#### Reference\n\n- [Detailed reference guide on what and how to use shaping functions.](https://thebookofshaders.com/05/)\n\n- [Visualisation of shaping functions](https://shaping-functions.surge.sh)\n\n- Inigo Quilez's [blog](http://www.iquilezles.org/www/index.htm) explains the use cases for shaping functions such as - animations, or making envelopes for music.\n\n\u003e The below functions were authored by [Inigo Quilez](http://www.iquilezles.org/index.html). I have just ported them to code so that they can be used in creating animations.\n\n#### Gain\n\n`(x: number, y: number) =\u003e number`\n\n```js\nimport { gain } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst gain = (x: number, y: number): number =\u003e {\n  const a = 0.5 * Math.pow(2 * (x \u003c 0.5 ? x : 1 - x), y);\n  return x \u003c 0.5 ? a : 1 - a;\n};\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n#### Impulse\n\n`(x: number, y: number) =\u003e number`\n\n```js\nimport { impulse } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst impulse = (x: number, y: number): number =\u003e {\n  const h = y * x;\n  return h * Math.exp(1 - h);\n};\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n#### Parabola\n\n`(x: number, y: number) =\u003e number`\n\n```js\nimport { parabola } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst parabola = (x: number, y: number): number =\u003e Math.pow(4 * x * (1 - x), y);\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n#### Sine\n\n`(x: number, y: number) =\u003e number`\n\n```js\nimport { sine } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst sine = (x: number, y: number): number =\u003e {\n  const a = 3.1459265359 * y * x - 1;\n  return Math.sin(a) / a;\n};\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n#### Power\n\n`(x: number, y: number, a: number) =\u003e number`\n\n```js\nimport { power } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst power = (x: number, a: number, b: number): number =\u003e {\n  const k = Math.pow(a + b, a + b) / (Math.pow(a, a) * Math.pow(b, b));\n  return k * Math.pow(x, a) * Math.pow(1 - x, b);\n};\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n#### Exponential step\n\n`(x: number, y: number, n: number) =\u003e number`\n\n```js\nimport { expStep } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst expStep = (x: number, y: number, n: number): number =\u003e {\n  return Math.exp(-y * Math.pow(x, n));\n};\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n#### Cubic pulse\n\n`(x: number, y: number, a: number) =\u003e number`\n\n```js\nimport { cubicPulse } from \"generative-art-tools\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eImplementation\u003c/summary\u003e\n  \u003cp\u003e\n\n```js\nconst cubicPulse = (x: number, y: number, a: number): number =\u003e {\n  x = Math.abs(x - a);\n  if (x \u003e y) return 0;\n\n  x /= y;\n  return 1 - x * x * (3 - 2 * x);\n};\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n## License\n\nMIT © [nitin42](https://github.com/nitin42)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitin42%2Fgenerative-art-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnitin42%2Fgenerative-art-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitin42%2Fgenerative-art-tools/lists"}