https://knowuh.github.io/2019-nerd-doodle/
[related code pen example](https://codepen.io/knowuh/pen/GeEEMb?editors=0010) # What is this talk? * Introduction to creative coding * Highlights from a class * For newbies * For cranky old-timers ## deets * [Canvas 2d api](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) * Raw Javascript * Live mistakes * Visual tricks * Art history * Resources ## Why sketch with code?- Educational
- Happy accidents
- Brain benefits*
* I am not a doctor
"I like to think of play not as an activity, but as an attitude, a way of engaging with the world"– *Mitchel Resnick* (@mres) # Early Computer artists
Frieder Nake – Mathemetician
George Nees – Math & Philosophy
Vera Molnar – Artist
Vera Molnar – Artist
Vera Molnar – Artist
#### VLW / ACG
## canvas
## Square on a canvas
demo
## 01
## Multiple Squares
demo
## 02
## Squares on a Grid
## 03
## Loop it
demo
## 04
#### *--record scratch--*
## Context & Transforms
### Remember this?
## We can change it with:
* `context.save()`
* `context.tranlate(…)`
* `context.rotate(…)`
* `context.scale(…)`
* `context.transform(…)`
* `context.restore()`
## Make it big
demo
##### 05
## Moar loops
demo
```javascript
function veraSquare() {
var i = 0;
var numSquares = 10;
var stepSize = 1 / numSquares;
// sale from 0 to 1 in numSquares steps
for (i = 0; i <= 1; i += stepSize) {
context.save();
context.scale(i, i);
drawSquare();
context.restore();
}
}
```
##### 06
### Imperfectionz & randomnez
demo
##### 07
## Parameters and Variations
demo
##### 08
## HSLA Colors
demo
##### 09
## Polar to Cartesian
* x = r × cos(θ)
* y = r × sin(θ)
## Put it together
demo
## Postscript: Animation
demo
# Accelerated Art School
* Sketch.
* Use arbitrary constraints.
* Learn about Gestalt principles.
* Some quick tips.
## Sketching:
* On paper.
* Many examples quickly.
* Disposable.
* Generate questions.
* Process not product.


Point of departure: ~1970


context
<html>
<head> … </head>
<body>
<canvas width="500" height="500"></canvas>
</body>
<script>
// what we are doing is all in between these script tags
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
</script>
</html>
// Easy way to draw a square:
context.strokeRect(10, 10, 100, 100);
// The hard way
context.strokeStyle = "black";
context.beginPath();
context.moveTo(10,10);
context.lineTo(100,10);
context.lineTo(100,100);
context.lineTo(10,100);
context.lineTo(10,10);
context.stroke();

// Draw a square at x,y of size:
function drawSquare (xLoc, yLoc, size) {
context.beginPath();
context.moveTo(xLoc , yLoc );
context.lineTo(xLoc + size, yLoc );
context.lineTo(xLoc + size, yLoc + size);
context.lineTo(xLoc , yLoc + size);
context.closePath();
context.stroke();
}
// draw some squares
var squareSize = 100;
drawSquare(10, 10, squareSize);
drawSquare(120, 10, squareSize);

var squareSize = 140;
var padding = 10;
// Draw a square at grid-y grid-y:
function drawSquare(gridX, gridY) {
var startX = gridX * (squareSize + padding) + padding;
var startY = gridY * (squareSize + padding) + padding;
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(startX + squareSize, startY);
context.lineTo(startX + squareSize, startY + squareSize) ;
context.lineTo(startX, startY + squareSize) ;
context.closePath();
context.stroke();
}
drawSquare(0, 0);
drawSquare(1, 0);
drawSquare(2, 1);
drawSquare(0, 2);

// hella squares:
var x, y;
var numWide = 4;
var numTall = 4;
for(x=0; x < numWide; x++) {
for(y=0; y < numTall; y++) {
drawSquare(x,y);
}
}



// ★ The only grid-size variables :
var marginScale = 0.9;
var numColumns = 3;
// ★ context.translate(…) to center the grid
function adjustMargins () {
var size = gridSize * numColumns;
var extraSpaceX = canvas.width - size;
var extraSpaceY = canvas.height - size;
context.translate(extraSpaceX/2, extraSpaceY/2);
if (canvas.width > canvas.height) {
gridSize = canvas.height / numColumns;
}
else {
gridSize = canvas.width / numColumns;
}
}
// ★ record the new window size
function resize() {
var {width: w, height: h} = canvas.getBoundingClientRect();
canvas.width = w;
canvas.height = h;
setgridSize();
draw();
}
// ★ When the window is resized, redraw …
window.addEventListener("resize", resize);
// ★ Align a drawing function with the grid
function drawInGrid (gridX, gridY, drawingFunction) {
var halfGrid = gridSize / 2;
context.save();
context.translate(gridX * gridSize + halfGrid, gridY * gridSize + halfGrid);
context.scale(marginScale, marginScale);
drawingFunction();
context.restore();
}
// ★ Before we draw, measure everything
function draw () {
setgridSize();
adjustMargins();
context.save();
var x, y;
for(x=0; x < numColumns; x++) {
for(y=0; y < numColumns; y++) {
drawInGrid(x, y, veraSquare);
}
}
context.restore();
}


function randomNudge(gridFraction) {
var randAmount = gridSize * gridFraction;
return randAmount - Math.random() * (randAmount/2)
}
function drawSquare () {
var halfGrid = gridSize / 2;
var wiggleFraction = 0.3;
var startX = - halfGrid + randomNudge(wiggleFraction) ;
var startY = - halfGrid + randomNudge(wiggleFraction) ;
var endX = halfGrid + randomNudge(wiggleFraction) ;
var endY = halfGrid + randomNudge(wiggleFraction) ;
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(endX, startY);
context.lineTo(endX, endY);
context.lineTo(startX, endY) ;
context.closePath();
context.stroke();
}

function drawSquare (gridX, gridY) {
var wiggleFraction = gridY / numColumns / 2
var halfGrid = gridSize / 2;
var startX = - halfGrid + randomNudge(wiggleFraction) ;
var startY = - halfGrid + randomNudge(wiggleFraction) ;
var endX = halfGrid + randomNudge(wiggleFraction) ;
var endY = halfGrid + randomNudge(wiggleFraction) ;
…
}

function getColor(hue, sat, light, alpha) {
var h = hue * 360; // Hue space is color wheel 360 deg
var s = sat * 100;
var l = light * 100;
return `hsla(${h}, ${s}%, ${l}%, ${alpha})`
}
// … later
var h = gridX / numColumns;
var s = 0.5;
var l = gridY / numColumns;
var a = 0.15;
context.fillStyle = getColor(h, s, l, a); // ★

wait what?
# No Spirograph??!


Or just use `context.rotate()`
radial drawing
demo var increment = (2 * Math.PI) / numPoints;
context.save();
context.beginPath();
context.moveTo(0, maxRadius * radii[0]);
for (i= 0; i < radii.length; i++) {
context.lineTo(0, maxRadius * radii[i]);
context.rotate(increment);
}
context.closePath();
context.stroke();
context.restore();

Sketch. All. The. Time.
## Constraints By holding some things constant, we focus on the possibilities of the remaining parameters. * Music * [Haiku](https://en.wikipedia.org/wiki/Haiku) * [Dogme films](https://en.m.wikipedia.org/wiki/Dogme_95) * eg: only paint 2" squares * eg: only 400 pixels * eg: only black and white ## Gestalt principles of design
The Gestalt principles are a set of laws arising from 1920s' psychology, describing how humans typically see objects by grouping similar elements, recognizing patterns and simplifying complex images. Designers use these to engage users via powerful -yet natural- "tricks" of perspective and best practice design standards.
## Gestlat principles of design
* Gestalt principles are real. They are grounded in the *mechanics* of human perception.
* Art, design, and [Optical illusions](https://en.wikipedia.org/wiki/Optical_illusion) exploit artifacts of human perception.
## Some Gestalt principles are …
closure
* ["Primer of Visual Literacy"](https://www.amazon.com/Primer-Visual-Literacy-Donis-Dondis/dp/0262540290) by Donis A. Dondis.
## Quick Tips:
* Curate & crop
* Contrasting elements
* Accidents
* Steal and **give credit**
- Closure: Our brain fills in gaps.
- Proximity: We group closer-together elements.
- Continuation: We follow lines.
- Similarity: We look for differences and commonality of shape.


Make it **Big**.
Make it **red**.
Or make **many** of them.
😅
Note:
- Take 1000 photographs, and choose one.
- Crop: Your initial framing will be wrong. Direct attention. Cut out noise.
- Contrast: What is the focus, what will stand out?
- Accidents: Investigate, celebrate, incorporate your accidents.
- Fake it: It's art. It's all fake. Their is no purity, it's all for show.
- surge - instantly publish a website
- code pen - scratch-pad for websites
- live server - quick feedback
- visual studio code -- nice editor.
- shader toy -- not for beginners
- Daniel Schiffman's Coding Train - @shiffman
- @inconvergent instructions
- @mxsage instructions
- solving sol -- Sol Lewitt
- MDN Canvas API docs
- D3 - SVG & Javascruot visualization toolkit
- Processing - granpappy of creative coding envs
- Open Frameworks -- C++ creative coding
- ThreeJS - wrapper for canvas 3D API.
@knowuh