Algorithmically generated triangle art

Overview

Trianglify Build Status

Trianglify is a library that I wrote to generate nice SVG background images like this one:

Contents

πŸ“¦ Getting Trianglify
🏎 Quickstart
βš–οΈ Licensing
πŸ“– API
🎨 Configuration

πŸ“¦ Getting Trianglify

You can grab Trianglify with npm/yarn (recommended):

npm install --save trianglify

Include it in your application via the unpkg CDN:

<script src='https://unpkg.com/trianglify@^4/dist/trianglify.bundle.js'></script>

Or download a .zip from the releases page.

🏎 Quickstart

Browsers

<script src='https://unpkg.com/trianglify@^4/dist/trianglify.bundle.js'></script>
<script>
  const pattern = trianglify({
    width: window.innerWidth,
    height: window.innerHeight
  })
  document.body.appendChild(pattern.toCanvas())
</script>

Node

const trianglify = require('trianglify')
const fs = require('fs')

const canvas = trianglify({
  width: 1920,
  height: 1080
}).toCanvas()

const file = fs.createWriteStream('trianglify.png')
canvas.createPNGStream().pipe(file)

You can see the examples/ folder for more usage examples.

The https://trianglify.io/ GUI is a good place to play around with the various configuration parameters and see their effect on the generated output, live.

βš–οΈ Licensing

The source code of Trianglify is licensed under version 3 of the GNU General Public License (GPLv3). This means that any websites, apps, or other projects that include the Trianglify javascript library need to be released under a compatible open-source license. If you are interested in using Trianglify in a closed-source project, please email [email protected] to purchase a commercial license.

However, it's worth noting that you own the copyright to the output image files which you create using Trianglify, just like you own the copyright to an image created using something like GIMP. If you just want to use an image file that was generated using Trianglify in your project, and do not plan to distribute the Trianglify source code or compiled versions of it, you do not need to worry about the license restrictions described above.

πŸ“– API

Trianglify is primarily used by calling the trianglify function, which returns a trianglify.Pattern object.

// load the library, either via a window global (browsers) or require call (node)
// in es-module environments, you can `import trianglify from 'trianglify'` as well
const trianglify = window.trianglify || require('trianglify')

const options = { height: 400, width: 600 }
const pattern = trianglify(options)
console.log(pattern instanceof trianglify.Pattern) // true

pattern

This object holds the generated geometry and colors, and exposes a number of methods for rendering this geometry to the DOM or a Canvas.

pattern.opts

Object containing the options used to generate the pattern.

pattern.points

The pseudo-random point grid used for the pattern geometry, in the following format:

[
  [x, y],
  [x, y],
  [x, y],
  // and so on...
]

pattern.polys

The array of colored polygons that make up the pattern, in the following format:

// {x, y} center of the first polygon in the pattern
pattern.polys[0].centroid

// [i, i, i] three indexes into the pattern.points array, 
// defining the shape corners
pattern.polys[0].vertexIndices

// Chroma.js color object defining the color of the polygon
pattern.polys[0].color

pattern.toSVG(destSVG?, svgOpts?)

Rendering function for SVG. In browser or browser-like (e.g. JSDOM) environments, this will return a SVGElement DOM node. In node environments, this will return a lightweight node tree structure that can be serialized to a valid SVG string using the toString() function.

If an existing svg element is passed as the destSVG, this function will render the pattern to the pre-existing element instead of creating a new one.

The svgOpts option allows for some svg-specific customizations to the output:

const svgOpts = {
  // Include or exclude the xmlns='http://www.w3.org/2000/svg' attribute on
  // the root <svg> tag. See https://github.com/qrohlf/trianglify/issues/41
  // for additional details on why this is sometimes important
  includeNamespace: true,
  // Controls how many decimals to round coordinate values to.
  // You can set this to -1 to disable rounding. Default is 1.
  coordinateDecimals: 1
}

pattern.toSVGTree(svgOpts?)

Alternate rendering function for SVG. Returns a lightweight node tree structure that can be seralized to a valid SVG string using the toString() function. In node environments, this is an alias for pattern.toSVG().

pattern.toCanvas(destCanvas?, canvasOpts?)

Rendering function for canvas. In browser and browser-like environments, returns a Canvas HTMLElement node. In node environments, this will return a node-canvas object which follows a superset of the Web Canvas API.

