Hoy vamos crear una eficiente galería de fotos con zoom para nuestra app mobile de forma muy muy sencilla, gracias a los componentes SlideBox y Scroll de Ionic Framework.

¿Quieres aprender Ionic Framework? ¡¡Mira mi curso de ionic completamente gratuito!!

Recordemos que Ionic es un framework de front-end para webs mobile que usa AngularJS y que podemos usar sin problema desde PhoneGap. Para más información, podéis revisar anteriores tutoriales, donde hemos hecho una Introducción a PhoneGap con Ionic, hemos profundizado en la navegación de apps PhoneGap gracias a Ionic y el routing de AngularJS, y hemos aprendido a usar el componente SlideBox de Ionic.

Resultado esperado

Antes que nada veamos lo que queremos conseguir, en el siguiente CodePen:

See the Pen Ionic zoomable images gallery by Enrique (@-kaik-) on CodePen.

Cabe destacar que para hacer zoom necesitamos realizar el gesto pinch, por lo que necesitaremos un dispositivo que soporte multi-touch.
Lo más sencillo para probar esta característica, será ver el CodePen desde el navegador del smartphone / tablet.

Componentes de Ionic

Si te interesa utilizar el nuevo SlideBox de Ionic, mira este tutorial actualizado

Veamos en primer lugar los componentes de Ionic que vamos a utilizar.

IonContent

La directiva ion-content es el contenedor más básico de Ionic. Lo aprovechamos para introducir todo nuestro contenido, aunque en este ejemplo ni siquiera sería necesario.
Lo usaremos del siguiente modo:

<ion-content>
<!-- los componentes de mi galería -->
</ion-content>

SlideBox

El componente ion-slide-box es un contenedor multi-página, que permite de forma automática desplazarse entre sus páginas arrastrando hacia los lados, con el gesto swipe.

Cada una de las páginas que contiene, se definen con la directiva ion-slide, y en su interior, podemos definir el contenido que queramos.

Lo integraríamos en nuestro HTML con una estructura como la siguiente:

<ion-slide-box>
<ion-slide>
<div class="first"><h1>First Slide</h1></div>
</ion-slide>
<ion-slide>
<div class="second"><h1>Second Slide</h1></div>
</ion-slide>
</ion-slide-box>

Tiene una API que permite diferentes opciones, pero nosotros no vamos a necesitar usarla.

Scroll

La directiva ion-scroll crea un contenedor que nos permite desplazarnos por su contenido haciendo scroll, y que además, entre sus opciones, nos ofrece poder hacer zoom con el típico gesto pinch de separar o acercar dos dedos.

Como punto a destacar, es importante decir que es necesario definir las dimensiones del scroll, así como de su contenido, para permitir hacer scroll correctamente.

Se utiliza del siguiente modo:

<ion-scroll zooming="true" direction="xy" style="width: 500px; height: 500px">
<div style="width: 1000px; height: 1000px; background: url('my/img/url')"></div>
</ion-scroll>

Veamos algunos de los atributos de ionScroll que nos interesan:

  • zooming: Nos permite hacer zoom en el contenido con el gesto pinch
  • direction: Define los ejes en los que se puede hacer scroll.
  • min-zoom: Estable el zoom mínimo que podemos hacer (es opcional)
  • locked: Por defecto es true. En caso de establecer 2 direcciones de scroll (xy), si lo ponemos a false nos permite desplazarnos en ambas direcciones a la vez.

$ionicSlideBoxDelegate

La directiva ionScroll cuenta con la posibilidad de utilizar un delegate llamado $ionicSlideBoxDelegate, que nos permite manipularla desde fuera (en nuestro controlador principal, por ejemplo).

En este caso, nos interesará poder saber qué diapositiva es la que estamos visualizando en cada momento, mediante la llamada currentIndex():

$ionicSlideBoxDelegate.currentIndex()

Y con esto tenemos todo lo que necesitamos de ionic.

Directivas de AngularJS

Para nuestro ejemplo, vamos a ayudarnos de un par de directivas predefinidas de AngularJS (además de ng-app y ng-controller) muy básicas:

  • ng-repeat: Nos permite repetir un mismo contenido a lo largo de una iteración. Lo usaremos para añadir un ion-slide por cada imagen de mi galería. A destacar que podemos obtener el índice de la repetición con $index, como veremos en el código.

  • ng-if: Permite determinar si un contenido debe añadirse o eliminarse del DOM. (Es mas eficiente que la directiva ng-show, ya que esta última solo cambia la propiedad display del elemento, que sigue estando en el DOM).

Entrando en código

