Desenhando com Python no Navegador

Bernardo Fontes

Ribeirão Preto / SP

25 de Outubro de 2019

Olar!


berinhard.github.io/sketches

twitter - @bbfontes

berinfontes.com/talks

## Programação Criativa - Programar para a **expressão** ao invés de resolução de problemas - A **experimentação** precedendo a funcionalidade ou assertividade - Tem com música, vídeo, desenho, fotografia...
## Generative Art - Objetos **criados com código** - O **algoritmo como sistema autônomo** determina o comportamento da composição - A pessoa controlando a máquina cria e programa os algoritmos e **controla sua randomicidade** - Programação + **técnicas**

Georg Ness - Generative Computergrafik

1965

23-Ecke (Polygon of 23 vertices)

Frieder Nake

1965

Hommage à Paul Klee

Vera Molnár

1968 / 1969

Interruptions

Lillian Schwartz

1970

Pixillation, photographic film stills

## Hoje em dia...

@manoloidee

@inconvergent

Saskia Freeke

@sasj_nl

Frederik Vanhoutte

@wblut

## O que tem em comum? - Todos usam [Processing](https://processing.org/)
## Processing - Uma IDE que usa Java para servir como um **sketchbook** - Ideal para estudantes e artistas visuais por conta de sua **API simples e versátil** - Possui um **modo Python** ([Jython](http://www.jython.org/) por baixo dos panos)
## Um exemplo ```python # Author: Berin # Sketches repo: https://github.com/berinhard/sketches from random import choice WHITE = color(228, 228, 228, 200) RED = color(228, 12, 10, 200) BLACK = color(17, 17, 17) def setup(): size(900, 900) noFill() background(BLACK) def draw(): radius = random(20, 300) x_positions = range(0, width, 20) y_positions = range(0, height, 20) x, y = choice(x_positions), choice(y_positions) if random(1) < 0.5: c = WHITE else: c = RED stroke(c) while radius > 20: ellipse(x, y, radius, radius) radius -= 20 if frameCount > 100: noLoop() ```
## Incríve né!? - Mas.....
## Problemas do Modo Python - É necessário **ativá-lo manualmente** pela IDE do Processing - Praticamente **preso à IDE** do Processing - Não tem acesso as **libs Python instaladas no sistema** - Ainda está no **Python 2.7** - O Jython não possui **nenhum** roadmap para migrar pra Python 3
### Python 2.7 "acaba" em 2 meses ![clock](images/clock.gif) Será que temos alternativas?
### 2 principais alternativas com limitações - [Pesquisa](https://github.com/villares/Resources-for-teaching-programming/blob/master/README.md) do Alexandre Villares - [p5py](https://github.com/p5py/p5) - Python 3 puro - Reescrita ainda incompleta - API bastante diferente da API do Processing - [BrythonIDE](https://esperanc.github.io/brythonide/) - Prof. Esperança - COPPE/UFRJ - Roda no navegador - Utiliza [Brython](https://brython.info/) - Tem questões de performance
### Quem poderá nos ajudar? ![clock](images/chapolin.gif)
## Python + p5.js [![clock](images/pyp5js.png)](https://berinhard.github.io/pyp5js/)
`$ pip install pyp5js` `$ pyp5js serve`
## API Básica ```python from pyp5js import * from random import choice colors = [ (235, 235, 0), (235, 0, 235), (0, 235, 235), ] def setup(): createCanvas(900, 900) background(27) rectMode(CENTER) def draw(): size = 20 for x in range(0, width + size, size): # itera por colunas for y in range(0, height + size, size): # itera por linhas fill(choice(colors)) # escolhe uma cor randomicamente if random(1) > 0.5: # condição para desenhar um retângulo ou círculo ellipse(x, y, size, size) else: rect(x, y, size, size) noLoop() ```
### O que acontece embaixo dos panos? - A interface web é uma abstração para a CLI - A criação do sketch via form equivale ao comando `$ pyp5js new sketch_name` - O diretório `~/sketchbook-pyp5js/sketch_name/` é criado com todo o código e arquivos necessários - Ao acessar `/sketch/pybr_001/` a lib "compila" o código Python para código JS - A compilação é através do comando `$ pyp5js transcrypt pybr_001` - Dentro do diretório do sketch, os JS finais são colocados dentro do diretório `target`
## API de Eventos ```python from pyp5js import * from random import choice shape_type = 'RECT' shape_size = 30 live_shapes = [] def add_shape(): x, y = mouseX, mouseY colors = [ (235, 235, 0), (235, 0, 235), (0, 235, 235), ] live_shapes.append(( shape_type, x, y, shape_size, choice(colors)) ) def keyPressed(): global shape_type, shape_size if key == 'c': shape_type = 'CIRCLE' elif key == 'r': shape_type = 'RECT' elif key == 'a': shape_size += 5 elif key == 'x': shape_size -= 5 def mouseClicked(): add_shape() def mouseDragged(): add_shape() def setup(): createCanvas(900, 900) rectMode(CENTER) def draw(): background(27) for format, x, y, size, c in live_shapes: noStroke() fill(c) if format == 'RECT': rect(x, y, size, size) elif format == 'CIRCLE': ellipse(x, y, size, size) x, y = mouseX, mouseY noFill() stroke(240) if shape_type == 'RECT': rect(x, y, shape_size, shape_size) elif shape_type == 'CIRCLE': ellipse(x, y, shape_size, shape_size) ```
## Manipulando o DOM ```python from pyp5js import * add_library("p5.dom.js") rect_base_size = 30 positions = [] w_size, h_size = None, None def setup(): global w_size, h_size createP("Hi! This is an example of how to use p5.dom.js with pyp5js") # creates a container div slider_div = createDiv() slider_div.style("display", "block") # creates the sliders w_size = createSlider(0, 600, 100) w_size.style('width', '50%') h_size = createSlider(0, 600, 100) h_size.style('width', '50%') # adds the slider to the container div slider_div.child(h_size) slider_div.child(w_size) createCanvas(600, 600) # fixes initial grid positions for x in range(-rect_base_size, width + rect_base_size, rect_base_size): for y in range(-rect_base_size, height + rect_base_size, rect_base_size): positions.append((x, y)) noFill() strokeWeight(2) rectMode(CENTER) def draw(): background(255) for x, y in positions: rect(x, y, w_size.value(), h_size.value()) ```
## Mas nem tudo são flores... ![](images/chapolin_2.gif) - No fundo, estamos usando JS e isso traz algumas questões - As vezes o uso de memória não é otimizado - Não ter toda a standard lib do Python - Algumas [outras diferenças](https://transcrypt.org/docs/html/differences_cpython.html) do CPython
## Já vivemos no futuro ![](images/astucia.gif) - [Pyodide](https://github.com/iodide-project/pyodide): The Python scientific stack, compiled to [WebAssembly](https://webassembly.org/) - Já existe uma [issue aberta](https://github.com/berinhard/pyp5js/issues/73) para migrar o pyp5js
## Call to Action! - Usem, quebrem, desmontem o `pyp5js` - Ajudem a melhorar a documentação - Criem novos exemplos e abram PRs com eles - Estarei presente nos Sprints

No Garoa (São Paulo) toda última terça-feira do mês

Em Recife toda última quarta-feira do mês

processing-brasil@googlegroups.com

Obrigado!

berinfontes.com

berinhard.github.io/sketches

twitter - @bbfontes