Code Monkey home page Code Monkey logo

p5js_typo's Introduction

p5js_typo

Gif

A repo to experiment (have fun) with typography using p5*js and Rune.font. All the code can be viewed and download on this github repo.

Contents

Interactive demos

light rays

light ray imageDemo - Code

spot lights

spot light imageDemo - Code

3d

3d image Demo - Code

particle lines

particle lines imageDemo - Code

particles attract repel

particle image Demo - Code

scribble

scribble imageDemo - **Code

tentacles

tentacles image Demo - Code

home

Tools

Drawing Framework

p5js

http://p5js.org/

this is our drawing library, it's used to setup the page, the canvas, programm the behaviors of animated objects etc. The website is full of ressources and tutorial to learn, you can also check Daniel Shiffman youtube channel.

scribble

https://github.com/generative-light/p5.scribble.js

this is a library for p5xjs and is only used in one experiment. It's made to make your lines and other shapes look as if the were drawn by hand.

Typographic library

Rune

https://github.com/runemadsen/rune.js

Rune is a full framework for graphic design. It is not limited to typography but we are using it mainly because of Rune.font addon and its support of paths.

Rune.font

https://github.com/runemadsen/rune.font.js

Rune.font is plugin for Rune, it allows us to load a font and convert its outline to Rune.path objects or a series of polygons that we will be able to use withing p5xjs.

Rune Madsen, author of the Rune framework, has a great lecture about typography btw : http://printingcode.runemadsen.com/lecture-typography/

Gui library

dat.GUI

https://github.com/dataarts/dat.gui

dat.GUI is lightweight user interface library for js. It provides a collapsing drawer in which you can place sliders, buttons etc.

home

Hands on tutorial

I will not explain in details how p5xjs works, there is plenty of ressources on the web about that. Hrere I will try to explain how to interface all our tools together.

First p5xjs uses two main functions

function setup(){

}

and

function draw(){

}

the setup is used to initialize all our variables, create a canvas etc. it is called once : on the loading of our page. the draw is an infinite loop that runs until the page is closed.

A lot of the "boilerplate" code will happen in the former, whereas the actual drawing and interaction will happen in the later.

home

Boilerplate code

the base of code used in the examples is a bit complex, our goal is :

1- to load a font, and analyse it using Rune.font to get a list of polygons we can use.

2- setup some gui elements to change the font and few parameters aswell as a button to regenerate the path.

Here is the code :

var f;
var path;
var polys;
var drawing = false;
var gui, params;

function setup(){
    createCanvas(windowWidth,windowHeight)  // create a full screen canvas
    background(255)

    // init all parameters
    params = new Parameters();
    // create dat.gui drawer
    gui = new dat.GUI();
    // gui setup
    var f2 = gui.addFolder('configuration / path generation')
   
     // Configuration parameters
    // font selector
    f2.add(params, 'font', {Avenir : "../fonts/AvenirNextLTW01-Medium.woff", BlackOpsOne : "../fonts/Black_Ops_One/BlackOpsOne-Regular.ttf",
                            Comfortaa : "../fonts/Comfortaa/Comfortaa-Bold.ttf",
                            NovaMono : "../fonts/Nova_Mono/NovaMono.ttf", ShadowsIntoLight : "../fonts/Shadows_Into_Light/ShadowsIntoLight.ttf", 
                            Sniglet: "../fonts/Sniglet/Sniglet-ExtraBold.ttf",Tangerine : "../fonts/Tangerine/Tangerine_Bold.ttf",
                            UnicaOne : "../fonts/Unica_One/UnicaOne-Regular.ttf"});  
    f2.add(params, 'message');
    f2.add(params, 'spacing', 1, 25).listen();
    f2.add(params, 'size', 100, 1200).listen();
    f2.add(params, 'regenerate');

    // button
    gui.add(params, 'save')

    getPoints();
}

// this function loads a font, and create an array of polygons
// a polygon being itself an array of vectors with x/y coordinates
function getPoints(){
    drawing = false;
    // create new font : we use rune
    console.log(params.font);
    f = new Rune.Font(params.font) 
    // load the font
    f.load(function(err){       
        path = f.toPath(params.message, 0, 0, params.size)
        polys = path.toPolygons({ spacing:params.spacing })
        drawing = true;
    });
}

var Parameters = function(){

    this.font = "../fonts/AvenirNextLTW01-Medium.woff"
    this.message = 'p5*js';
    this.spacing = 2;
    this.size = 400;

    this.regenerate = function(){
        getPoints();
    }

    this.save = function(){
        saveCanvas()
    }

}

Quite a few things happened here, so let's break it down.

home

Loading a font and generating a path

First we create a few variables that will be handy.

var f; // store the current font
var path; // store the path calculated from the current font
var polys; // store the array of polygons calculated from the current font
var drawing = false; // as loading is asynchron we need to keep track of its progression
var gui, params; // store gui related things.

The boolean drawing is used to know when the loading of the font is finished : when the font is loaded we have a path varaible that is not null aswell as an array of polygons. This variable is used in the getPoints(), it is set to false at the beginning, and set to true when the font is finally loaded.

