Form IV: basil.js

basil.js, Selektion und Typografie, From the Word “Art”... Suchen, From the Word “Art”... Zeichnen

basil.js

basil.js verpackt die Programmierschnittstelle von InDesign in eine Processing-ähnliche Struktur.

Download, Installation

Programme in basil.js sehen Processing-Programmen sehr ähnlich:

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";

function setup() {
}

function draw() {
}

b.go();

..., allerdings beginnen alle Variablen und Funktionen der Library mit einem b.

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";

function setup() {
}

function draw() {
    b.stroke(255,0,0);
    b.line(0,0,b.width,b.height);
}

b.go();

..., Variablen heißen grundsätzlich var (kein float, int, String usw.) und draw() wird nach b.go(); nur ein mal ausgeführt.Die Skripte laufen relativ langsam und können mit b.delay(...) weiter verzögert werden.

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";

var mitteX;
var mitteY;

function setup() {
    mitteX = b.width/2;
    mitteY = b.height/2;
}

function draw() {
    for (var i=0; i<50; i++) {
        b.line(mitteX, mitteY, b.random(b.width), b.random(b.height));
        b.delay(1000);
    }
}

b.go();

Selektion und Typografie

Zugriff auf ein Objekt, das in InDesign ausgewählt wurde:

var selektion = b.selections();

Das Ergebnis ist ein Array. Wir nehmen das erste selektierte Element heraus (Nummer 0)...

var frame = selektion[0];

...und entnehmen ihm alle Wörter:

var alleWorte = b.words(frame);

Die Worte werden mit einer Schleife durchlaufen (auch möglich: Callback). Der Befehl b.typo(...) setzt die typografischen Eigenschaften des entsprechenden Worts.

Hilfreich: basil.js Typo Cheatsheet.

for (var i = 0; i < alleWorte.length; i++) {
    b.typo(alleWorte[i], "pointSize", b.random(8,44));
}

Insgesamt:

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";

function draw() {
    var selektion = b.selections();
    var frame = selektion[0];
    var alleWorte = b.words(frame);  // characters, paragraphs
    for (var i = 0; i < alleWorte.length; i++) {
        b.typo(alleWorte[i], "pointSize", b.random(8,44));
    }
}

b.go(); 

Alle Schriftarten stehen im Array app.fonts. Wir erzeugen eine Zufallszahl zwischen 0 und der Länge des Arrays, nehmen damit eine zufällige Schriftart heraus und geben ihren Namen mit b.println(...) aus. Weil Positionen im Array kein Komma kennen, muss die Zufallszahl abgerundet werden (b.floor(...)).

var zufallsIndex = b.floor(b.random(app.fonts.length));
var schriftart = app.fonts[zufallsIndex].name;
b.println(schriftart);

Verwenden der Schriftart ebenfalls mit b.typo(...).

b.typo(alleWorte[i], "appliedFont", schriftart);

Insgesamt:

function draw() {
    var selektion = b.selections();
    var frame = selektion[0];
    var alleWorte = b.words(frame);
    
    for (var i = 0; i < alleWorte.length; i++) {
        var zufallsIndex = b.floor(b.random(app.fonts.length));
        var schriftart = app.fonts[zufallsIndex].name;
        b.println(schriftart);
        b.typo(alleWorte[i], "appliedFont", schriftart);
        b.typo(alleWorte[i], "pointSize", b.random(8,44));
    }
}

b.go(); 

Das selbe für jeden einzelnen Buchstaben (bei etwas unpassendem Variablennamen)...

var alleWorte = b.characters(frame);

...oder für jeden Absatz:

var alleWorte = b.paragraphs(frame);

From the Word “Art”... Suchen

Sol LeWitt (siehe auch): From the Word “Art”: Blue Lines to Four Corners, Green Lines to Four Sides, and Red Lines Between the Words (1972).

Wir beginnen mit einer Textbox, die wir mit Sol LeWitts Manifest „Sentences on Conceptual Art “ füllen.

Das Programm beginnt mit der ausgewählten Textbox...

var selektion = b.selections();

Wir legen Arrays an, in dem wir alle x- und y-Positionen des Wortes “Art” speichern. Zusätzlich: ein Zähler für das Wort.

var artX = new Array();
var artY = new Array();
var artcounter = 0;

Jetzt mit einer Schleife nach “Art” suchen:

var frame = selektion[0];
var alleWorte = b.words(frame);

// From the Word "Art": 
for (var i = 0; i < alleWorte.length; i++) {
    // ...	
}

Ein if fragt, ob das aktuelle Wort das richtige ist (und ignoriert dank toLowerCase() ob es groß oder klein geschrieben ist). b.trimWord(...) schneidet Satzzeichen ab:

