Advertisement
  1. Code
  2. iOS SDK

Una Introducción a Quartz 2D

by
Difficulty:BeginnerLength:LongLanguages:

Spanish (Español) translation by Javier Salesi (you can also view the original English article)

¿Qué es Quartz 2D?

Quartz 2D es el motor de dibujo 2D de Apple, un importante componente del framework Core Graphics. Con frecuencia puedes ver que a Quartz 2D se le llama Core Graphics o simplemente CG.

Quartz 2D utiliza el "modelo del pintor". En el modelo del pintor, cada operación de dibujo sucesiva aplica una capa de "pintura" a un "lienzo" resultante, con frecuencia llamado una página. Piensa en ésto como un artista que trabaja en una pintura. Si el artista fuera a pintar el lienzo completo de azul y luego pinta algunas nubes en en lienzo entonces las nubes cubrirían al azul debajo de ellas. Una vez que algo es "pintado" en el lienzo, no puede ser cambiado sino añadir mas pintura sobre eso.

Todo lo que se pinta en Quartz 2D se hace a través de un contexto gráfico de tipo CGContextRef. Con una referencia a un contexto gráfico, puedes usar las funciones de Quartz 2D para dibujar al contexto, ejecutar operaciones, tales como trasladar el contexto, y cambiar los parámetros del estado gráfico, como el grosor de una línea y color de relleno. Quartz 2D es una API basada en C, como tal invocarás las funciones de C pasando el contexto como un parámetro.

Para dibujar en la pantalla en iOS, debes tomar como subclase un UIView y sobreescribir su método drawRect(_:). Es dentro de éste método drawRect(_:) que harás cualquier dibujo personalizado. Nunca deberías llamar al método drawRect(_:) directamente en tu código. Si necesitas actualizar la pantalla con nuevos comandos de dibujo, deberías llamar a los métodos setNeedsDisplay() o setNeedsDisplayInRect(_:).

Cuando se usa Quartz 2D en iOS, la coordenada (0,0) se ubica en la esquina superior izquierda de la pantalla. La coordenada x se incrementa mientras te mueves a la derecha y la coordenada y se incrementa mientras te mueves hacia abajo.

A través de éste tutorial, puedes querer consultar la guía de programación para Quartz 2D. El objetivo de éste tutorial es iniciarte en el uso de Quartz 2D. Hay mucho que no será cubierto y para apreciar completamente todo lo que Quartz 2D tiene para ofrecer te sugiero leer la guía de programación.

Dejando atrás esta breve introducción, comencemos a usar Quartz 2D.

1. Preparando un UIView para Dibujar

Asumiendo que tienes un proyecto abierto y listo para empezar a trabajar con Quartz 2D, los pasos que necesitas dar son muy simples. Necesitarás crear una clase que es una subclase de UIView, agregar un view desde la librería Object a tu proyecto en Interface Builder, y establecer la clase de view en la subclase UIView que creaste. Veamos esto paso por paso.

Paso 1: estableciendo la subclase UIView

Ve a File > New > File... En la sección iOS, selecciona Source y luego elige Cocoa Touch Class como la plantilla.

New Cocoa Touch Class

En la sguiente pantalla, da un nombre a tu clase, asegúrate que es una subclase UIView, y establece el lenguaje en Swift. Pulsa Next y elige donde guardar tu nueva subclase.

Set File Options

Si ves la fuente de tu clase recién creada, verás el méodo drawRect(_:). Está actualmente deshabilitado como comentario, pero cambiaremos eso en unos momentos.

Paso 2: Agregando un View y estableciendo la Clase

Abre la storyboard del proyecto y abre Object Library ubicada a la derecha. En el campo de búsqueda abajo, ingresa "UIView" para filtrar objetos que no nos interesan.

Show Object Library

Arrastra una instancia de UIView al view controller. Con el view seleccionado, abre el Indentity Inspector a la derecha y cambia Class a como hayas nombrado la subclase.

Set Class on View

Cualquier código que agregues dentro del método drawRect(_:) será dibujado cuando la subclase UIView sea instanciada. La view automáticamente configura el entorno de dibujo para que puedas empezar a dibujar inmediatamente. La view configura el CGContextRef mencionado al inicio de esta lección y está dentro del método drawRect(_:) del que obtendrás referencia.

2. Proyecto de Inicio

Para comenzar rápidamente, he proporcionado un proyecto de inicio que tiene todos los view ya preparados y listos para usar. Las subclases UIView son nombradas como el comando de dibujo que estaremos explorando. Por ejemplo, cuando estamos aprendiendo a dibujar líneas la correspondiente clase será nombrada DrawLinesView.

Puedes descargar el proyecto de inicio desde Github. Comenzaremos a codificar en el próximo paso.

3. Obteniendo una Referencia al Contexto Gráfico

Antes de que puedas dibujar cualquier cosa, necesitas obtener una referencia al contexto gráfico. Esto se logra como sigue.