So let's now have a look at the getPoints() function

// this function loads a font, and create an array of polygons
// a polygon being itself an array of vectors with x/y coordinates
function getPoints(){
    drawing = false;
    // create new font : we use rune
    console.log(params.font);
    f = new Rune.Font(params.font) 
    // load the font
    f.load(function(err){       
        path = f.toPath(params.message, 0, 0, params.size)
        polys = path.toPolygons({ spacing:params.spacing })
        drawing = true;
    });
}

it's pretty straight forward, and it runs with minimal changes from the Rune.font documentation example :

http://printingcode.runemadsen.com/examples/typography/font/

we have a callback for when the loading is actually finished. When it's done we can actually draw. However you'll notice that I use things like params.font, params.spacing instead of the "hardcoded values from the Rune documentation. This is because of the dat.GUI implementation for parameters.

home

Gui creation

The main ressource to learn dat.GUI is located here for further references : http://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage

Our boilerplate code involves being able to switch fonts, change the size of the message we want to display, and the spacing of points on the outline of the fonts. Those parameters can be changed via a gui, and once you are set you can click on regenerate to recalculate the path and the polys variable.

To do that dat.GUI is pretty easy. The variable named gui represents the things that will be displayed in the control drawer, whereas the variable named params is a javascript object that will simply hold our parameter values.

First let's concentrate on params, on the setup we just have this line to initialize our object.

    // init all parameters
    params = new Parameters();

and further on the code we have the actual object with its default parameters, which is just a data structure :

var Parameters = function(){

    this.font = "../fonts/AvenirNextLTW01-Medium.woff"
    this.message = 'p5*js';
    this.spacing = 2;
    this.size = 400;

        this.regenerate = function(){
        getPoints();
    }

    this.save = function(){
        saveCanvas()
    }

}

dat.GUI will infer the kind of object it draws from the values of the varaibles. So the message by default is "p5xjs" but you can change it you will however need to click on the button regenerate to call the getPoints() function again to re-generate the path and our array of polygons. Since this.regenerate is a function it will be displayed as a button and once you click it you execute the code in-beetween the brackets.

The filling of our control drawer is done in the setup() function :

    // create dat.gui drawer
    gui = new dat.GUI();
    
    // gui setup
    var f2 = gui.addFolder('configuration / path generation')

with the second line of code, we create a specific group of controls f2 in our gui, which will be called 'configuration / path generation'. We will now add elements to this specific folder of controls.

First a font selection object :

    f2.add(params, 'font', {Avenir : "../fonts/AvenirNextLTW01-Medium.woff", BlackOpsOne :     "../fonts/Black_Ops_One/BlackOpsOne-Regular.ttf", Comfortaa : "../fonts/Comfortaa/Comfortaa-Bold.ttf",
NovaMono : "../fonts/Nova_Mono/NovaMono.ttf", ShadowsIntoLight : "../fonts/Shadows_Into_Light/ShadowsIntoLight.ttf", 
Sniglet: "../fonts/Sniglet/Sniglet-ExtraBold.ttf",Tangerine : "../fonts/Tangerine/Tangerine_Bold.ttf", UnicaOne : "../fonts/Unica_One/UnicaOne-Regular.ttf"});  

when you pass a json-like object to the .add() function it will create a dropdown list with each key appearing as an element of the list.

we arleady mentionned message and regenerate entries, so we are left with the later two :

    f2.add(params, 'spacing', 1, 25).listen();
    f2.add(params, 'size', 100, 1200).listen();

those will be sliders as params.spacing and params.size are numeric value, you can then pass the lower and higher bounds as arguments.

You can also notice the .listen() which will make the gui elements listen to the changes that would come from the programm. It can be usefull when creating presets - for instance in the "tentacles" example.

home

Drawing code

We now have the basics for our code base. All we have to do now is actually draw.

In most of the example, some "drawing" things are already happening in the getPoints() function because we want to create a collection of objects (in the sense of oop objects) that take the coordinates of each point of each polygon. In that case the drawing is merely about creating a for loop that runs through our collection and calls the appropriate behavior.

But we can also simply iterate through our array of polygons to draw a shape on each spot... something like :

for (var i=0; i < polys.length ; i++){
           var poly = polys[i];
           for(var j = 0; j < poly.state.vectors.length; j++) {
                var vec1 = poly.state.vectors[j];
          
                noFill()
                stroke(255);
                strokeWeight(1);
                scribble.scribbleEllipse(vec1.x, vec1.y,25,25);   
           }
}                

home

p5js_typo's People

Contributors

b2renger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

p5js_typo's Issues

Exploring Dynamic Typography in p5.js: Inside-Out Element Generation

Hi, I'm Yujian, a visual designer currently learning p5.js for visual design. I'm interested in creating dynamic typography where elements or shapes are generated from within the text itself. Unlike traditional methods that rely on outlining text, I'm seeking approaches where elements like grids, matrices, or irregular lines can fill the interior of the text while maintaining a relationship with its edges. It's not just about masking; I aim for a deeper integration with the text's contours.

I hope you've been well all these years. If you're still active here, I sincerely hope you can answer my question.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.