if (b.trimWord(alleWorte[i].contents.toLowerCase()) == "art") {
    //...
}

Die Position eines Wortes ist sein Abstand vom Rand (horizontalOffset) und die Postionen seiner Grundlinie (baseline). Um in die Wortmitte zu kommen, muss die Größe des Wortes berechnet werden (b.bounds(...)) und dann die halbe Länge und Breite eingerechnet werden.

var mitteX = alleWorte[i].horizontalOffset + b.bounds(alleWorte[i]).width/2;
var mitteY = alleWorte[i].baseline - b.bounds(alleWorte[i]).height/2;

Die Position wird in den beiden Arrays an der Stelle gespeichert, die angibt, das wievielte Wort wir bisher gezählt haben. Dann wird weitergezählt:

artX[artcounter] = mitteX;
artY[artcounter] = mitteY;
artcounter++;

Die gesamte Schleife, die die Position von jedem “Art” findet:

// From the Word "Art": 
for (var i = 0; i < alleWorte.length; i++) {
    if (b.trimWord(alleWorte[i].contents.toLowerCase()) == "art") {
        var mitteX = alleWorte[i].horizontalOffset + b.bounds(alleWorte[i]).width/2;
        var mitteY = alleWorte[i].baseline - b.bounds(alleWorte[i]).height/2;
        artX[artcounter] = mitteX;
        artY[artcounter] = mitteY;
        artcounter++;
    }
}

From the Word “Art”... Zeichnen

Eine zweite Schleife durchläuft alle gefundenen Positionen...

for (var i = 0; i < artX.length; i++) {
    // ...
}

...und zeichnet dann. Zunächst die blauen Linien in die Ecken, ...

// Blue Lines to Four Corners, 
b.stroke(0,0,255);
b.line(0,0,artX[i],artY[i]);
b.line(0,b.height,artX[i],artY[i]);
b.line(b.width,0,artX[i],artY[i]);
b.line(b.width,b.height,artX[i],artY[i]);

...dann die Grünen Linien zum Seitenrand...

// Green Lines to Four Sides, 
b.stroke(0,255,0);
b.line(0,b.height/2,artX[i],artY[i]);
b.line(b.width/2,0,artX[i],artY[i]);
b.line(b.width,b.height/2,artX[i],artY[i]);
b.line(b.width/2,b.height,artX[i],artY[i]);

...und dann die roten Linien zwischen allen Wörtern. Dazu muss eine zweite Schleife durchlaufen werden, die das aktuelle “Art” mit allen anderen verbindet:

for (var j = 0; j < artX.length; j++) {
    if (i != j) {
        b.line(artX[i],artY[i],artX[j],artY[j]);
    }
}

Das gesamte Programm zu From the Word “Art”... angewendet auf Sentences on Conceptual Art:

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";
function draw() {
    var selektion = b.selections();
    var artX = new Array();
    var artY = new Array();
    var artcounter = 0;
	
    var frame = selektion[0];
    var alleWorte = b.words(frame);
    
    // From the Word "Art": 
    for (var i = 0; i < alleWorte.length; i++) {
        if (b.trimWord(alleWorte[i].contents.toLowerCase()) == "art") {
            var mitteX = alleWorte[i].horizontalOffset + b.bounds(alleWorte[i]).width/2;
            var mitteY = alleWorte[i].baseline - b.bounds(alleWorte[i]).height/2;
            b.println("Found "+alleWorte[i].contents+" at "+mitteX+", "+mitteY);
            artX[artcounter] = mitteX;
            artY[artcounter] = mitteY;
            artcounter++;
        }
    }
	
    for (var i = 0; i < artX.length; i++) {
        // Blue Lines to Four Corners, 
        b.stroke(0,0,255);
        b.line(0,0,artX[i],artY[i]);
        b.line(0,b.height,artX[i],artY[i]);
        b.line(b.width,0,artX[i],artY[i]);
        b.line(b.width,b.height,artX[i],artY[i]);
        
        // Green Lines to Four Sides, 
        b.stroke(0,255,0);
        b.line(0,b.height/2,artX[i],artY[i]);
        b.line(b.width/2,0,artX[i],artY[i]);
        b.line(b.width,b.height/2,artX[i],artY[i]);
        b.line(b.width/2,b.height,artX[i],artY[i]);
        
        // and Red Lines Between the Words
        b.stroke(255,0,0);
        for (var j=0; j < artX.length; j++) {
            if (i != j) {
                b.line(artX[i],artY[i],artX[j],artY[j]);
            }
        }
    }
}

b.go();