Virare un immagine ad un colore predefinito
Ancora una volta una richiesta d’aiuto pervenuta sul forum è alla base dei nostri tutorial.
Paolo infatti aveva la necessità di virare alcune immagini ad un colore predefinito volendo però che al mouseover queste tornassero con i colori originali (la richiesta sul Forum è la seguente canvas css jquery modifica per l’effetto hover ).
Paolo ci segnalava una funzione trovata in rete adatta allo scopo ( tintImage, che utilizza l’elemento HTML5 canvas che consente il rendering dinamico delle immagini) che però non riusciva ad adattare al suo caso. La funzione è la seguente:
function tintImage(imgElement, tintColor) { var canvas = document.createElement("canvas"); canvas.width = imgElement.offsetWidth; canvas.height = imgElement.offsetHeight; var ctx = canvas.getContext("2d"); ctx.drawImage(imgElement, 0, 0); var map = ctx.getImageData(0, 0, imgElement.offsetWidth, imgElement.offsetHeight); // Corretto su segnalazione di Paolo var imdata = map.data; var r, g, b, avg; for ( var p = 0, len = imdata.length; p < len; p += 4 ) { r = imdata[p]; g = imdata[p + 1]; b = imdata[p + 2]; avg = Math.floor((r + g + b) / 3); imdata[p] = imdata[p + 1] = imdata[p + 2] = avg; } ctx.putImageData(map, 0, 0); ctx.globalCompositeOperation = "lighter"; ctx.globalAlpha = 0.5; ctx.fillStyle = tintColor; ctx.fillRect(0, 0, canvas.width, canvas.height); imgElement.src = canvas.toDataURL(); }
Abbiamo quindi preso 3 immagini ed abbiamo sviluppato la funzione javascript necessaria allo scopo, sfruttando anche la proprietà CSS z-index: tale proprietà infatti ci consente di posizionare un’altro elemento sopra l’immagine originale.
Volendo virare le immagini con tre differenti colori, come prima cosa creiamo un array con i colori da applicare alle immagini:
var toColor = { 0 : '#ff0000', 1 : '#ff9900', 2 : '#FFFFFF' };
A questo punto eseguiamo un ciclo sulle immagini principali: “avvolgiamo” ogni immagine in un div contenitore e la cloniamo assegnandoli la classe ‘item-vired’.
Inseriamo quindi l’immagine clonata prima dell’immagine originale ed infine assegniamo al contenitore le dimensioni dell’immagine.
jQuery('.item').each( function () { var el = jQuery(this); el.wrap("<div class='img_wrapper'>") .clone() .addClass('item_vired') .insertBefore(el).queue( function () { var el = jQuery(this); el.parent().css({ "width": this.width, "height": this.height }); el.dequeue(); }); });
Il metodo .queue() ci permette di manipolare direttamente una coda di funzioni.
Inoltre richiamando il metodo con una funzione di callback ci permette di collocare una nuova funzione alla fine della coda.
La funzione di callback verrà eseguita una volta per ogni elemento.
Utilizziamo quindi la funzione tintImage per virare ogni immagine con il proprio colore assegnato precedentemente tramite l’array toColor definito all’inizio.
A questo punto abbiamo quindi un contenitore ( img_wrapper ) con all’interno due immagini: quella clonata e virata ( item_wired ) e quella originale ( item ).
Qui ci vengono in aiuto le proprietà CSS z-index e position: il contenitore infatti verrà posizionato in maniera relativa mentre le due immagini saranno posizionate in modo assoluto.
Inoltre all’immagine virata verrà dato uno z-index di 100 per posizionarla al di sopra di quella originale.
A questo punto utilizziamo le funzioni mouseover e mouseout sul contenitore per ottenere l’effetto voluto: useremo un’animazione per modificare l’opacità dell’immagine virata per far apparire l’immagine originale posizionata esattamente sotto di essa.
jQuery('.img_wrapper').mouseover(function () { jQuery(this).children('.item_vired').stop().animate({ opacity: 0, }, 500); }); jQuery('.img_wrapper').mouseout(function () { jQuery(this).children('.item_vired').stop().animate({ opacity: 1, }, 500); })
Ovviamente il tutto andrà eseguito al document.ready.
Otteniamo quindi il seguente codice javascript
jQuery(function () { jQuery(window).load(function () { var toColor = { 0 : '#ff0000', 1 : '#ff9900', 2 : '#FFFFFF' }; jQuery('.item').each( function () { var el = jQuery(this); el.wrap("<div class='img_wrapper'>") .clone() .addClass('item_vired') .insertBefore(el).queue( function () { var el = jQuery(this); el.parent().css({ "width": this.width, "height": this.height }); el.dequeue(); }); }); jQuery('.item_vired').each(function (index, value) { tintImage(this, toColor[index]); }); jQuery('.img_wrapper').mouseover(function () { jQuery(this).children('.item_vired').stop().animate({ opacity: 0, }, 500); }); jQuery('.img_wrapper').mouseout(function () { jQuery(this).children('.item_vired').stop().animate({ opacity: 1, }, 500); }); }); }); function tintImage(imgElement, tintColor) { var canvas = document.createElement("canvas"); canvas.width = imgElement.offsetWidth; canvas.height = imgElement.offsetHeight; var ctx = canvas.getContext("2d"); ctx.drawImage(imgElement, 0, 0); var map = ctx.getImageData(0, 0, imgElement.offsetWidth, imgElement.offsetHeight); // Corretto su segnalazione di Paolo var imdata = map.data; var r, g, b, avg; for ( var p = 0, len = imdata.length; p < len; p += 4 ) { r = imdata[p]; g = imdata[p + 1]; b = imdata[p + 2]; avg = Math.floor((r + g + b) / 3); imdata[p] = imdata[p + 1] = imdata[p + 2] = avg; } ctx.putImageData(map, 0, 0); ctx.globalCompositeOperation = "lighter"; ctx.globalAlpha = 0.5; ctx.fillStyle = tintColor; ctx.fillRect(0, 0, canvas.width, canvas.height); imgElement.src = canvas.toDataURL(); }
Il codice CSS invece sarò il seguente:
.img_wrapper {position:relative;float:left;display:inline-block;margin:0;padding:0 5px;} .item {position:absolute;} .item_vired {position:absolute;z-index:100;opacity:1}
Potete visualizzare la
Questo tutorial ti è servito? Sostieni jQuery Italia con una donazione!
[donateplus]