I thought adding a picture gallery to a cordova app would be a piece of cake when I started a mobile project a few months ago. I was surprised to discover that the large cordova community had never fully developped such a useful plugin!
This article aims to save you a few headaches and help you build a gallery with pictures coming from the picture library on Cordova with the plugin we've forked and enhanced. It also explains how to display those images as squares with the correct orientation and without stretching the pictures, like this:
Every plugin I found digging in the forks of the official plugin was not what I needed.
In order to build a gallery, you are bound to need:
So we forked the johnnyoin's plugin to retrieve the pictures from the latest to the n-th, a parameter that you can set.
On Android 6, you will also need to install the permission plugin to ask for the permission to access the gallery. Here is how to use it:
++pre>const pictures = [];
const getDevicePictures = (pictureCount) => {
// CameraRoll is a global object added by the plugin
CameraRoll.getPhotos((picture) => {
// picture is an empty object when loading is finished
if (picture.path) {
picture.path = picture.path.replace('assets-library://', 'cdvfile://localhost/assets-library/');
pictures.push(picture);
}
}, (err) => {
console.error('An error occured :(')
},
{ count: pictureCount });
}
document.addEventListener('deviceready', () => {
const pictureCount = 7;
// The following line works only with Ionic, adapt it to your needs
if (ionic.Platform.isAndroid()) {
const permissions = cordova.plugins.permissions;
const readPermission = permissions.READ_EXTERNAL_STORAGE;
permissions.hasPermission(
readPermission,
permissions.requestPermission(readPermission, () => getDevicePictures(pictureCount))
);
} else {
getDevicePictures(pictureCount);
}
});++/pre>
On iOS, the performance is great on all devices without having to scale down the images.
On Android, displaying multiple high-resolution pictures on a cordova app will make your app painfully slow. To fix that, the only solution we found was to retrieve thumbnails instead of the full images.
++pre>CameraRoll.getPhotos((picture) => {
// `picture` is an object with a `path`, a `date`
// on android there is a`thumbnailPath` that you can use to display a thumbnail.
console.log(picture);
}++/pre>
When you have retrieved the pictures, the challenge is to display them as square, without stretching them and keeping the good image orientation.
This orientation issue is fixed by using an html ++code>img++/code> element, but it prevents you from using the css property ++code>background-size: cover++/code> which usually fix stretching issues.
Hopefully there is an awesome css property that will do the trick, object-fit.
Here is an example in AngularJs:
++pre><div
class="thumbnail"
ng-repeat="picture in pictures"
>
<img
class="image"
ng-src="{{ picture.thumbnailPath || picture.path }}"
/>
</div>++/pre>
with the following css:
++pre>.thumbnail {
width: 33vw;
height: 33vw;
}
.image {
width: 100%;
height: 100%;
object-fit: cover;
}++/pre>
You can easily get a gallery which looks like this:
Your camera roll should now be functional, but the Android thumbnails are likely to appear rotated.
To fix this, the plugin also returns the orientation of the picture on android. It can be use with a ++code>transform: rotate++/code>like this in AngularJs:
++pre>div
<div
class="thumbnail"
ng-repeat="picture in pictures"
>
<img
class="image"
ng-style="{'transform': 'rotate(' + (picture.orientation || 0) + 'deg)'}"
ng-src="{{picture.thumbnailPath || picture.path}}"
/>
</div>++/pre>
Now you should have a fully functional and good looking picture gallery!
Pull requests are welcome!
If you are more a react-native person, at BAM we made a plugin too a few months ago, but now the CameraRoll API of React Native has a full support out-of-the-box of iOS and Android. Yay!
Article you may like: How to get images from camera roll with React Native on Android?