Nuestra aplicación constará de 3 archivos: index.html, style.css y app.js, donde definiremos el código html, los estilos y el javascript, respectivamente.

Index.html

<html ng-app="demoApp">
<head>
<meta charset="utf-8">
<title>
Zoomable images
</title>

<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">

<!-- importamos ionic -->
<link href="//code.ionicframework.com/1.0.0-beta.13/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/1.0.0-beta.13/js/ionic.bundle.js"></script>

<!-- importamos nuestro CSS y JS -->
<link href="style.css" rel="stylesheet">
<script src="app.js"></script>
</head>


<body class="padding" ng-controller="DemoCtrl">
<ion-content>

<ion-slide-box>

<ion-slide ng-repeat="image in images">

<div class="container" ng-if="slideVisible($index)" class="scrollCanvas">
<ion-scroll class="scrollCanvas" zooming="true" min-zoom="1" direction="xy" locked="false">
<div class="image" style="background-image: url(
{{image}} )"></div>
</ion-scroll>

</div>
<!-- añadimos un espacio vacio para evitar problemas con slidebox y las diapositivas ocultas. Ver post dedicado a SlideBox para más información. -->
<div>&nbsp;</div>

</ion-slide>

</ion-slide-box>


</ion-content>

</body>
</html>

Destacar que para poder tener muchas imágenes sin que eso nos penalice a la hora de navegar entre ellas (recordemos que queremos ejecutar este código en una app mobile, que no destacan precisamente por su rendimiento), lo que hacemos es incluir solo 3 imágenes en el DOM: la actual, la anterior y la posterior.

Esto lo hacemos creando una función slideVisible en el controlador, a la que pasamos el índice, y la que nos devolverá true o false en función de si debemos incluir o no la imagen en el slide, cosa que haremos con ng-if.

DETALLE: A priori parece que podríamos usar el ng-if en el propio elemento ion-slide, pero lo único que conseguiríamos es generar menos diapositivas, lo que causará problemas en la navegación del componente ion-slide-box. Fijaros que el número de diapositivas no cambia en ningún momento: para el caso de no incluir imágen, creamos una diapositiva vacía con un único espacio.

style.css

Poco cabe destacar de la hoja de estilos. En todo caso, ver como definimos las dimensiones del componente scroll y de su contenido, así como el centrado de la imagen mediante la clase .image.

ion-content{
background-color: grey;
}


.container{
background-color: grey;
}


.scrollCanvas{
width: 100%;
height: 100%;
background-color: black;
}


.image{
width: 100%;
height: 600px;
background-size: contain;
background-repeat: no-repeat;
background-position: center, center;
}

app.js

Nuestro controlador es extremadamente sencillo, con un array de URLs de imágenes, y la función slideVisible.
Sólo cabe destacar como inyectamos el servicio $ionicSlideBoxDelegate para poderlo utilizar en la función que determina si la imagen debe mostrarse o no.

angular.module('demoApp', ['ionic'])
.controller('DemoCtrl',function($scope, $ionicSlideBoxDelegate) {

$scope.images = [
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSeuNVzlDcFunjMxXa3_ui65_fJgwvT8Eq0M5GluaIbl5DJYLOaCI0McDw",
"https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTg_tgzzbgiZ9QnAe8-xtbnBe04jJ7Ke7s60llFYcwhiZqFQO1BQ6mqdh0W",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQamBcgUQKpzafi4MNW6WYnS6wxvJCiQjKc_uoAz4ycmyHO2qvV0q4sCazG",
"https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSqXQBbyRukbsao9ljVsi8SMW7GWVlXl2By4jS7QiqFNr3ChFf9Lw",
"https://ga-core.s3.amazonaws.com/production/uploads/program/default_image/2034/Angularjs-Bootcamp-LONDON.jpg",
]

$scope.slideVisible = function(index){
if( index < $ionicSlideBoxDelegate.currentIndex() -1
|| index > $ionicSlideBoxDelegate.currentIndex() + 1){
return false;
}
return true;
}

});

Y con esto ya estaría, puedes disfrutar de tu nueva galería de imágenes en el móvil, realizada de forma muy sencilla y eficiente, como se le pide a una aplicación PhoneGap.

Os dejo con una foto del resultado.

phonegap ionic image gallery with zoom

Recuerda que puedes ver el codigo completo en acción desde el CodePen del inicio. Y si quieres aprender un poco más de AngularJS y mejorar aún la eficiencia en la carga de imágenes de tu galería, te recomiendo que leas el tutorial Directivas elemento en AngularJS: lazy-loading images.

¡Saludos!