Empezando con Paper.js; Projectos e Items
Spanish (Español) translation by Marina Cardone (you can also view the original English article)
Quizás hayas oído sobre Paper.js. Entonces, empecemos con la pregunta: ¿qué es Paper.js? Es una librería que te permita crear y trabajar con gráficos vectoriales. El sitio oficial lo describe como la Navaja Suiza del Scripting de Gráficos Vectoriales.
A pesar del hecho de que la librería tiene mucho para ofrecer, es fácil de aprender incluso si nunca escuchaste de ella con anterioridad. En este tutorial comenzaré con lo más básico de la librería y luego nos moveremos a tópicos más complejos.
Utilizando PaperScript
Hay dos maneras de usar la librería. Puedes utilizar PaperScript, que es una extensión de JavaScript y ayuda a trabajar un poco más rápido, o puedes utilizar directamente JavaScript.
PaperScript es el mismo viejo JavaScript que siempre has utilizado. De todas formas, agrega soporte para operadores matemáticos para los objetos point
y size
. También simplifica la instalación de manejadores de eventos para Project
, View
y objetos Tool
del mouse.
Para PaperScript, necesitas utilizar la etiqueta script habitual con el type configurado como "text/paperscript". Si cargas el código externamente, también necesitas agregar una etiqueta <script>
con la URL apropiada para cargar tu código. Un último atributo que necesitas especifiar es data-paper-canvas="canvasId"
, o la versión corta canvas="canvasId"
, que le dice a la librería acerca del canvas con el que tiene que trabajar. El código de abajo crea un cuadrilátero en PaperScript.
1 |
<script type="text/paperscript" canvas="quad"> |
2 |
var path = new Path(); |
3 |
path.strokeColor = 'black'; |
4 |
var pointOne = new Point(100, 20); |
5 |
var pointTwo = new Point(-100, 100); |
6 |
var pointThree = new Point(300, 30); |
7 |
path.moveTo(pointOne); |
8 |
path.lineTo(pointOne + pointTwo); |
9 |
path.lineTo(pointTwo + pointThree); |
10 |
path.lineTo(pointOne + pointThree); |
11 |
path.closed = true; |
12 |
</script> |
Utilizando JavaScript
Si no estás cómodo con PaperScript, puede también utilizar JavaScript en tus proyectos. Tienes que agregar un par más de líneas de código si decides hacerlo de esta manera. La primera cosa que necesitas hacer es chequear si el DOM está listo porque no será posible trabajar con el canvas antes de eso. Luego puedes crear un proyecto y una vista utilizando el objeto paper
. Todas las clases de Paper.js y los objetos ahora estarán accesibles solo a través del objeto paper
.
Como mencioné anteriormente, tendrás que utilizar funciones Math en lugar de operadores cuando trabajes con Point y Size. El código debajo ilustra todas estas diferencias:
1 |
window.onload = function() { |
2 |
var canvas = document.getElementById('quad'); |
3 |
paper.setup(canvas); |
4 |
var path = new paper.Path(); |
5 |
path.strokeColor = 'black'; |
6 |
var pointOne = new paper.Point(100, 20); |
7 |
var pointTwo = new paper.Point(-100, 100); |
8 |
var pointThree = new paper.Point(300, 30); |
9 |
path.moveTo(pointOne); |
10 |
path.lineTo(pointOne.add(pointTwo)); |
11 |
path.lineTo(pointTwo.add(pointThree)); |
12 |
path.lineTo(pointOne.add(pointThree)); |
13 |
path.closed = true; |
14 |
paper.view.draw(); |
15 |
}
|
Como es evidente de los fragmentos de código anteriores, es relativamente fácil utilizar PaperScript cuando trabajas con Paper.js. Por lo tanto, todos los ejemplos de ahora en más estarán basados en PaperScript.
Jerarquía del Proyecto
Si alguna vez utilizaste una aplicación de diseño gráfico como Adobe Photoshop o Illustrator, debes estar familiarizado con el concepto de capas. Cada capa en estos programas tiene su propio contenido el cual, cuando se combina con otras capas, crea el resultado final. Capas similares también existen en Paper.js y pueden ser accedidas utilizando project.layers
.
Inicialmente, cada proyecto tiene una capa única que es accesible a través de project.activeLayer
. Cualquier nuevo item que crees será añadido a la capa activa actualmente como su hijo. Todos los hijos de una capa específica pueden ser accedidos utilizando la propiedad layer.children
de la capa activa.
Hay múltiples maneras de acceder a todos estos hijos. Si solo necesitas acceder al primer y último hijo de cualquier item, puedes utilizar item.firstChild
y item.lastChild
respectivamente. También puedes asignar un nombre específico a cualquier hijo y luego utilizar ese nombre para acceder a él luego. Digamos que una capa en la que estás trabajando tiene alrededor de 30 hijos. No es práctico ir a través de todos los ítems de a uno. Por esta razón, la librería tiene una propiedad layer.children.length
que puedes utilizar para obtener el número total de hijos y luego iterar sobre la lista utilizando un loop for
.
Este fragmento de código accede a varios hijos utilizando todas las propiedades que discutimos recién:
1 |
var circleA = new Path.Circle(new Point(45, 150), 45); |
2 |
var circleB = new Path.Circle(new Point(110, 150), 20); |
3 |
var circleC = new Path.Circle(new Point(165, 150), 35); |
4 |
var circleD = new Path.Circle(new Point(255, 150), 55); |
5 |
var circleE = new Path.Circle(new Point(375, 150), 65); |
6 |
var circleF = new Path.Circle(new Point(475, 150), 35); |
7 |
circleC.name = 'GreenCircle'; |
8 |
project.activeLayer.firstChild.fillColor = 'orange'; |
9 |
project.activeLayer.lastChild.fillColor = 'pink'; |
10 |
project.activeLayer.children[1].fillColor = 'purple'; |
11 |
project.activeLayer.children['GreenCircle'].fillColor = 'lightgreen'; |
12 |
for (var i = 3; i < 5; i++) { |
13 |
project.activeLayer.children[i].fillColor = 'tomato'; |
14 |
}
|
El ejemplo embebido debajo muestra el script en acción. Puedes verificar que el color de todos los círculos concuerda con el color que le asignamos en el código anterior.
También puedes utilizar el método item.parent
para acceder al padre de un ítem, como el método item.children
, que utilizaste para acceder a todos sus hijos. Siempre que crees un nuevo ítem, su padre siempre será la capa activa en el proyecto. Como sea, se puede cambiar añadiendo el ítem como hijo de otra layer
o group
.
Antes de continuar, déjenme explicar qué es un group
. Para ser honesto, ambos layer
y group
son bastante similares. La principal diferencia entre estos dos es que cualquier nuevo ítem que crees será agregado automáticamente a la capa activa, pero en el caso de un grupo, tendrás que agregarlos.
Hay múltiples formas en las que puedes agregar ítems a un grupo. Puedes pasar un ítem de arrays al grupo constructor y estos será agregados al array de item.children
del grupo. Para agregar elementos a un grupo una vez que fue creado, puedes utilizar la función item.addChild(item)
. También puedes agregar un hijo en un índice específico utilizando la función item.insertChild(index, item)
.
Eliminar estos ítems es tan facil como agregarlos. Para eliminar un ítem de un proyecto, puedes utilizar la función item.remove()
. Ten en mente que esto no destruirá el ítem, y puede ser agregado nuevamente al proyecto en cualquier momento que quieras. Si el ítem que removiste tiene algún hijo, todos los hijos serán removidos también. ¿Qué pasa si quieres eliminar todos los hijos pero mantener el ítem intacto? Esto puede lograrse utilizando la función item.removeChildren()
.
Entendiendo los Ítems
El término item
apareció varias veces en este tutorial. Entonces, ¿qué es? Todo lo que aparece en un proyecto de Paper.js es un item
. Esto incluye layers
, paths
, groups
, etc. Mientras que diferentes ítems tienen propiedades que son específicas a ellos, otras propiedades son aplicables a todos ellos.
Si intentas esconder un ítem del usuario, puedes hacerlo configurando el valor de item.visible
a false
. También puedes clonar cualquier ítem con la función item.clone()
. Esta función retorna el ítem clonado, que puede guardar una variable y manipularla luego. También puedes cambiar la opacidad de cualquier ítem utilizando la propiedad item.opacity
. Cualquier valor entre 0 y 1 hará el ítem traslúcido.
También puedes configurar un modo de mezcla para cualquier ítem utilizando la propiedad item.blendMode
. El modo de mezcla necesitar ser pasado como un string
. La librería también provee una propiedad item.selected
la que, si está configurada como true
, crea un contorno visual encima de ese elemento. Esto puede ser muy útil durante la depuración ya que te permite ver los patrones de construcción, puntos de segmentos individuales, y cajas de contorno de ítems.
Transformaciones del Ítem
Los ítems pueden fácilmente escalarse, rotarse o moverse alrededor en un proyecto de Paper.js. En esta sección, cubriré todas estas transformaciones brevemente.
Para cambiar la posición de un item
, puedes utilizar su propiedad item.position
y configurar la posición a un nuevo punto. Si quieres mover un elemento, puedes hacerlo con la ayuda del operador +=
.
También puedes escalar un ítem utilizando la función item.scale(scale)
. Esta función escalará el ítem partiendo de su punto central. Puedes escalar un ítem partiendo de otro punto si lo especificas en un segundo parámetro, como item.scale(scale, point)
. Además, la librería tambien te permite escalar ítems de manera diferente en dirección horizontal y vertical pasando dos números como parámetros, como item.scale(scaleX, scaleY)
.
Rotar ítems es similar a escalarlos. Puedes utilizar la función item.rotate(angle)
para rotar elementos a partir de su centro. El ángulo se especifica en grados, la rotación ocurre en la dirección de las agujas del reloj. Para rotar un ítem alrededor de un punto específico, puedes también pasar un punto como segundo parámetro, como item.rotate(angle,point)
.
El siguiente fragmento de código aplica todas las transformaciones y manipulaciones que discutimos recién a tres rectángulos diferentes.
1 |
var rectA = new Path.Rectangle(new Point(250, 70), new Size(120, 120)); |
2 |
rectA.fillColor = 'pink'; |
3 |
|
4 |
var rectB = rectA.clone(); |
5 |
rectB.fillColor = 'purple'; |
6 |
rectB.position += new Point(80, 80); |
7 |
rectB.opacity = 0.6; |
8 |
rectB.blendMode = 'color-burn'; |
9 |
rectB.scale(1.5); |
10 |
rectB.rotate(45); |
11 |
|
12 |
var rectC = rectB.clone(); |
13 |
rectC.fillColor = 'lightgreen'; |
14 |
rectC.position += new Point(-180, 0); |
15 |
rectC.blendMode = 'color-dodge'; |
16 |
rectC.scale(1.5); |
El código es bastante auto-explicativo. Cloné el rectángulo B del rectángulo A, y el rectángulo B adquiere todas las propiedades del rectángulo A. Lo mismo va para el rectángulo B y C.
Nota que utilicé el operador +=
que discutimos antes para mover los ítems. Este operador mueve los ítems relativamente de sus posiciones anteriores en lugar de utilizar valores absolutos.
El ejemplo posterior te muestra el resultado final luego de todas estas transformaciones. Puedes intentar diferentes modos de mezcla o cambiar otras propiedades en el ejemplo para ver cómo afectan el resultado final.
Pensamientos Finales
Como mencioné anteriormente, Paper.js es fácil de aprender y te permite crear gráficos vectoriales fácilmente. Este tutorial cubre lo más básico que necesitas saber para trabajar con la librería. Próximamente, publicaremos el próximo tutorial de la serie, el que discute cursos y geometrías en detalle.
Mientras tanto, es importante que notes que JavaScript se ha convertido en uno de los lenguajes de facto de trabajo en la web. Esto no es sin curvas de aprendizaje, y está lleno de frameworks y librerías para mantenerte ocupado, también. Si estás buscando más recursos adicionales para estudiar o utilizar en tu trabajo, chequea qué tenemos disponible en el marketplace de Envato.
Hasta entonces, te sugiero que crees unos ejemplos básicos por ti mismo y practiques lo que has aprendido hasta ahora. Si tienes alguna pregunta sobre este tutorial, déjamelo saber en los comentarios.