If an existing canvas element is passed as the destCanvas, this function will render the pattern to the pre-existing element instead of creating a new one.

To use this in a node.js environment, the optional dependency node-canvas needs to be installed as a dependency of your project npm install -save canvas.

The canvasOpts option allows for some canvas-specific customizations to the output:

const canvasOpts = {
  // determines how the canvas is rendered on high-DPI (aka "retina") devices.
  // - 'auto' will automatically render the canvas at the appropriate scale ratio
  //   for pixel-perfect display.
  // - a numeric value will render the canvas at that specific scale factor
  //   for example, 2.0 will render it at 2x resolution, wheras 0.5 will render
  //   at half resolution
  // - 'false' will disable scaling, and the canvas will be rendered at the 
  //   exact resolution specified by `width, height`
  scaling: 'auto',
  // if the canvas is rendered at a different resolution than the {width, height}
  // trianglify will apply some inline style attributes to scale it back to
  // the requested {width, height} options. Set applyCssScaling to false to 
  // disable this behavior.
  applyCssScaling: true
}

🎨 Configuration

Trianglify is configured by an options object passed in as the only argument. The following option keys are supported, see below for a complete description of what each option does.

const defaultOptions = {
  width: 600,
  height: 400,
  cellSize: 75,
  variance: 0.75,
  seed: null,
  xColors: 'random',
  yColors: 'match',
  fill: true,
  palette: trianglify.colorbrewer,
  colorSpace: 'lab',
  colorFunction: trianglify.colorFunctions.interpolateLinear(0.5),
  strokeWidth: 0,
  points: null
}

width

Integer, defaults to 600. Specify the width in pixels of the pattern to generate.

height

Integer, defaults to 400. Specify the height in pixels of the pattern to generate.

cellSize

Integer, defaults to 75. Specify the size in pixels of the mesh used to generate triangles. Larger values will result in coarser patterns, smaller values will result in finer patterns. Note that very small values may dramatically increase the runtime of Trianglify.

variance

Decimal value between 0 and 1 (inclusive), defaults to 0.75. Specify the amount of randomness used when generating triangles. You may set this higher than 1, but doing so may result in patterns that include "gaps" at the edges.

seed

String, defaults to null. Seeds the random number generator to create repeatable patterns. When set to null, the RNG will be seeded with random values from the environment. An example usage would be passing in blog post titles as the seed to generate unique but consistient trianglify patterns for every post on a blog site.

xColors

False, string, or array of CSS-formatted colors, default is 'random'. Specify the color gradient used on the x axis.

Valid string values are 'random', or the name of a colorbrewer palette (i.e. 'YlGnBu' or 'RdBu'). When set to 'random', a gradient will be randomly selected from the colorbrewer library.

Valid array values should specify the color stops in any CSS format (i.e. ['#000000', '#4CAFE8', '#FFFFFF']).

yColors

False, string or array of CSS-formatted colors, default is 'match'. When set to 'match' the x-axis color gradient will be used on both axes. Otherwise, accepts the same options as xColors.

palette

The array of color combinations to pick from when using random for the xColors or yColors. See src/utils/colorbrewer.js for the format of this data.

colorSpace

String, defaults to 'lab'. Set the color space used for generating gradients. Supported values are rgb, hsv, hsl, hsi, lab and hcl. See this blog post for some background on why this matters.

colorFunction

Specify a custom function for coloring triangles, defaults to null. Accepts a function to override the standard gradient coloring, which is passed a variety of data about the pattern and each polygon and must return a Chroma.js color object.

See examples/color-function-example.html and utils/colorFunctions.js for more information about the built-in color functions, and how to write custom color functions.

fill

Boolean, defaults to true. Specifies whether the polygons generated by Trianglify should be filled in.

strokeWidth

Number, defaults to 0. Specify the width of the strokes used to outline the polygons. This can be used in conjunction with fill: false to generate weblike patterns.

points

Array of points ([x, y]) to triangulate, defaults to null. When not specified an array randomised points is generated filling the space. Points must be within the coordinate space defined by width and height. See examples/custom-points-example.html for a demonstration of how this option can be used to generate circular trianglify patterns.

