jeudi 27 mai 2010

Animation pour zoomer sur une image

En regardant un peu l'application de démo (KitchenSink), j'ai trouvé l'exemple image_scaling.js
Génial, justement ce qu'il me fallait ! Des images en petites taille, et quand on clique dessus, un effet de zoome simple et efficace. Voyons ce code...

var image1 = Titanium.UI.createView({
  backgroundImage:'../images/smallpic1.jpg',
  height:75,
  width:75,
  top:40,
  left:50,
  borderWidth:3,
  borderColor:'#fff',
  zIndex:1
});

win.add(image1);

var center1 = null;

var scaled1 = false;
image1.addEventListener('click', function() {
  var t = Titanium.UI.create2DMatrix();
  
  if (!scaled1) {
    t = t.scale(4.0);
    center1 = image1.center;
    image1.animate({transform:t,center:win.center,zIndex:10,duration:500});
    scaled1 = true;
  }
  else {
    image1.animate({transform:t,center:center1,zIndex:1,duration:500});
    scaled1 = false;
  }
});

Bon, on peu discuter de la multiplication des variables (center1, scaled1...), surtout si on fait ça dans une boucle où tout est dynamique. Mais ce n'est pas le plus important.

Je me suis empressé d'adapter cela à mon code. Qui ressemblait à peu près ça :

// Chercher l'image sauvegardé auparavant (download, appareil photo...)
var f = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, "photo_1.jpg");

var image1 = Titanium.UI.createImageView({
  image: f,
  height:75,
  width:75,
  top:40,
  left:50,
  zIndex:1
});

win.add(image1);

image1.addEventListener('click', function(e) {
  var t = Titanium.UI.create2DMatrix(), im = e.source;
  
  if (! im.isScaled) {
    t = t.scale(4.0);
    im.initialCenter = image1.center;
    im.animate({transform:t,center:win.center, zIndex:10, duration:500});
    im.isScaled = true;
  }
  else {
    im.animate({transform:t,center: im.initialCenter,zIndex:1,duration:500});
    im.isScaled = false;
  }
});

Résultat : j'avais bien un effet de zoom, mais mon image était totalement pixelisée. En fait, même si l'image a des dimensions largement supérieures à celle de l'écran, la transformation (et donc la mise à l'échelle) semble se baser sur la vue présente. Mais ce n'est pas du tout ce qui se passait dans la démo pourtant !
On observe un peu plus en détail... Tiens, ils ont en fait créé une simple vue avec une image de fond : backgroundImage.
OK. On essaie à nouveau.

var f = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, "photo_1.jpg");

var image1 = Titanium.UI.createView({
  backgroundImage: f,
  height:75,
  width:75,
  top:40,
  left:50,
  zIndex:1
});

Roulements de tambour... Et crash de l'application. Aïe ! Et oui, la propriété backgroundImage attend une chaîne de caractères, et non un objet File.
Il reste alors une idée : récupérer l'adresse de ce fichier. On va voir la documentation. Ah, aucune doc sur l'objet File...
On se replonge dans l'appli KitchenSink... Miracle, il existe une propriété nativePath sur l'objet File...
Dernier essai :

var win = Titanium.UI.currentWindow;

var f = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, "photo_1.jpg");

var image1 = Titanium.UI.createView({
  backgroundImage: f.nativePath,
  height:80,
  width:60,
  top:40,
  left:50,
  borderWidth:3,
  borderColor:'#fff',
  zIndex:1
});

win.add(image1);

image1.addEventListener('click', function(e) {
  var t = Titanium.UI.create2DMatrix(), im = e.source;
   
  if (! im.isScaled) {
    t = t.scale(4.5);
    im.initialCenter = image1.center;
    im.animate({transform:t,center:win.center, zIndex:10, duration:350});
    im.isScaled = true;
  }
  else {
    im.animate({transform:t,center: im.initialCenter,zIndex:1,duration:350});
    im.isScaled = false;
  }
});

Et là, enfin, on obtient ce que l'on attendait... Maintenant que je le sais, cela me semble évident, mais ce n'était pas le cas tout de suite...

Update : au lieu de passer par la création d'un objet File, on peut aussi faire directement comme ça...

...
  backgroundImage: Titanium.Filesystem.applicationDataDirectory + "/photo_1.jpg",
  ...

Aucun commentaire:

Enregistrer un commentaire