Front IDILL :
search by curves added
search by type added
notifications added
timeline improved
/*
* This file is part of the TraKERS\Front IDILL package.
*
* (c) IRI <http://www.iri.centrepompidou.fr/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/*
* Projet : TraKERS
* Module : Front IDILL
* Fichier : mosaic.js
*
* Auteur : alexandre.bastien@iri.centrepompidou.fr
*
* Fonctionnalités : Définit la "classe" mosaïque et définit des fonctions d'intéractions.
*/
/*
* Classe définissant la mosaïque.
* Elle contient sa longueur, le nombre d'images total, une liste d'urls pour les vidéos, leurs snapshots principaux et leur position.
* Contient également les dimensions en px de la mosaïque.
*/
function mosaic(len, imgToShow, imgTotal, zoomPercentage, prezoomPercentage, zoomedMargin)
{
//S'il s'agit d'un rectangle.
if(imgToShow % len == 0)
{
//Longueur horizontale.
this.length = len;
//Nombre d'images dans la mosaïque.
this.imagesToShow = imgToShow;
this.imagesTotal = imgTotal;
//Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
this.videos = [];
this.urls = [];
this.imgs = [];
this.ids = [];
//On remplit le tableau d'ids.
for(var i = 0 ; i < this.imagesTotal ; i++)
this.ids.push(i);
//On les mélange.
this.ids.sort(function()
{
return 0.5 - Math.random()
});
console.log(this.ids);
//Dimensions de la mosaïque en pixels.
this.width;
this.height;
//Dimensions d'un snapshot en pixels.
this.snapshotWidth;
this.snapshotHeight;
//Espacement entre les snapshots en pixels.
this.marginWidth;
//Temps d'intéractions/d'animations.
this.preZoomTime;
this.preUnzoomTime;
this.zoomTime;
this.unzoomTime;
this.timeNeighbourGlowing;
this.timeNeighbourUnglowing;
this.timeMovingToNeighbour;
this.timeSearchFade;
this.timeNotifyFade;
//Booléens permettant ou non certaines intéractions selon le contexte.
this.zoomed;
this.fullscreen;
this.canMoveToNeighbour;
this.helpDisplayed;
//Mode actuel.
this.currentMode;
//Snapshot sur lequel on a zoomé.
this.previousZoomedSN;
//Son ID.
this.previousId;
//Largeur de la marge pour le centrage vertical de la mosaïque.
this.MPTop_margin;
this.top_margin;
//Pourcentage d'agrandissement lors d'un prézoom et d'un zoom.
this.prezoomPercentage = prezoomPercentage;
this.zoomPercentage = zoomPercentage;
//Espacement des snapshots après un zoom.
this.zoomedMargin = zoomedMargin;
//Mosaïque locale.
this.localMos;
//Position des voisins lors d'un zoom.
this.neighboursIds = [];
//ID du snapshot du milieu lors d'un zoom.
this.centerId;
//Lecteur.
this.player;
//Coordonnées et dimensions d'un snapshot zoomé.
this.snTop = 0;
this.snLeft = 0;
this.snWidth = 0;
this.snHeight = 0;
this.searchCanvas;
this.loadFromJson('./player/json/videos.json');
}
else
{
//Affiche un message d'erreur.
}
}
/*
* Méthode d'affichage de la mosaïque.
* Génère une matrice de imgs.
*/
mosaic.prototype.createMosaic = function()
{
this.previousZoomedSN = '';
this.previousPrezoomDiv = '';
this.fullscreen = false;
this.canMoveToNeighbour = false;
this.helpDisplayed = false;
var str = '';
if(this.imgs.length >= this.imagesToShow)
{
for(var i = 0 ; i < this.imagesToShow ; i++)
{
//On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global.
str += '<div id="snapshotDiv-' + i + '" class="snapshotDivs"><img id="snapshot-' + i + '" class="snapshots" src="snapshots-little/' + this.imgs[i] + '" /></div>';
}
}
console.log(this.imagesToShow);
return str;
}
/*
* Permet de raffraichir la mosaïque.
*/
mosaic.prototype.loadMosaic = function()
{
var createMosaic = this.createMosaic();
if(createMosaic == '')
{
return;
}
var _this = this;
//On affecte les chemins vers les images à la mosaïque.
this.previousZoomedSN;
//this.width =
//On met à jour la mosaïque.
$('#mainPanel').html(createMosaic);
//On récupère la taille des bordures.
this.marginWidth = $('.snapshotDivs').css('margin-bottom');
this.marginWidth = parseFloat(mos.marginWidth)*2;
//On calcule la taille des divs contenant les snapshots.
this.width = $('#mainPanel').innerWidth();
//On ne calculera pas tout de suite la hauteur de la mosaique étant donnée qu'elle est calculée par la suite dynamiquement.
this.snapshotWidth = this.width / this.length - this.marginWidth;
this.snapshotHeight = this.snapshotWidth*9/16;
$('.snapshotDivs').css('width', this.snapshotWidth).css('height', this.snapshotHeight).css('margin', this.marginWidth/2);
this.height = $('#mainPanel').innerHeight();
//On centre verticalement la mosaïque.
this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
$('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
//On affiche les notifications.
this.notifySelectionSearchMosaicFull();
$('.snapshotDivs').mouseenter(function ()
{
//On effectue un prézoom dès qu'on va sur une image.
_this.preZoom($(this));
});
$('body').keypress(function (event)
{
//Si on a appuié sur la touche 'q' ou 'Q';
if(event.which == 113 || event.which == 81)
{
_this.unzoom();
}
});
}
/*
* Zoom sur la position d'une image, 1ère partie. Durant le laps de temps de time ms, l'utilisateur a le choix de zoomer sur une autre image.
* Après ce laps de temps, l'image zoom complétement et il n'est plus possible de sélectionner une autre image par pointage.
*/
mosaic.prototype.preZoom = function(snapshot)
{
if(this.fullscreen)
{
return;
}
//On enlève les notifications initiales si elles existent.
this.removeSelectionSearchMosaicFull();
//Mosaïque.
var mosaic = this;
//Dimensions de la mosaïque.
var h = this.height, w = this.width;
//Longueur en images, nombre d'images et taille de bordure de la mosaïque.
var len = this.length, imgs = this.imagesToShow, margin = this.marginWidth;
//Dimensions et position d'un snapshot dans la mosaïque.
var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
var sTop = snapshot.position().top, sLeft = snapshot.position().left;
var prezoomPercentage = this.prezoomPercentage;
//ID de l'image actuelle.
var currentId = $('img', snapshot).attr('id');
//Si un zoom est déjà en cours, on ne zoom sur rien d'autre en attendant que ce snapshot ai dézoomé en cas de mouseleave.
if(this.zoomed)
{
if($('#preZoomContainer-' + currentId) != $(this) && this.previousZoomedSN != '' && this.previousId != '')
{
this.preUnzoom();
}
else
{
return;
}
}
//On indique qu'on a zoomé et on spécifie le snapshot sur lequel on a zoomé.
this.zoomed = true;
this.previousZoomedSN = snapshot;
this.previousId = currentId;
//On récupère les attributs de l'image.
var fakeImg = $('img', snapshot);
//On forme la balise de la fausse image et on passe son url pour les grands snapshots.
fakeImg = '<img id="fake-' + currentId + '" class="snapshots" src="' + fakeImg.attr('src').replace('-little/', '/') + '" />';
//On génère un faux snapshot identique au précédent et qu'on va coller dessus.
var fakeSnapshot = '<div id="prezoomContainer-' + currentId + '" class="prezoomContainers"><div id="prezoomSnapshot-' + currentId + '" class="snapshotDivs">' + fakeImg + '</div></div>';
//On l'ajoute à la mosaïque.
$('#mainPanel').append(fakeSnapshot);
//On modifie ses attributs.
$('#fake-' + currentId).load(function()
{
$('#prezoomContainer-' + currentId).css('display', 'block');
$('#prezoomContainer-' + currentId).css('top', sTop).css('left', sLeft).css('width', (snWidth + margin)).css('height', (snHeight + margin));
$('#prezoomSnapshot-' + currentId).css('width', (snWidth)).css('height', (snHeight));
//Dimensions et coordonnées initiales du div sur lequel on zoom.
var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
var initialDivTop = $('#prezoomContainer-' + currentId).position().top, initialDivLeft = $('#prezoomContainer-' + currentId).position().left;
//Dimensions et coordonnées finales du div.
var finalDivWidth = initialDivWidth * (prezoomPercentage+1), diffWidth = finalDivWidth - initialDivWidth, finalDivHeight = initialDivHeight + diffWidth;
var finalDivTop = (initialDivTop - (finalDivHeight - snHeight)/2), finalDivLeft = (initialDivLeft - (finalDivWidth - snWidth)/2);
//CAS PARTICULIER pour la position du snapshot zoomé : les bordures.
if(finalDivTop < 0)
{
finalDivTop = -margin;
}
if(finalDivTop + finalDivHeight > h)
{
finalDivTop = h - finalDivHeight;
}
if(finalDivLeft < 0)
{
finalDivLeft = 0;
}
if(finalDivLeft + finalDivWidth + margin*2 > w)
{
finalDivLeft = w - finalDivWidth - margin*2;
}
////Code de debug.
////CAUTION////
/*var red = '<div id="red"></div>';
if($('#red') != null || $('#red') != undefined)
$('body').append(red);
$('#red').css('background-color', '#FF0000').css('position', 'absolute').css('top', '0px').css('left', '0px').css('width', '100px').css('height', '100px');
$('#red').css('top', finalDivTop).css('left', finalDivLeft).css('width', finalDivWidth).css('height', finalDivHeight);*/
//alert("initial : " + initialDivWidth + " " + initialDivHeight + " ; final : " + finalDivWidth + " " + finalDivHeight);
////CAUTION////
//On prézoom le div en le centrant sur le milieu du snapshot pointé.
$('#prezoomSnapshot-' + currentId).animate(
{
width: finalDivWidth + margin,
height: finalDivHeight - margin*2,
top: finalDivTop + margin,
left: finalDivLeft + margin
}, this.preZoomTime);
$('#prezoomContainer-' + currentId).animate(
{
width: finalDivWidth + margin*2,
height: finalDivHeight - margin,
top: finalDivTop + margin,
left: finalDivLeft
}, this.preZoomTime, function()
{
mosaic.notifyPointMosaicPrezoom();
});
});
//Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
$('#prezoomContainer-' + currentId).click(function ()
{
if(this.previousZoomedSN != '')
{
mosaic.zoom();
}
});
}
/*
* Dézoome sur la position de l'image. Il est à noter que ce dézoome diffère du dézoom global dans la mesure où celui-ci ne concerne que l'image sur laquelle on a zoomé.
*/
mosaic.prototype.preUnzoom = function()
{
//Si on n'a pas zoomé, on quitte la fonction.
if(!this.zoomed)
{
return;
}
this.removePointMosaicPrezoom();
//On spécifie la marge afin de centrer le prédézoom.
var margin = this.marginWidth;
//ID du snapshot précédemment pointé.
var id = this.previousId;
//On ne zoom plus.
this.zoomed = false;
//On rétrécit le snapshot de prézoom, puis on le supprime en donnant l'illusion qu'il s'agissait du véritable snapshot, alors qu'en fait c'était un clone.
$('#prezoomSnapshot-' + id).animate(
{
width: this.snapshotWidth,
height: this.snapshotHeight,
top: this.previousZoomedSN.position().top,
left: this.previousZoomedSN.position().left
}, this.preUnzoomTime);
$('#prezoomContainer-' + id).animate(
{
width: this.snapshotWidth + margin,
height: this.snapshotHeight + margin,
top: this.previousZoomedSN.position().top,
left: this.previousZoomedSN.position().left
}, this.preUnzoomTime, function(){ $(this).remove(); this.zoomed = false; });
}
/*
* Zoom d'un snapshot en plein écran.
*/
mosaic.prototype.zoom = function()
{
var mos = this;
//Si la mosaïque est en pleine écran, pas la peine de zoomer.
if(this.fullscreen)
{
return;
}
this.removePointMosaicPrezoom();
//On prend les attributs nécessaires au calculs.
var margin = this.marginWidth, len = this.length, imgs = this.imagesToShow;
var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
var newMPWidth = initMPWidth * len + this.zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + this.zoomedMargin * ((imgs / len));
var newPreMPWidth = initMPWidth * len * this.zoomPercentage + this.zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * this.zoomPercentage + this.zoomedMargin * ((imgs / len));
//Dimensions et coordonnées initiales du div sur lequel on zoom.
var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
//Dimensions et coordonnées finales du div.
var finalDivWidth = initialDivWidth * (this.zoomPercentage+1), finalDivHeight = initialDivHeight * (this.zoomPercentage+1);
var newZoomTop = -this.previousZoomedSN.position().top*(newPreMPHeight/initMPHeight) - this.zoomedMargin/2 + (initMPHeight - initMPHeight * this.zoomPercentage)/2, newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - this.zoomedMargin/2 + (initMPWidth - initMPWidth * this.zoomPercentage)/2;
var newSnWidth = initMPWidth * this.zoomPercentage, newSnHeight = initMPHeight * this.zoomPercentage;
this.preUnzoom(this);
/*SINGULARITE*/
this.fullscreen = true;
//On passe l'image du snapshot pointé en HD.
var zoomedImg = $('img', this.previousZoomedSN);
var src = zoomedImg.attr('src');
zoomedImg.attr('src', src.replace('-little/', '/'));
//On récupère son ID.
var tab, zoomedImgId;
tab = mos.previousId.split('-');
zoomedImgId = tab[1];
//Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
$('.snapshotDivs').animate(
{
width: newSnWidth,
height: newSnHeight,
margin: this.zoomedMargin/2 + 'px',
opacity: '0.4'
}, this.zoomTime);
//Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
$(this.previousZoomedSN).animate(
{
opacity: '1'
}, this.zoomTime);
//On zoome sur la mosaïque.
$('#mainPanel').animate(
{
width: newPreMPWidth,
height: newPreMPHeight,
top: newZoomTop,
left: newZoomLeft
}, this.zoomTime, function()
{
//On charge les interactions avec les voisins.
mos.centerId = zoomedImgId;
mos.listenToNeighbours();
mos.currentMode = 'VIDEO';
console.log('h : ' + -newZoomLeft + " " + zoomedImg.position().left);
mos.snTop = (zoomedImg.position().top + newZoomTop + mos.MPTop_margin), mos.snLeft = (zoomedImg.position().left + newZoomLeft);
mos.snWidth = newSnWidth + 1, mos.snHeight = newSnHeight + 1;
mos.loadPlayer(mos.snTop, mos.snLeft, mos.snWidth, mos.snHeight, newZoomTop, newZoomLeft);
/*mos.unload();
mos.localMos.loadLocalMosaic(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, mos.imgs, tab[1]);*/
});
}
/*
* Chargement du player basé sur le metadataplayer.
*/
mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft)
{
//On configure les options de lancement.
IriSP.libFiles.defaultDir = "../lib/";
IriSP.widgetsDir = "./player/metadataplayer/"
var videoToPlay = this.videos[this.centerId];
var currentMetadata = this.urls[this.centerId];
console.log('VIDEO[' + this.centerId + '] : ' + videoToPlay);
console.log('MD[' + this.centerId + '] : ' + currentMetadata);
var _metadata = {
url: currentMetadata,
format: 'ldt'
};
console.log(zoomTop + " m" + this.marginWidth);
var _config = {
gui: {
zoomTop: zoomTop - this.marginWidth*2,
zoomLeft: zoomLeft,
width: newSnWidth,
height: newSnHeight,
container: 'LdtPlayer',
default_options: {
metadata: _metadata
},
css:'./player/metadataplayer/LdtPlayer-core.css',
widgets: [
{
type: "Timeline"
}
]
},
player:{
type: 'html5', // player type
video: videoToPlay,
live: true,
height: newSnHeight,
width: newSnWidth,
autostart: true
}
};
//On positionne le player.
$('.LdtPlayer').css(
{
//display: 'none',
position: 'absolute',
'background-color': '#000000',
top: newZoomTop,
left: newZoomLeft
});
//On démarre le player.
this.player = null;
this.player = new IriSP.Metadataplayer(_config, _metadata);
}
/*
* Retour à la taille normale de la mosaïque.
*/
mosaic.prototype.unzoom = function()
{
//Si on n'est pas en plein écran, on quitte.
if(!this.fullscreen)
{
return;
}
this.snTop = 0;
this.snLeft = 0;
this.Width = 0;
this.snHeight = 0;
//On charge les attributs nécessaires aux calculs.
var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
var mpWidth = this.width, mpHeight = this.height;
var mos = this;
//On passe le snapshot sur lequel on a zoomé en SD.
var zoomedImg = $('img', this.previousZoomedSN);
var src = zoomedImg.attr('src');
zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
mos.player.widgets[0].freePlayer();
$('.LdtPlayer').remove();
$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
//On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
$('.snapshotDivs').animate(
{
width: sWidth,
height: sHeight,
margin: this.marginWidth/2 + 'px',
opacity: '1'
}, this.unzoomTime);
//On dézoom sur la mosaïque.
$('#mainPanel').animate(
{
width: mpWidth,
height: mpHeight,
top: '0px',
left: '0px'
}, this.unzoomTime, function()
{
//On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
mos.fullscreen = false;
mos.canMoveToNeighbour = false;
//On revient en mode MOSAIC.
mos.currentMode = 'MOSAIC';
//On ne permet plus le déplacement vers les voisins.
$('.snapshotDivs').unbind('mouseenter', mos.selectNeighbour);
//On remet les notifications initiales.
mos.notifySelectionSearchMosaicFull();
});
}
/*
* Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
*/
mosaic.prototype.listenToNeighbours = function()
{
////TEST
//$('.test').empty();
this.canMoveToNeighbour = false;
var currentLine = Math.floor(this.centerId / this.length), currentColumn = this.centerId % this.length;
var zoomedImg = $('img', this.previousZoomedSN);
var mos = this;
//On cherche l'ID des voisins.
//Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
//Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
this.neighboursIds[1] = (currentColumn < this.length) ? (+this.centerId + 1) : -1;
//Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.length) : -1;
//Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
this.neighboursIds[3] = (currentLine < (this.imagesToShow / this.length)) ? (+this.centerId + this.length) : -1;
//ID du cadre voisin.
var preId;
for(var i = 0 ; i < this.neighboursIds.length ; i++)
{
if(this.neighboursIds[i] != -1)
{
preId = '#neighbourFrameBorder-' + this.neighboursIds[i];
//On permet le déplacement vers les voisins.
// $('#snapshotDiv-' + this.neighboursIds[i] + ', ' + preId + '-left,' + preId + '-right,' + preId + '-up,' + preId + '-down').mouseenter(mos.selectNeighbour);
$('#snapshotDiv-' + this.neighboursIds[i]).mouseenter(mos.selectNeighbour);
}
}
}
/*
* Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
*/
mosaic.prototype.selectNeighbour = function()
{
////TEST
//$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
//Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
if((mos.currentMode == 'VIDEO') && ($(this).attr('id') != 'snapshotDiv-' + mos.centerId))
{
//On crée le cadre qui va être superposé au voisin.
//On le colle au voisin.
var tab = $(this).attr('id').split('-');
var snapshotId = tab[1];
var neighbourFrame = '';
var marginValue = parseFloat($(this).css('margin'));
neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
$('#mainPanel').append(neighbourFrame);
//On positionne le div de background juste au niveau du voisin.
$('#neighbourFrame-' + snapshotId).css(
{
'top': (+$(this).position().top + marginValue),
'left': (+$(this).position().left + marginValue),
'width': $(this).width(),
'height': $(this).height()
});
//On positionne le div de background noir juste au niveau de l'image du voisin.
$('#neighbourImgBg-' + snapshotId).css(
{
'top': marginValue,
'left': marginValue,
'width': $(this).width() - marginValue*2,
'height': $(this).height() - marginValue*2,
});
//On met par dessus le div de l'image clonée du voisin.
$('#neighbourImg-' + snapshotId).css(
{
'top': 0,
'left': 0,
'width': $(this).width() - marginValue*2,
'height': $(this).height() - marginValue*2,
'background-image': 'url("' + $('img', $(this)).attr('src') + '")',
'background-size': $(this).width() + 'px ' + $(this).height() + 'px',
'background-position': -marginValue + 'px ' + -marginValue + 'px',
'opacity': '0.4'
});
var fId = '#neighbourFrame-' + snapshotId;
$(fId).animate(
{
//On le fait apparaître.
opacity: '1'
}, timeNeighbourGlowing, function()
{
//On peut désormais se déplacer vers ce voisin.
mos.canMoveToNeighbour = true;
});
//Lorsqu'on quitte un des snapshots (bien entendu le voisin en question), on retire le cadre.
$(fId).mouseleave(mos.deselectNeighbour)
//Si on clique sur le voisin ou son cadre, on passe au voisin suivant.
$(fId).click(mos.moveToNeighbour);
}
}
/*
* Change la coloration d'une bordure quittée lors d'une vue en plein écran.
*/
mosaic.prototype.deselectNeighbour = function()
{
////TEST
//$('.test').append('un,');
//On ne peut plus se déplacer vers les voisins.
mos.canMoveToNeighbour = false;
//On récupère le voisin.
var neighbourFrame = $(this);
//Si on est en mode VIDEO.
if(mos.currentMode == 'VIDEO')
{
//On le fait disparaître progressivement.
neighbourFrame.animate(
{
opacity: '0'
}, timeNeighbourUnglowing, function()
{
//Une fois invisible, on le supprime.
neighbourFrame.remove();
});
}
}
/*
* Lors d'une vue en plein écran, on se déplace vers le voisin dont l'id a été spécifié dans la fonction appelante.
*/
mosaic.prototype.moveToNeighbour = function()
{
//Si on ne peut pas se déplacer vers les voisins, on quitte.
if(!mos.canMoveToNeighbour)
{
return;
}
//On obtient l'ID de destination.
var tab = $(this).attr('id').split('-');
var destinationId = tab[1];
//On charge les attributs nécessaires aux calculs.
var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
var divideCoeffTop = Math.floor(destinationId / mos.length) == 0 ? 1 : Math.floor(destinationId / mos.length);
var divideCoeffLeft = destinationId % mos.length == 0 ? 1 : destinationId % mos.length;
var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
//On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
if(mos.previousZoomedSN.position().top > neighbourFrameTop)
MPCurrentTop += Math.abs(neighbourFrameTop - mos.previousZoomedSN.position().top);
else if(mos.previousZoomedSN.position().top < neighbourFrameTop)
MPCurrentTop -= Math.abs(neighbourFrameTop - mos.previousZoomedSN.position().top);
//On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
if(mos.previousZoomedSN.position().left > neighbourFrameLeft)
MPCurrentLeft += Math.abs(neighbourFrameLeft - mos.previousZoomedSN.position().left);
else if(mos.previousZoomedSN.position().left < neighbourFrameLeft)
MPCurrentLeft -= Math.abs(neighbourFrameLeft - mos.previousZoomedSN.position().left);
//On passe le snapshot de destination en HD.
var destinationImg = $('#snapshot-' + destinationId);
var destinationImgSrc = destinationImg.attr('src');
destinationImg.attr('src', destinationImgSrc.replace('snapshots-little/', 'snapshots/'));
//On passe l'ancien snapshot en SD.
var currentImgSrc = $('img', mos.previousZoomedSN).attr('src');
$('img', mos.previousZoomedSN).attr('src', currentImgSrc.replace('snapshots/', 'snapshots-little/'));
//On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
var neighbourFrame = $(this);
var tab = neighbourFrame.attr('id').split('-');
mos.centerId = tab[1];
$(this).css('opacity', '0');
neighbourFrame.remove();
mos.player.widgets[0].freePlayer();
$('.LdtPlayer').remove();
$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
//On grise le snapshot qu'on vient de quitter.
mos.previousZoomedSN.animate(
{
opacity: '0.4'
});
//On se déplace.
$('#mainPanel').animate(
{
top: MPCurrentTop,
left: MPCurrentLeft
}, timeMovingToNeighbour, function()
{
//On fait apparaître le snapshot vers lequel on s'est déplacé.
$('#snapshotDiv-' + destinationId).animate(
{
opacity: '1'
}, mos.zoomTime, function()
{
//On recharge les voisins.
$('.snapshotDivs').unbind('mouseenter', mos.selectNeighbour);
mos.previousZoomedSN = $('#snapshotDiv-' + mos.centerId);
mos.listenToNeighbours();
mos.loadPlayer((destinationImg.position().top + MPCurrentTop + mos.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height(), MPCurrentTop, MPCurrentLeft);
});
});
}
/*
* Déchargement du contenu de la mosaïque pour le chargement de la mosaïque locale.
*/
mosaic.prototype.unload = function()
{
//On supprime les event listeners des objets de la mosaïque.
$('.snapshotDivs').unbind();
$('.snapshots').unbind();
$('.prezoomContainers').unbind();
//On supprime physiquement les objets.
$('#mainPanel').empty();
}
/*
* Centre verticalement un snapshot.
*/
/*function verticalCenterImg(mosaic, img)
{
//On récupère sa hauteur.
var image_height = img.height();
//Calcule la marge du haut de chaque div pour le centrage.
if(mosaic.top_margin == undefined)
mosaic.top_margin = (mosaic.snapshotHeight > image_height) ? (mosaic.snapshotHeight - image_height)/2 : (image_height - mosaic.snapshotHeight)/2;
//On centre le snapshot.
img.css('margin-top', mosaic.top_margin).css('margin-bottom', mosaic.top_margin);
}*/
/*
* Permet de tester l'égalité des éléments de deux objets.
* Pour ce faire on compare les éléments définissant ces objets.
*/
$.fn.equals = function(compareTo)
{
if (!compareTo || !compareTo.length || this.length!=compareTo.length)
{
return false;
}
for (var i=0; i<this .length; i++)
{
if (this[i]!==compareTo[i])
{
return false;
}
}
return true;
}
/*
* Charge les vidéos, les snapshots et les annotations depuis un fichier json.
*/
mosaic.prototype.loadFromJson = function(path)
{
var _this = this;
var i = 0;
$.getJSON(path, function(data)
{
$.each(data, function(key, val)
{
// console.log(val);
$.each(val, function(key_video, val_video)
{
$.getJSON(val_video.metadata, function(meta)
{
_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
//console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/'));
});
// _this.imgs.push(val_video.snapshot);
// _this.urls.push(val_video.metadata);
_this.imgs[_this.ids[i]] = val_video.snapshot;
_this.urls[_this.ids[i]] = val_video.metadata;
i++;
});
});
console.log('rdy');
_this.loadMosaic();
});
}
/*
* Affecte une vidéo au tableau des vidéos selon son id
*/
mosaic.prototype.affectVideoById = function(metadata_id, video)
{
for (i = 0 ; i < this.urls.length ; i++)
{
if(this.urls[i] == metadata_id)
{
this.videos[i] = video;
break;
}
}
}
/*
* Lance une recherche par courbes.
*/
mosaic.prototype.startSearch = function()
{
var top, left, width, height, margin_top, inMosaic;
//Si on est dans le cas d'un filtrage de mosaïque.
if(this.currentMode == "FILTER")
{
var mainPanel = $('#mainPanel');
top = mainPanel.position().top;
left = mainPanel.position().left;
width = mainPanel.width();
height = mainPanel.height();
margin_top = this.MPTop_margin;
inMosaic = true;
}
//Sinon si c'est une recherche dans la vidéo.
else if(this.currentMode == "SEARCH")
{
top = this.snTop;
left = this.snLeft;
width = this.snWidth;
height = this.snHeight;
margin_top = '0px';
inMosaic = false;
}
this.searchCanvas = new searchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic);
this.searchCanvas.create();
}
/*
* Quitte une recherche par courbes.
*/
mosaic.prototype.leaveSearch = function()
{
this.searchCanvas.leaveSearch();
}
/* ===============================================
* *
* ZONE DES NOTIFICATIONS *
* *
=============================================== */
/*
* Affiche la notification de sélection/recherche lorsque la mosaique est complète.
*/
mosaic.prototype.notifySelectionSearchMosaicFull = function()
{
//On spécifie les notifications en div.
var notification_selection = "<div id='notify_selection' class='notifications'></div>";
var notification_search = "<div id='notify_search' class='notifications'></div>";
//On les ajoute à la mosaïque.
$('#mainPanel').append(notification_selection + notification_search);
//On calcule leurs coordonnées et dimensions.
var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
var notify_margin = parseInt($('.notifications').css('margin'));
var selection_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
var search_left = selection_left + notify_width + notify_margin;
//On les positionne.
$('#notify_selection').css(
{
left: selection_left
});
$('#notify_search').css(
{
left: search_left
});
//On les fait apparaître.
$('.notifications').css(
{
opacity: "0.9"
});
}
/*
* Supprime la notification de sélection/recherche lorsque la mosaique est complète.
*/
mosaic.prototype.removeSelectionSearchMosaicFull = function()
{
$('#notify_selection, #notify_search').remove();
}
/*
* Affiche la notification de maintient du pointage lors d'une phase de prézoom.
*/
mosaic.prototype.notifyPointMosaicPrezoom = function()
{
if($('#notify_point').length > 0)
{
return;
}
//On spécifie les notifications en div.
var notification_point = "<div id='notify_point' class='notifications'></div>";
//On les ajoute à la mosaïque.
$('#mainPanel').append(notification_point);
console.log('Append');
//On calcule leurs coordonnées et dimensions.
var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
var notify_margin = parseInt($('.notifications').css('margin'));
var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
//On les positionne.
$('#notify_point').css(
{
left: point_left
});
//On les fait apparaître.
$('.notifications').css(
{
opacity: "0.9"
});
}
/*
* Supprime la notification de maintient du pointage.
*/
mosaic.prototype.removePointMosaicPrezoom = function()
{
$('#notify_point').remove();
}
/*
* Affiche l'aide.
*/
mosaic.prototype.notifyHelp = function()
{
if(this.helpDisplayed)
{
return;
}
this.removeSelectionSearchMosaicFull();
this.removePointMosaicPrezoom();
this.helpDisplayed = true;
var search_2hands_tab = ['no_motion', 'right_angle', 'contact', 'grand_jete', 'circle', 'screw', 'arc', 'rythme', 'slow', 'up_down', 'wave', 'wheel'];
var search_body_tab = ['bend', 'fall', 'jump', 'hello', 'knee_up'];
var controls_1hand_tab = ['selection'];
//On spécifie les notifications en div.
var search_title = "<div id='search_title'></div>";
var search_img = "<div id='search_img' class='notify_imgs'></div>";
var search_2hands_text = "<div id='search_2hands_text'></div>";
var search_2hands_imgs = "<div id='search_2hands_imgs' class='notify_imgs_big'>";
for(var i = 0 ; i < search_2hands_tab.length ; i++)
{
search_2hands_imgs += "<div id='2hands_" + search_2hands_tab[i] + "' class='notify_imgs_small'></div>";
}
search_2hands_imgs += "</div>";
var search_body_text = "<div id='search_body_text'></div>";
var search_body_imgs = "<div id='search_2hands_imgs' class='notify_imgs'>"
for(var i = 0 ; i < search_body_tab.length ; i++)
{
search_body_imgs += "<div id='body_" + search_body_tab[i] + "' class='notify_imgs_small'></div>";
}
search_body_imgs += "</div>";
var controls_title = "<div id='controls_title'></div>";
var controls_img = "<div id='controls_img' class='notify_imgs'></div>";
var controls_1hand_text = "<div id='controls_1hand_text'></div>";
var controls_1hand_imgs = "<div id='controls_1hand_imgs' class='notify_imgs'>";
for(var i = 0 ; i < controls_1hand_tab.length ; i++)
{
controls_1hand_imgs += "<div id='1hand_" + controls_1hand_tab[i] + "' class='notify_imgs_small'></div>";
}
controls_1hand_imgs += "</div>";
var help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + search_body_text + search_body_imgs + "</div>";
var help_controls = "<div id='help_controls'>" + controls_title + controls_img + controls_1hand_text + controls_1hand_imgs + "</div>";
var notification_help = "<div id='notify_help'>" + help_search + "<div id='help_sep'></div>" + help_controls + "</div>";
//On les ajoute à la mosaïque.
$('body').append(notification_help);
//On calcule leurs coordonnées et dimensions.
var notify_width = $(window).width(), notify_height = $(window).height();
var notify_margin = parseInt($('#notify_help').css('margin'));
var notify_ = 10;
//On les positionne.
$('#notify_help').css(
{
left: "0px",
top: "0px",
width: notify_width - notify_margin * 2,
height: notify_height - notify_margin * 2,
"margin-top": notify_margin_top
});
var search_width = $('#help_search').width();
$('#search_title').html('Recherche');
$('#search_2hands_text').html('Gestes à effectuer avec les deux mains');
$('#search_body_text').html('Gestes à effectuer avec le corps entier');
for(var i = 0 ; i < search_2hands_tab.length ; i++)
{
$("#2hands_" + search_2hands_tab[i]).css("background-image", "url('./pictos/help/" + search_2hands_tab[i] + ".png')");
//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
}
for(var i = 0 ; i < search_body_tab.length ; i++)
{
$("#body_" + search_body_tab[i]).css("background-image", "url('./pictos/help/" + search_body_tab[i] + ".png')");
//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
}
$('#controls_title').html('Contrôles');
$('#controls_1hand_text').html('Gestes à effectuer avec une seule main');
for(var i = 0 ; i < controls_1hand_tab.length ; i++)
{
$("#1hand_" + controls_1hand_tab[i]).css("background-image", "url('./pictos/help/" + controls_1hand_tab[i] + ".png')");
//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
}
//On les fait apparaître.
$('#notify_help').css(
{
opacity: "1"
});
$('.notify_imgs_big').css(
{
opacity: "1"
});
}
/*
* Supprime l'aide.
*/
mosaic.prototype.removeHelp = function()
{
if(!this.helpDisplayed)
{
return;
}
var _this = this;
$('#notify_help').fadeOut(this.timeNotifyFade, function()
{
_this.helpDisplayed = false;
$('#notify_help').remove();
});
}