Comments
  • v0.2.0 dependency on node-canvas problematic

    v0.2.0 dependency on node-canvas problematic

    Because v0.2.0 depends on node-canvas, I'm probably going to get some confused folks having trouble installing it because of the cairo dependency.

    Possible solutions: make node-canvas an optional dependency, eliminate the node-canvas dependency (how?), include documentation on how to install cairo for node-canvas with the whole

    PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig npm install
    

    thing.

    Need to think about how to handle this one.

    enhancement 
    opened by qrohlf 14
  • Proposal: Node.js friendly version

    Proposal: Node.js friendly version

    With node.js friendly version one could use this to generate backgrounds on server side or on desktop.

    D3 is already in NPM so it should not be that hard.

    I tried to do it myself but I do not really now node.js that well

    opened by Visgean 14
  • Install fails on Node 4.*

    Install fails on Node 4.*

    Some of the dependencies fail on install with the latest versions of node. Seems as this is coming from JSDom which has already resolved this issue on the latest version.

    full error https://gist.github.com/mattmischuk/553e359d3157dca2a0ed

    opened by mattmischuk 9
  • Some lines looks noisy

    Some lines looks noisy

    Thanks for great work! Love the idea!

    But when I generate image and save, some lines looks noisy: trianglify

    On iPhone looks different, but noisy too. Screenshot: 2018-06-01 13 27 07

    opened by Alex-Sokolov 8
  • minimum custom D3 build for trianglify to depend on

    minimum custom D3 build for trianglify to depend on

    Hi,

    Really loving trianglify, thanks for making it! Do you know what the minimum build of D3 needs to be to make it work with trianglify? Right now I've identified the modules:

    • core
    • selection
    • scale
    • interpolate
    • geom

    Would be a nice feature to list or even provide the minimum D3 build required to run trianglify, as the lib progresses I'd imagine the custom build may change.

    Thanks, /t

    opened by tmaslen 8
  • Add an option to generate svg nodes with the correct xmlns attribute for standalone use

    Add an option to generate svg nodes with the correct xmlns attribute for standalone use

    I have been trying to use the svg version of Trianglify, but that output is not valid. I have compared the outerHTML of svg() to a valid Trianglify svg, and there are some obvious problems which are fixable, but there are some more serious problems which mean that the svg cannot be parsed by SVG editors.

    opened by jedison 7
  • trianglify generated image as a div's background?

    trianglify generated image as a div's background?

    Hi, is it possible to make trianglify generated image as a div's background? If yes, how? Code similar to:

    <div class="fullscreen background" style="background-image:url('http://www.minimit.com/images/picjumbo.com_IMG_6648.jpg');" data-img-width="1600" data-img-height="1064">
    
    opened by ser 6
  • watch files in gulp

    watch files in gulp

    Hi! I am working with your awesome library :smile: but it is very tedious to type the gulp command every time I want to see the result. So I am using gulp's watch to do it instead. I think you will like it as well ...

    opened by mandulaj 6
  • Passing destSVG to pattern.toSVG() does not work; implementation is missing πŸ€¦β€β™‚οΈ

    Passing destSVG to pattern.toSVG() does not work; implementation is missing πŸ€¦β€β™‚οΈ

    From the docs:

    If an existing svg element is passed as the destSVG, this function will render the pattern to the pre-existing element instead of creating a new one.

    The way I understand it, the attached code should work, but it doesn't. In fact it doesn't seem like passing destSVG does anything. Am I missing something?

    codePen

    bug 
    opened by IsakUlstrup 5
  • The output image is cropped

    The output image is cropped

    I generated a pattern with the following: let pattern = Trianglify({ width: 350, height: 250, cell_size: 30, variance: 0.75, seed: null, x_colors: ['red','blue','yellow','purple','orange','green'], y_colors: ['white','black'], color_space: 'rgb', stroke_width: 0.6 }); var svg = pattern.svg();

    I was surprised to see that the red on the left and green on the right was so thin: image

    To check that further, I copied the generated svg into a file, set a broader viewBox (instead of the defaut, that would fit to the width and height and start in 0,0), and added a white rect that represents the default viewBox. Here is what I got: image

    The white rectangle represents the part that is displayed, and you can see that some colors are cropped, and a good deal of triangles are lost. I understand it's so that you don't have thin triangles on the border, or even holes; I also understand I can tweak it by duplicating colors at the extremities for instance; but I feel there must be a way to handle that nicely, maybe by making your gradient start on the inside of the box and not on the bounds of the outer triangles?

    Steps to reproduce: Include the snippet above in a 350 * 250 box, and note that red and green extremities are out of the picture.

    opened by Saucistophe 5
  • Avoid false positives in Node environment check

    Avoid false positives in Node environment check

    I'm working with a browser environment where the process global variable is defined. The Node check should be a little more specific to avoid false positives.

    opened by AlexNisnevich 5
  • CLI version of trianglify

    CLI version of trianglify

    First, thank you for creating this project!

    Just wanted to drop a note that I've created a CLI version of trianglify with a few options exposed to tweak the images: https://github.com/furlai/trianglifier

    It's not much, just a small typescript-based node application that configures things within Docker. However, I figure for folks just wanting to quickly generate and iterate on an image without embedding the library on a site, it serves a decent purpose.

    Feedback welcome, of course.

    opened by dabdine 0
  • Upgrade cell generation algorithm

    Upgrade cell generation algorithm

    https://bost.ocks.org/mike/algorithms/

    Bridson’s algorithm for Poisson-disc sampling solves your problem with using a square grid for initial point generation, it gives you uniform triangle size and randomized point distribution. Would probably really enhance the visual here.

    You could also go with the best-candidate algorithm on the same page, which has the nice property of the numCandidates tuning parameter mapping nicely to the triangle variance param that's currently used to randomly distort the square grid.

    opened by qrohlf 0
  • Uncouple from node-canvas.

    Uncouple from node-canvas.

    node-canvas requires node gyp and its a nightmare to use with things like electron or docker. Is there a way to fully uncouple from canvas and instead have an abstraction where the user can decide?

    For example, svg is a good start but if I install Trianglify I am forced to download node-canvas even if I dont want it.

    Maybe some possible alternatives:

    • http://joshmarinacci.github.io/node-pureimage/
    • http://camanjs.com/
    opened by VictorioBerra 12
  • Upload prebuilt .zip files to the Releases tab

    Upload prebuilt .zip files to the Releases tab

    Per v4.0.0, the dist folder with build artifacts will no longer be checked in to git. This is a Good Thing, but it also means that users who don't want to use NPM or unpkg will have to build a bundle from source if they want to use Trianglify the old fashioned way.

    This ticket is to build a Github Actions workflow that will trigger when a new version tag is pushed, and upload a .zip containing the trianglify.bundle.js and trianglify.bundle.min.js files to the release entry on Github.

    opened by qrohlf 0
  • Feature Proposal: Web Worker support/example

    Feature Proposal: Web Worker support/example

    I'd like to run some tests on how to move Trianglify computations off the main thread.

    The main use case here is increasing the responsiveness of the sliders on https://trianglify.io/ - normally, for high-framerate use cases I would recommend implementing custom animation logic on the raw geometry output of Trianglify, but because the input sliders require mesh re-generation and re-coloring this is a unique situation that means I have to call the full trianglify().toCanvas() pipeline every time the user moves a slider.

    Throttling to 15fps and/or using requestAnimationFrame can help in some situations, but ultimately moving pattern computation off the UI thread would be the most effective solution to this problem.

    enhancement 
    opened by qrohlf 0
  • sanity check on cell_size

    sanity check on cell_size

    The current sanity checks for cell_size are not sufficient, it is still possible to create an infinite loop by passing in a string (i.e. "40" instead of 40) for cell_size.

    Oops.

    bug 
    opened by qrohlf 2
