Since my first project in html/css was a digital reinterpretation of mondrians work, I thought i might do my first basiljs project related to mondrian once aswell. I wrote a script that creates a book with a random, "mondrianesque" illustration on each page. As a little easteregg, there is a 1 in 100 chance of a Malevic "Black Square" appearing instead of a Mondrian.
// @includepath ~/Documents/;%USERPROFILE%Documents;
// @include basiljs/basil.js;
function draw() {
size("A4"); // sets document size(width, height) or size("preset")
layer("output"); // creates layer called 'output' and draw our items there
clear(layer("output")); // clears all items on a layer - useful when starting out
units(MM); // sets units to milimeters (can use PTS, PX, CM, IN)
canvasMode(MARGIN);
pageCount(1);
var numPages = 30;
for (var p = 0; p < numPages; p++) {
if (p > 0) {
addPage();
}
mondrian(p);
}
}
function mondrian(pval) {
var myRandomness = Math.round(Math.random() * 3 + 1);
var myRandomness2 = Math.round(Math.random() * 3 + 1);
var myRandomness3 = Math.round(Math.random() * 4 + 1);
var colorRandomness = Math.round(Math.random() * 5 + 1);
var MALEVIC = Math.round(Math.random() * 99 + 1);
//x axis
var xstart = random(width * 0.05, width * 0.15);
var xend = random(width * 0.85, width * 0.95);
var x1 = random(width * 0.2, width * 0.39);
var x2 = random(width * 0.41, width * 0.59);
var x2ahalf = random(width * 0.5, width * 0.59);
var x3 = random(width * 0.61, width * 0.8);
//y axis
var ystart = random(height * 0.15, height * 0.29);
var yend = random(height * 0.74, height * 0.85);
var y1 = random(height * 0.34, height * 0.49);
var y2 = random(height * 0.51, height * 0.59);
var y3 = random(height * 0.61, height * 0.69);
//RGB 1
var R1 = 255;
var G1 = 0;
var B1 = 0;
//RGB 2
var R2 = 0;
var G2 = 0;
var B2 = 0;
//RGB3
var R3 = 255;
var G3 = 255;
var B3 = 255;
//RGB4
var R4 = 255;
var G4 = 255;
var B4 = 255;
//RGB5
var R5 = 255;
var G5 = 255;
var B5 = 255;
if (colorRandomness == 1) {
R1 = 255;
G1 = 0;
B1 = 0;
R3 = 255;
G3 = 255;
B3 = 255;
R2 = 255;
G2 = 255;
B2 = 255;
R4 = 255;
G4 = 255;
B4 = 0;
R5 = 0;
G5 = 0;
B5 = 255;
}
if (colorRandomness == 2) {
R1 = 0;
G1 = 0;
B1 = 0;
R3 = 255;
G3 = 255;
B3 = 255;
R2 = 255;
G2 = 0;
B2 = 0;
R4 = 0;
G4 = 0;
B4 = 255;
R5 = 255;
G5 = 255;
B5 = 255;
}
if (colorRandomness == 3) {
R1 = 255;
G1 = 255;
B1 = 0;
R4 = 0;
G4 = 0;
B4 = 255;
R3 = 255;
G3 = 255;
B3 = 255;
R2 = 255;
G2 = 255;
B2 = 255;
R5 = 255;
G5 = 255;
B5 = 255;
}
if (colorRandomness == 4) {
R1 = 0;
G1 = 0;
B1 = 255;
R3 = 255;
G3 = 255;
B3 = 255;
R2 = 255;
G2 = 255;
B2 = 0;
R4 = 0;
G4 = 0;
B4 = 0;
R5 = 255;
G5 = 255;
B5 = 255;
}
if (colorRandomness == 5) {
R1 = 255;
G1 = 255;
B1 = 255;
R3 = 0;
G3 = 0;
B3 = 255;
R2 = 255;
G2 = 255;
B2 = 255;
R4 = 255;
G4 = 255;
B4 = 255;
R5 = 255;
G5 = 255;
B5 = 255;
}
if (colorRandomness == 6) {
R1 = 255;
G1 = 255;
B1 = 0;
R3 = 255;
G3 = 255;
B3 = 255;
R2 = 255;
G2 = 255;
B2 = 255;
R4 = 255;
G4 = 255;
B4 = 0;
R5 = 255;
G5 = 0;
B5 = 0;
}
/* if (pval%2 == 0){
G1 = 255;
} else {
G1 = 0;
} */
fill(255);
stroke(0);
strokeWeight(10);
rect(xstart, ystart, xend - xstart, yend - ystart);
strokeWeight(5);
if (myRandomness == 1) {
fill(R3, G3, B3);
rect(xstart, ystart, xend - xstart, y1 - ystart);
fill(255);
}
if (myRandomness == 2) {
rect(xstart, ystart, x3 - xstart, y1 - ystart);
rect(x3, ystart, xend - x3, y1 - ystart);
}
if (myRandomness == 3) {
fill(R1, G1, B1);
rect(xstart, ystart, x1 - xstart, y1 - ystart);
fill(255);
rect(x1, ystart, x2ahalf - x1, y1 - ystart);
rect(x2ahalf, ystart, xend - x2ahalf, y1 - ystart);
}
if (myRandomness == 4) {
fill(R5, G5, B5);
rect(xstart, ystart, x1 - xstart, y1 - ystart);
fill(R3, G3, B3);
rect(x1, ystart, x3 - x1, y1 - ystart);
fill(255);
rect(x3, ystart, xend - x3, y1 - ystart);
}
if (myRandomness2 == 1) {
fill(R4, G4, B4);
rect(xstart, y1, x2 - xstart, y2 - y1);
fill(255);
rect(x2, y1, xend - x2, y2 - y1);
}
if (myRandomness2 == 2) {
fill(R5, G5, B5);
rect(xstart, y1, x1 - xstart, y2 - y1);
fill(255);
rect(x1, y1, xend - x1, y2 - y1);
}
if (myRandomness2 == 3) {
rect(xstart, y1, x1 - xstart, y2 - y1);
rect(x1, y1, x2 - x1, y2 - y1);
fill(R2, G2, B2);
rect(x2, y1, xend - x2, y2 - y1);
fill(255);
}
if (myRandomness2 == 4) {
rect(xstart, y1, x2 - xstart, y2 - y1);
rect(x2, y1, x3 - x2, y2 - y1);
fill(R3, G3, B3);
rect(x3, y1, xend - x3, y2 - y1);
fill(255);
}
if (myRandomness3 == 1) {
fill(R3, G3, B3);
rect(xstart, y2, x2ahalf - xstart, yend - y2);
fill(255);
rect(x2ahalf, y2, xend - x2ahalf, yend - y2);
}
if (myRandomness3 == 2) {
rect(xstart, y2, x3 - xstart, yend - y2);
fill(R2, G2, B2);
rect(x3, y2, xend - x3, yend - y2);
fill(255);
}
if (myRandomness3 == 3) {
fill(R4, G4, B4);
rect(xstart, y2, x1 - xstart, yend - y2);
fill(R5, G5, B5);
rect(x1, y2, x2 - x1, yend - y2);
fill(R2, G2, B2);
rect(x2, y2, xend - x2, yend - y2);
fill(255);
}
if (myRandomness3 == 4) {
rect(xstart, y2, x1 - xstart, y3 - y2);
fill(R1, G1, B1);
rect(x1, y2, x3 - x1, y3 - y2);
fill(R3, G3, B3);
rect(x3, y2, xend - x3, y3 - y2);
fill(255);
}
if (myRandomness3 == 5) {
fill(R5, G5, B5);
rect(xstart, y2, xend - xstart, yend - y2);
fill(255);
}
if (myRandomness3 == 4 || myRandomness3 == 1) {
if (myRandomness == 1) {
fill(R3, G3, B3);
rect(xstart, y3, x1 - xstart, yend - y3);
fill(255);
rect(x1, y3, x2 - x1, yend - y3);
fill(R3, G3, B3);
rect(x2, y3, xend - x2, yend - y3);
fill(255);
} else {
rect(xstart, y3, x2 - xstart, yend - y3);
fill(R4, G4, B4);
rect(x2, y3, xend - x2, yend - y3);
fill(0);
}
}
if (MALEVIC == 2) {
noStroke();
fill(255);
rect(0, 0, width, height);
fill(0);
textSize(30);
textLeading(25);
textTracking(-10);
textFont("Alternate Gothic No2 D", "Regular");
textAlign(Justification.CENTER_ALIGN);
rect(
width / 2 - width * 0.3,
height / 2 - width * 0.3,
width * 0.6,
width * 0.6
);
text(
"FUCK MONDRIAN... \n MALEVIC HAS HIT YOU WITH THE BLACK SQUARE!",
0,
height * 0.85,
width,
height * 0.15
);
strokeWeight(5);
fill(255);
}
/*
beginShape();
vertex(x1,y1);
vertex(x2,y1);
vertex(x2,y2);
vertex(x1,y2);
endShape(); */
}
During the lockdown I wrote a script that creates a random room with only one window for each page. It also randomizes three different daytimes.
// @includepath ~/Dokumente/;%USERPROFILE%Documents;
// @include basiljs/basil.js;
function draw() {
size("A4"); // sets document size(width, height) or size("preset")
layer("Ebene 1"); // creates layer called 'output' and draw our items there
clear(layer("Ebene 1")); // clears all items on a layer - useful when starting out
pageCount(1);
var numPages = 15;
for (var p = 0; p < numPages; p++) {
if (p > 0) {
addPage();
}
myRoom(p);
}
function myRoom(pval) {
noStroke();
var radius = random(50, 100);
var radius2 = random(50, 80);
var myWidth = random(0, width - radius);
var myHeight = random(height * 0.2, height * 0.8 - radius);
var radius3 = random(3, 6);
var radius4 = random(8, 13);
var radius5 = random(4, 15);
var myHeight2 = random(height * 0.6, height * 0.9);
var myWidth2 = random(width * 0.4, width * 0.6);
var myRandom = random(5, 30);
var myRandom2 = random(5, 30);
var myRandom3 = random(0, 10);
var myRandom4 = random(1, 3);
var myRandom5 = random(1.2, 2.2);
var myRandomness = Math.round(Math.random() * 2.2 + 1);
print(myRandomness);
}
var myDecke = random(0, height * 0.2);
var myBoden = random(height * 0.8, height);
var myGrad1 = gradient(color(225), color(225));
var myGrad2 = gradient(color(230), color(180));
var myGrad3 = gradient(color(210), color(235));
var myGrad4 = gradient(color(240), color(215));
var myGrad5 = gradient(color(205), color(210));
var myGrad6 = gradient(color(200, 255, 244), color(237, 255, 244));
var myGrad7 = gradient(color(180, 235, 244), color(217, 235, 244));
var myGrad8 = gradient(color(25, 22, 30), color(10, 15, 25));
var myGrad9 = gradient(color(31, 0, 7), color(50, 32, 25));
fill(0);
var myRect = rect(myWidth, myHeight, radius, radius2);
property(myRect, "label", "background" + pval);
property(myRect, "fillColor", myGrad5);
property(myRect, "gradientFillAngle", 90);
var sel = label("background" + pval);
var bnds = bounds(sel);
var myWindow = rect(
myWidth + myRandom / 2,
myHeight + myRandom2 / 2,
radius - myRandom,
radius2 - myRandom2
);
if (myRandomness == 2) {
property(myWindow, "fillColor", myGrad6);
property(myWindow, "gradientFillAngle", 70);
fill(255, 255, 0);
ellipse(
random(
myWidth + myRandom / 2 + 20,
myWidth + myRandom / 2 + (radius - myRandom) - 25
),
random(
myHeight + myRandom2 / 2 + 10,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 20
),
10 + myRandom3,
10 + myRandom3
);
}
if (myRandomness == 1) {
property(myWindow, "fillColor", myGrad7);
property(myWindow, "gradientFillAngle", 100);
var wolkekoordy = random(
myHeight + myRandom2 / 2 + 5,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 15
);
var wolkekoordx = random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 15
);
var wolkekoordy2 = random(
myHeight + myRandom2 / 2 + 5,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 15
);
var wolkekoordx2 = random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 15
);
fill(255);
ellipse(wolkekoordx, wolkekoordy, 6, 2 + myRandom4);
ellipse(wolkekoordx + 3, wolkekoordy - 1, 8, 4 + myRandom4);
ellipse(wolkekoordx + 6, wolkekoordy, 5, 2 + myRandom4);
ellipse(wolkekoordx2, wolkekoordy, 5, 1.5 + myRandom4);
ellipse(wolkekoordx2 + 2, wolkekoordy - 0.5, 8, 3 + myRandom4);
ellipse(wolkekoordx2 + 5, wolkekoordy, 4, 1.5 + myRandom4);
}
if (myRandomness == 3) {
property(myWindow, "fillColor", myGrad8);
property(myWindow, "gradientFillAngle", 5);
fill(255);
var ximfenster = random(
myWidth + myRandom / 2,
myWidth + myRandom / 2 + (radius - myRandom)
);
var yimfenster = random(
myHeight + myRandom2 / 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2)
);
ellipse(
random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 10
),
random(
myHeight + myRandom2 / 2 + 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 7
),
1,
1
);
ellipse(
random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 10
),
random(
myHeight + myRandom2 / 2 + 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 7
),
1,
1
);
ellipse(
random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 10
),
random(
myHeight + myRandom2 / 2 + 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 7
),
1,
1
);
ellipse(
random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 10
),
random(
myHeight + myRandom2 / 2 + 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 7
),
1,
1
);
ellipse(
random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 10
),
random(
myHeight + myRandom2 / 2 + 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 7
),
1,
1
);
ellipse(
random(
myWidth + myRandom / 2 + 5,
myWidth + myRandom / 2 + (radius - myRandom) - 10
),
random(
myHeight + myRandom2 / 2 + 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 7
),
1,
1
);
fill(255);
var mondkoordy = random(
myHeight + myRandom2 / 2 + 15,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) - 20
);
var mondkoordx = random(
myWidth + myRandom / 2 + 15,
myWidth + myRandom / 2 + (radius - myRandom) - 25
);
ellipse(mondkoordx, mondkoordy, 7 + myRandom3, 7 + myRandom3);
var mondnegativ = ellipse(
mondkoordx + 4,
mondkoordy,
7 + myRandom3,
7 + myRandom3
);
property(mondnegativ, "fillColor", myGrad8);
property(mondnegativ, "gradientFillAngle", 5);
}
//Fensterbalken
fill(207.5);
rect(
myWidth + myRandom / 2 + (radius - myRandom) / 2,
myHeight + myRandom2 / 2,
1,
radius2 - myRandom2
);
rect(
myWidth + myRandom / 2,
myHeight + myRandom2 / 2 + (radius2 - myRandom2) / 2,
radius - myRandom,
1
);
//Decke
beginShape();
vertex(width, 0);
vertex(0, 0);
vertex(0, myDecke);
vertex(bnds.left, bnds.top);
vertex(bnds.right, bnds.top);
vertex(width, myDecke);
var Decke = endShape(CLOSE);
property(Decke, "fillColor", myGrad1);
property(Decke, "gradientFillAngle", 90);
beginShape();
vertex(0, myBoden);
vertex(bnds.left, bnds.bottom);
vertex(bnds.left, bnds.top);
vertex(0, myDecke);
var Wand1 = endShape(CLOSE);
property(Wand1, "fillColor", myGrad4);
property(Wand1, "gradientFillAngle", 0);
beginShape();
vertex(width, myBoden);
vertex(bnds.right, bnds.bottom);
vertex(bnds.right, bnds.top);
vertex(width, myDecke);
var Wand2 = endShape(CLOSE);
property(Wand2, "fillColor", myGrad3);
property(Wand2, "gradientFillAngle", 0);
/*
fill(0);
beginShape();
vertex(width,myBoden -40);
vertex(bnds.right +20,bnds.bottom );
vertex(bnds.right +20,bnds.top );
vertex(width,myDecke +40);
var Fenster2 = endShape(CLOSE);
*/
beginShape();
vertex(width, height);
vertex(0, height);
vertex(0, myBoden);
vertex(bnds.left, bnds.bottom);
vertex(bnds.right, bnds.bottom);
vertex(width, myBoden);
var Boden = endShape(CLOSE);
property(Boden, "fillColor", myGrad2);
property(Boden, "gradientFillAngle", 90);
/* MAKE A LAMP!!! :)
var myLampeDeckel= ellipse(myWidth2, myHeight2,radius4,radius3);
property(myLampeDeckel,"label","deckel"+pval);
var sel2 = label("deckel"+pval);
var bnds2 = bounds(sel2);
var myLampeBode= ellipse(myWidth2, myHeight2+3+radius5,radius4+8,radius3);
fill (0);
beginShape();
vertex(bnds2.right,bnds2.top + (bnds2.bottom-bnds2.top)/2);
vertex(bnds2.left,bnds2.top + (bnds2.bottom-bnds2.top)/2);
vertex(bnds2.left - 4,bnds2.top + (bnds2.bottom-bnds2.top)/2 +3+radius5);
vertex(bnds2.right + 4,bnds2.top + (bnds2.bottom-bnds2.top)/2 +3+radius5);
var LampenMantel = endShape(CLOSE);
myLampeDeckel= ellipse(myWidth2, myHeight2,radius4,radius3);
property(LampenMantel,"fillColor",myGrad9);
property(LampenMantel,"gradientFillAngle",0);
property(myLampeDeckel,"fillColor",myGrad9);
property(myLampeDeckel,"gradientFillAngle",90);
property(myLampeBode,"fillColor",myGrad9);
property(myLampeBode,"gradientFillAngle",0); */
}
This Script breaks down a font and uses the anchor Points to depict how each letter of the alphabet is constructed/drawn. The script I wrote can theoretically be fed any typeface.
// @includepath ~/Dokumente/;%USERPROFILE%Documents;
// @include basiljs/basil.js;
function draw() {
size("A4"); // sets document size(width, height) or size("preset")
layer("output"); // creates layer called 'output' and draw our items there
clear(layer("output")); // clears all items on a layer - useful when starting out
units(MM);
pageCount(1);
var numPages = 26;
for (var p = 0; p < numPages; p++) {
if (p > 0) {
addPage();
}
myFunction(p);
}
}
function myFunction(pval) {
fill(230);
stroke(0);
var myAlphabet = [
"Aa",
"Bb",
"Cc",
"Dd",
"Ee",
"Ff",
"Gg",
"Hh",
"Ii",
"Jj",
"Kk",
"Ll",
"Mm",
"Nn",
"Oo",
"Pp",
"Qq",
"Rr",
"Ss",
"Tt",
"Uu",
"Vv",
"Ww",
"Xx",
"Yy",
"Zz",
];
var myTypefaces = [
"Abril Fatface",
"Amador",
"News Plantin MT Std",
"Betty Noir",
"Didot",
"Gotham Pro (OTF)",
"Minion Pro",
"Finnegan LT Com",
"Stilson",
];
var Randomizer = -1 + Math.round(Math.random() * 8 + 1);
print(Randomizer);
textFont(myTypefaces[Randomizer], "Regular");
textSize(250);
textAlign(Justification.CENTER_ALIGN, VerticalJustification.CENTER_ALIGN);
var myText = text(myAlphabet[pval], 0, 0, width, height);
var outlines = createOutlines(myText);
outlines[0].strokeColor = color(10);
outlines[0].strokeWeight = 1;
var pts = pathToPoints(outlines, 5);
beginShape();
noFill();
strokeWeight(0.2);
for (var k = 0; k < pts.paths.length; k++) {
var path = pts.paths[k];
beginShape();
for (var l = 0; l < path.points.length; l++) {
var pt = path.points[l];
vertex(pt.x + 2, pt.y + 2);
}
var myShape = endShape(CLOSE);
var bnds = bounds(myShape);
line(bnds.right + 2, bnds.top, bnds.left - 2, bnds.top);
line(bnds.right + 2, bnds.top - 2, bnds.left - 2, bnds.top - 2);
line(bnds.right, bnds.top - 4, bnds.right, bnds.bottom + 2);
line(bnds.left, bnds.top - 4, bnds.left, bnds.bottom + 2);
line(bnds.right + 2, bnds.bottom, bnds.left - 2, bnds.bottom);
line(bnds.right + 2, bnds.bottom - 2, bnds.left - 2, bnds.bottom - 2);
//line(bnds.right, bnds.top, bnds.left, bnds.bottom);
//line(bnds.left, bnds.top, bnds.right, bnds.bottom);
line(
bnds.right - (bnds.right - bnds.left) / 2 - 2,
bnds.bottom - (bnds.bottom - bnds.top) / 2 - 2,
bnds.left - 4,
bnds.top - 4
);
line(
bnds.right - (bnds.right - bnds.left) / 2 - 2,
bnds.bottom - (bnds.bottom - bnds.top) / 2 - 2,
bnds.right -
(bnds.right - bnds.left) / 2 -
2 -
(bnds.bottom - bnds.top) / 2 -
2,
bnds.top + (bnds.bottom - bnds.top) / 2 - 2
);
line(
bnds.right - (bnds.right - bnds.left) / 2 - 2,
bnds.top - 6,
bnds.right - (bnds.right - bnds.left) / 2 - 2,
bnds.bottom + 4
);
ellipse(
bnds.right - (bnds.right - bnds.left) / 2 - 2,
bnds.bottom - (bnds.bottom - bnds.top) / 2 - 2,
bnds.bottom - bnds.top,
bnds.bottom - bnds.top
);
//var strokeTypes = ['Wellenlinie' , 'Dreifach' , 'Gepunktet']
//property(myShape, 'strokeType', random(strokeTypes));
}
for (var j = 0; j < pts.beziers.length; j++) {
var pt = pts.beziers[j];
strokeWeight(0.7);
stroke(255, 0, 0);
fill(255, 0, 0);
line(pt.anchor.x, pt.anchor.y, pt.right.x, pt.right.y);
ellipse(pt.right.x, pt.right.y, 0.4, 0.4);
line(pt.anchor.x, pt.anchor.y, pt.left.x, pt.left.y);
ellipse(pt.left.x, pt.left.y, 0.4, 0.4);
fill(255);
strokeWeight(0.7);
ellipse(pt.anchor.x, pt.anchor.y, 0.7, 0.7);
}
fill(90);
textSize(18);
textFont("Helvetica", "Bold");
textAlign(Justification.CENTER_ALIGN, VerticalJustification.CENTER_ALIGN);
var myText2 = text(
"Anatomy of " + myTypefaces[Randomizer] + ' "' + myAlphabet[pval] + '"',
0,
height / 1.5,
width,
height - height / 1.5
);
var outlines2 = createOutlines(myText2);
noFill();
noStroke();
var pts2 = pathToPoints(outlines2);
beginShape();
for (var l = 0; l < pts2.points.length; l++) {
var pt2 = pts2.points[l];
vertex(pt2.x, pt2.y);
}
var myShape2 = endShape(CLOSE);
strokeWeight(0.1);
stroke(50);
var bnds2 = bounds(myShape2);
line(bnds2.right + 1, bnds2.top + 0.11, bnds2.left - 1, bnds2.top + 0.11);
line(bnds2.right + 1, bnds2.top - 1.29, bnds2.left - 1, bnds2.top - 1.29);
line(bnds2.right, bnds2.top - 2, bnds2.right, bnds2.bottom + 1);
line(bnds2.left, bnds2.top - 2, bnds2.left, bnds2.bottom + 1);
line(bnds2.right + 1, bnds2.bottom, bnds2.left - 1, bnds2.bottom);
line(bnds2.right + 1, bnds2.bottom - 1.4, bnds2.left - 1, bnds2.bottom - 1.4);
}
The final project was done together with Nicolas Zufferey. We combined machine learning, ml5js and basiljs by training a char-rnn model with Harry Potter texts and then feeding it the eBook "A little wizard" to complete it in the writing style of J.K.Rowling. The text output was then layouted in Indesign by a basiljs code.
JAVASCRIPT FOR TEXTGENERATING
let charRNN;
let sentiment;
let words;
let words2;
var myText;
var mynewText;
function setup() {
myText = loadStrings("wizard.txt");
console.log(myText);
noCanvas();
charRNN = ml5.charRNN("/models/jkrowling_HP/");
sentiment = ml5.sentiment("movieReviews", modelReady);
console.log("Modell 2 wird geladen...");
console.log("Modell 1 wird geladen...");
}
function modelReady() {
console.log("Modell 1 geladen!");
console.log("Modell 2 geladen!");
generate();
}
function generate() {
console.log("Text wird generiert...");
let txt = myText;
if (txt.length > 0) {
let data = {
seed: txt,
temperature: 0.8,
length: 4000,
};
charRNN.generate(data, gotData);
function gotData(err, result) {
var newText = result.sample;
runningInference = false;
words = newText.split(" ").join(" ");
words2 = newText.split(" ");
getSentiment();
var blob = new Blob(["Welcome to Websparrow.org."], {
type: "text/plain;charset=utf-8",
});
download(newText, "harry.txt", "text/plain");
}
}
}
function download(data, filename, type) {
var file = new Blob([data], { type: type });
if (window.navigator.msSaveOrOpenBlob)
// IE10+
window.navigator.msSaveOrOpenBlob(file, filename);
else {
// Others
var a = document.createElement("a"),
url = URL.createObjectURL(file);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
}
function getSentiment() {
var a = 0;
var b = 100;
var sentimentValuePerSection = [];
var sentimentValuePerWords = [];
for (j = 0; j < 30; j++) {
const text = words.slice(a, b);
const prediction = sentiment.predict(words.slice(a, b));
console.log(prediction.score);
sentimentValuePerSection.push(prediction.score);
a = a + 100;
b = b + 100;
}
for (i = 0; i < 30; i++) {
const text2 = words2[i];
const prediction2 = sentiment.predict(words2[i]);
console.log(prediction2.score);
sentimentValuePerWords.push(prediction2.score);
}
console.log(sentimentValuePerSection);
console.log(sentimentValuePerWords);
download(sentimentValuePerSection, "sentiment-data.csv", "text/plain");
}
JAVASCRIPT FOR INDESIGN
// @includepath ~/Dokumente/;%USERPROFILE%Documents;
// @include basiljs/basil.js;
var text_boxes = [];
var pagination = 1;
var textfile;
var ogfile;
var myRandomness;
function draw() {
var output = layer("output"); //creates output layer
clear(output); //clears output layer
units(MM); //sets document unit to milimeters
pageCount(1); //force 1 page
colorMode(CMYK);
var numPages = 9; //number of pages
textfile = loadStrings("harry.txt").join(" ");
ogfile = loadStrings("wizard.txt").join(" ");
textSize(20);
for (var p = 0; p < numPages; p++) {
//adds pages until number of pages is reached
if (p > 0) {
//
addPage();
}
//backdrop()
addTextBoxes(p + 1); //p+1 is the current page number
pagina();
if (p > 0) {
linkTextFrames(text_boxes[p], text_boxes[p + 1]);
/*
var objMax = words(sel).length;
characters(sel, function(obj, counter){
typo(obj, "pointSize", 20);
typo(obj, "appliedFont", "Helvetica");
}); */
}
//pagina(p+1) //p+1 is the current page number
}
property(
text_boxes[1],
"contents",
"A LITTLE WIZARD X HARRY POTTER \n \n" + ogfile + textfile + "\n\nTHE END."
);
var c = 1;
for (var k = 0; k < numPages; k++) {
//randomizer();
words(text_boxes[c], function (obj) {
typo(obj, "skew", random(-20, 20));
typo(obj, "pointSize", round(random(15, 20)));
println(myRandomness);
});
typo(text_boxes[c], "justification", Justification.LEFT_JUSTIFIED);
c = c + 1;
}
/*
var sel = text_boxes[2];
lines(sel, function(obj, counter){
// 'obj' is each line
// 'counter' is counting each object 0..1..2..
var bnd = bounds(obj); // returns object w/ .left, .top, etc.
line(bnd.left, bnd.baseline, bnd.right, bnd.xHeight);
});
var objMax = lines(sel).length; // store how many there are
characters(sel, function(obj, counter){
// 'obj' is each character
// 'counter' is counting each object 0..1..2..
typo(obj, "tracking", random(0,20)); // stroke color
}); */
//savePDF(timestamp() + ".pdf")
}
/*function randomizer(){
myRandomness = Math.round(random(0,5));
} */
function pagina(page) {
//Places a text box that contains the current page number (page)
var bottom = 20; //distance to bottom of page
fill(100);
rectMode(CENTER);
if (pagination == 9) {
pagination = "9" + "¾";
}
var page_box = text(pagination, width / 2, height - bottom, 15, 15);
//println(pagination);
typo(page_box, "characterRotation", random(360));
pagination = pagination + 1;
}
function backdrop() {
//places a colored rectangle as a backdrop
rectMode(CORNER);
fill(10);
rect(0, 0, width, height);
}
function addTextBoxes(page) {
//Adds boxes for text
rectMode(CORNER);
noStroke();
if (page % 2 == 1) {
// check if page odd
var myOuterMargin = 20; //outer margin on odd page
var myInnerMargin = 40; //inner margin on odd page
} else {
var myOuterMargin = 40; //outer margin on even page
var myInnerMargin = 20; //inner margin on even page
}
var myTopMargin = 20; //top margin (even and odd)
var myBottomMargin = 35; //bottom margin (even and odd)
text_boxes[page] = text(
"platzhalter",
myOuterMargin,
myTopMargin,
width - (myOuterMargin + myInnerMargin),
height - (myTopMargin + myBottomMargin)
);
// property(text_box, "label", "textbox" + page);
// typo(text_boxes, "hyphenation", false);
}
Basiljs is a javascript library developed by Ted Davis, Benedikt Gross and Ludwig Zeller used to scripting and automation InDedign. We were introduced to it during Interaction II. Showcased here are 4 books/concepts I developed during the workshop as home assignments, each exploring something we learned on the day. All of it is pure code that executes actions in InDesign and puts out a book in .pdf format.
Libraries/Tools used: basiljs/ml5js/RunwayML/InDesign