Ésto regresa un tipo opaco, CGContextRef,  y pasarás éste contexto en las funciones C para hacer el dibujo personalizado. Ahora que sabemos como obtener una referencia al contexto gráfico podemos comenzar a explorar los comandos de dibujo.

4. Dibujar una Línea

Si has descargado el proyecto de inicio, abre DrawLineView.swift y agrega lo siguiente al método drawRect(_:).

Primero obtenemos una referencia al contexto de dibujo como se discutió anteriormente. Debido a que ésto es algo que haremos para cada ejemplo, no mencionaré ésto en los próximos ejemplos.

La función CGContextSetStrokeColorWithColor(_:_:) establece el color con el que la línea será dibujada o trazada. Los parámetros que pasamos son el contexto gráfico y el nuevo color del trazo.

Si piensas en el contexto gráfico como el lienzo de un pintor, entonces la función CGContextMoveToPoint(_:_:_:) mueve el pincel a un punto particular en el lienzo desde el cual comenzar o continuar dibujando. Imagina dibujar en un pedazo de papel, levantando tu mano, y mover a una parte diferente del papel y continuar dibujando. Esencialmente eso es lo que éste método logra. Pasamos el contexto gráfico y una coordenada x y y desde donde comenzamos a dibujar.

La función CGContextAddLineToPoint(_:_:_:) toma como parámetros el contexto gráfico, el valor de x para el final del segmento de línea, y el valor y para el final del segmento de línea. Después de agregar el segmento de línea, el punto actual será establecido al punto final del segmento de línea. Comenzamos la operación de dibujo en (0,0), después de ésta operación de dibujo el cursor o pincel está en (200,200).

Finalmente, para hacer el dibujo necesitas llamar a la función CGContextStrokePath(_:) pasando el contexto gráfico. Ésta función simplemente dibuja una línea a lo largo de la ruta que especificamos.

Compila y ejecuta el proyecto de ejemplo para ver el efecto.

5. Dibujar un Rectángulo

Abre DrawRectangleView.swift y agrega lo siguiente al método drawRect(_:). Deberías estar familiarizado con las dos primeras líneas a estas alturas.

La función CGRectMake(_:_:_:_:) es parte de CGGeometry y proporciona una forma fácil de crear una estructura CGRect. Como su nombre lo implica, CGRect es una estructura que contiene la ubicación y dimensiones de un rectángulo. Un CGRect tiene dos campos, origin y size, que son un CGPoint y un CGSize respectivamente. Si no estás familiarizado con éstos tipos de datos, entonces lee la Guía de CGGeometry.

Creamos un constante rectangle, usando la funcilón CGRectMake(_:_:_:_:) y llamamos a la función CGContextAddRect(_:_:_:_:), que toma como parámetros el contexto gráfico y un CGRect. Finalmente, llamamos a CGContextStrokePath(context) para dibujar el rectángulo.

Compila y ejecuta el proyecto para ver el rectángulo dibujado en la pantalla.

6. Dibujar un Círculo

Abre DrawCircleView.swift y actualiza el método drawRect(_:) como sigue.

Te puedes preguntar ¿por qué estamos llamando a CGRectMake(_:_:_:_:) cuando estamos dibujando un círculo? El rectángulo es el área en la que el círculo debe caber. En el código de arriba, creamos un círculo al usar un cuadrado. Si quieres dibujar un óvalo o una elipse, entonces necesitas hacer el rectángulo con la forma mas rectangular.

Entonces llamamos a la función CGContextAddEllilpseInRect(_:_:), que toma como parámetros el contexto gráfico y el rectángulo en el cual dibujar la elipse. El círculo es dibujado al llamar a CGContextStrokePath(_:), pasando el contexto gráfico.

7. Dibujando un Arco

Abre DrawArcView.swift y agrega el siguiente código dentro del método drawRect(_:).


La función CGContextAddArc(_:_:_:_:_:_:_:) toma pocos parámetros:

  • el contexto gráfico
  • el valor x para el centro del arco
  • el valor y para el centro del arco
  • el radio del arco
  • el ángulo para el punto inicial del arco, medido en radianes desde el eje x positivo.
  • el ángulo para el punto final del arco, medido en radianes desde el eje x positivo.
  • un valor de 1 para crear un arco en sentido de las manecillas del reloj o un valor de 0 para crear un arco en sentido contrario a las manecillas del reloj.

8. Dibujando un Trazado 

Para dibujar formas mas complejas, creas una ruta y la  trazas. Observa el método drawRect(_:) en DrawPathView.swift.

En el método drawRect(_:), llamamos a CGContextAddLineToPoint(_:_:_:) un número de veces para crear un triángulo. Nota que el triángulo no está lleno, solo trazado. En el próximo paso, veremos como rellenar el triángulo con color.

9. Rellenando una Ruta

Abre FillPathView.swift y actualiza el método drawRect(_:) como se muestra abajo.