procedurally generated fish drawings

fishdraw procedurally generated fish drawings. demo generates all sorts of weird fishes outputs polylines (supported format svg, json, csv, etc.) full

Lingdong Huang 2.1k Jan 3, 2023
Upload your webpack-generated assets to CDN, allowing renaming/rehashing.

webpack5-cdn-plugin For webpack4, please refer to webpack4-cdn-plugin. Docs Install npm i webpack5-cdn-plugin -D Usage const { Webpack5CDNPlugin } =

ζ–‡θ”Ί 4 Aug 22, 2022
Fast and robust triangle-triangle intersection test with high precision for cross and coplanar triangles based on the algorithm by Devillers & Guigue.

fast-triangle-triangle-intersection Fast and robust triangle-triangle intersection test with high precision for cross and coplanar triangles based on

Technology and knowledge for interaction 10 Nov 15, 2022
3D Infinite Art Gallery! This pulls from Reddit's r/Art and creates a procedural infinite art gallery from random (sfw-only) posts.

Infinite-Art-Gallery Click for Demo! 3D Infinite Procedurally-Generated Art Gallery! This pulls from Reddit's r/Art and creates a procedural infinite

Austin 33 Dec 15, 2022
NFT Art Generator made to create random unique art and their metadeta for NFTS.

Welcome to HashLips ?? All the code in these repos was created and explained by HashLips on the main YouTube channel. To find out more please visit: ?

Haadi Raja 2 Dec 11, 2022
A simple game where you can draw art similar to pixel art, or practice Kufic Calligraphy.

Etch-A-Sketch Where to try it? https://jee-el.github.io/etch-a-sketch/ What's the game about? It's a sketching website or game where you can : Draw wh

Lhoussaine Ghallou 6 Oct 27, 2022
This project displays the art collection using the Metropolitan Museum of Art API. For this project we used HTML, CSS, Javascript, Webpack and Jest.

Metropolitan Museum of Art This project displays the art collection using the Metropolitan Museum of Art API. For this project we used HTML, CSS, Java

David Vera Castillo 11 Dec 24, 2022
Contains html file showcasing Earthquake related data generated in the form of VR model, ArcGIS API with real-time earthquake feed and video of simulation of earthquake generated in blender

Module-EADGI-Project-All about Earthquakes Introduction Contains html file showcasing Earthquake related data generated in the form of VR model, ArcGI

Abhishek Rawat 2 Jun 9, 2022
:art: Color Pickers from Sketch, Photoshop, Chrome, Github, Twitter & more

React Color 13 Different Pickers - Sketch, Photoshop, Chrome and many more Make Your Own - Use the building block components to make your own Demo Liv

case 11.2k Jan 6, 2023
✨ Plan your future with Mandal-art ✨

✨ Plan your future with Mandal-art ✨ ?? Make my own Mandal-art Mandal-art is a word that combines'Manda+la' and'Art', which means'achieving the goal',

Min Kyung Kang 35 Nov 9, 2022
This is a particle animation art piece using threejs.

3d-particle-mofing ● DEMO Usage Clone repository Install Node.js Create an .env file and copy the contents of .env-sample. Run following commands np

Hisami Kurita 23 Oct 28, 2022
Interactive digital art with head-coupled perspective effect using Three.js and TensorFlow.js

Interactive digital frame with head-tracking using Three.js & TensorFlow.js Using TensorFlow.js and Three.js, this project is a prototype of an intera

Charlie 61 Dec 12, 2022
Build your own generative art NFT collection with 21 lines of JavaScript

Avatar Collection Build your own Generative Art NFT Collection in 1 minute. Quickstart Just run the following to get started: git clone https://github

rarepress 79 Dec 16, 2022
Share your (queer) art to your local LGBTQ+ community :3

art lav Share your (queer) art to your local LGBTQ+ community :3 watch a video of our demo! https://youtu.be/8Fp89tMSdFA The Problem Despite growing m

Nathan Endow 3 Jan 25, 2022
In game dev, generative art, and creative coding, sine is a ubiquitous function that is often used as a spring-like oscillator for a given parameter.

In game dev, generative art, and creative coding, sine is a ubiquitous function that is often used as a spring-like oscillator for a given parameter.

Mark Racette 3 Feb 22, 2022
Beat Akamai Technologies' State of the Art Antibot 2.0

Akamai Bot Manager 2.0 If you want to talk join https://discord.gg/amBFR6G2PM Feel free to contact me @lulu_fr_ on Twitter, open an issue or start a d

LULU 50 Dec 15, 2022
Mystery generative art I conjured up for no particular reason

Mystery Art Mystery generative art I conjured up for no particular reason. Samples The following samples were generated from a starting geometric shap

Ronak Badhe 3 Feb 25, 2022
Create amazing pixel art murals. 🐸

Pixelate Create amazing pixel art murals with sticky notes. Pixelate is a image editor that shows assembly guides to put art with sticky notes on your

Google 19 Dec 11, 2022
Design and apply pixel art to reddit's /r/place

Reddit /r/place BOT Design and apply pixel art to reddit's /r/place Install NOTE: If you are using M1 mac and have issue installing node-canvas, see t

Stefan Mirea 10 Apr 4, 2022
A web app that helps you create Pixel Art Masterpieces! ;)

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Seyyed Mohammad Shobeiry 3 Jun 13, 2022