En el paso previo, trazamos una ruta, pero también puedes rellenar una ruta con un color particular. En el método drawRect(_:) de arriba, comenzamos creando una ruta para el mismo triángulo como en el ejemplo previo. Ésta vez establecemos un color de relleno usando la función CGContextSetFillColorWithColor(_:_:) y llamamos a CGContextFillPath(_:) en lugar de CGContextStrokePath(_:).

10. Rellenando una Elipse

Aparte de rellenar rutas, también puedes rellenar elipses y rectángulos. En este ejemplo, rellenaremos una elipse. Rellenar un rectángulo, sin embargo, es muy similar. La documentación te dirá como se hace. Actualiza el método drawRect(_:) en FillEllipseView.swift como se muestra abajo.

La mayoría de éste código a estas alturas debería serte familiar. Estamos usando una nueva función, CGContextSetLineWidth(_:_:) para establecer el grosor de la línea y llamamos a CGContextFillEllipseInRect(_:_:) para rellenar la elipse. Ésta función toma como parámetros el contexto de gráficos y el rectangulo en el cual rellenar la elipse.

11. Agregando Líneas

La función CGContextAddLines(_:_:_:) es una función útil cuando tienes un número de segmentos de líneas rectas conectadas que deseas dibujar. Aquí recreamos el triángulo anterior en los ejemplos, usando la función CGContextAddLines(_:_:_:). Agrega el siguiente código a AddLinesView.swift.

La función CGContextAddLines(_:_:_:) toma como parámetros el contexto de gráficos, un arreglo de valores que especifican los puntos de inicio y fin de los segmentos de línea para dibujar como estructuras CGPoint, y el número de elementos en el arreglo. Nota que el primer punto en el arreglo especifica el punto de inicio.

12. Dibujando un Degradado

Con Quartz 2D, es fácil dibujar degradados. Son soportados tanto degradados lineales como radiales. En este ejemplo, dibujaremos un degradado lineal. La documentación te ayudará si estás interesado en dibujar degradados lineales. Agrega lo siguiente a DrawGradientView.swift.

La función CGContextDrawLinearGradient(_:_:_:_:_:) toma como parámetros:

  • el contexto de gráficos
  • una estructura CGGradient
  • un punto de inicio
  • un punto final
  • modificadores opcionales que especifican si el relleno se extiende mas allá del punto de inicio o del punto final.

Una estructura CGGradient define una suave transición entre colores a través de un área. Tiene un espacio de color, dos o mas colores, y una ubicación para cada color. Las constantes colorspace, colors, y locations en el ejemplo de arriba representan éstas partes que conforman el CGGradient.

Para dibujar el degradado, llamamos a la función CGContextDrawLinearGradient(_:_:_:_:_:), pasando el contexto gráfico, el CGGradient, valores de inicio y fin, y 0 para indicar que el relleno debería extenderse mas alla de a ubicación inicial.

13. Dibujando una Sombra

Una sombra es una imagen dibujada debajo, y con un desplazamiento de, un objeto gráfico para que la sombra imite el efecto de una fuente de luz proyectada sobre el objeto gráfico. -Guía de Programación de Quartz 2D

Hay dos funciones que puedes usar para dibujar sombras, CGContextSetShadow(_:_:_:) y CGContextSetShadowWithColor(_:_:_:_:). Cuando se usa CGContextSetShadow(_:_:_:), a todos los objetos dibujados se les aplica una sombra usando un color negro con un alfa de 1/3. La función CGContextSetShadowWithColor(_:_:_:_:) te permite especificar un color para la sombra.

Veamos como funciona esto en la práctica. Agrega lo siguiente a SetShadowWithColor.swift.

Cuando se dibujan sombras, deberías guardar el estado del contexto gráfico, elaborar cualquier cambio requerido, y luego restablecer el estado gráfico. Llamamos a CGContextSaveGState(_:) para guardar el estado actual del contexto gráfico, especificar un desplazamiento para la sombra, shadowOffset, y llamar a la función CGContextSetShadowWithColor(_:_:_:_:). Éstas funciones toman como parámetros:

  • el contexto gráfico
  • el desplazamiento para la sombra
  • la cantidad de desenfoque
  • el color de la sombra

El resto del código debería serte familiar. Finalmente, restablecemos el contexto gráfico al llamar a CGContextRestoreGState(_:), pasando el contexto gráfico.

14. Dibujando una Cara Feliz

Pensé que sería divertido finalizar este tutorial al dibujar una simple cara feliz usando lo que hemos aprendido a través de éste tutorial. Agrega lo siguiente a DrawHappyFaceView.swift.

La implementación del método drawRect(_:) debería tener sentido por ahora y deberías tener una cara feliz dibujada en la pantalla.

Conclusión

Ésto llega al final del tutorial. Ahora deberías tener una comprensión básica de como ejecutar dibujos personalizados usando el motor de dibujo Quartz 2D. Espero que hayas aprendido algo útil al leer éste tutorial.

¡Sé el primero en conocer las nuevas traducciones–sigue @tutsplus_es en Twitter!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.