EDIT : Ce n'est qu'après avoir posté ce message que j'ai réalisé que la réponse de @350D faisait exactement la même chose.
Étonnamment, cela peut être fait en seulement 4 lignes de code :
const canvas = document.getElementById("canvas"),
preview = document.getElementById("preview"),
ctx = canvas.getContext("2d");
canvas.width = 1;
canvas.height = 1;
preview.width = 400;
preview.height = 400;
function getDominantColor(imageObject) {
//draw the image to one pixel and let the browser find the dominant color
ctx.drawImage(imageObject, 0, 0, 1, 1);
//get pixel color
const i = ctx.getImageData(0, 0, 1, 1).data;
console.log(`rgba(${i[0]},${i[1]},${i[2]},${i[3]})`);
console.log("#" + ((1 << 24) + (i[0] << 16) + (i[1] << 8) + i[2]).toString(16).slice(1));
}
// vvv all of this is to just get the uploaded image vvv
const input = document.getElementById("input");
input.type = "file";
input.accept = "image/*";
input.onchange = event => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = readerEvent => {
const image = new Image();
image.onload = function() {
//shows preview of uploaded image
preview.getContext("2d").drawImage(
image,
0,
0,
preview.width,
preview.height,
);
getDominantColor(image);
};
image.src = readerEvent.target.result;
};
reader.readAsDataURL(file, "UTF-8");
};
canvas {
width: 200px;
height: 200px;
outline: 1px solid #000000;
}
<canvas id="preview"></canvas>
<canvas id="canvas"></canvas>
<input id="input" type="file" />
Comment cela fonctionne :
Créer le contexte de la toile
const context = document.createElement("canvas").getContext("2d");
L'image ne sera dessinée que sur un seul pixel de la toile, ce qui permettra au navigateur de trouver la couleur dominante à votre place.
context.drawImage(imageObject, 0, 0, 1, 1);
Après cela, il suffit de récupérer les données de l'image pour le pixel :
const i = context.getImageData(0, 0, 1, 1).data;
Enfin, convertissez en rgba
o HEX
:
const rgba = `rgba(${i[0]},${i[1]},${i[2]},${i[3]})`;
const HEX = "#" + ((1 << 24) + (i[0] << 16) + (i[1] << 8) + i[2]).toString(16).slice(1);
Il y a cependant un problème avec cette méthode, et c'est que getImageData
provoquera parfois des erreurs Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
C'est la raison pour laquelle vous devez télécharger des images dans la démo au lieu de saisir une URL, par exemple.
Cette méthode peut également être utilisée pour la pixellisation des images en augmentant la largeur et la hauteur pour dessiner l'image.
Cela fonctionne sur chrome mais peut ne pas fonctionner sur d'autres navigateurs.
24 votes
Mon ami Boaz a déjà emprunté cette voie (j'espère qu'il nous dira ce qu'il en pense) mais la moyenne vous laisse généralement avec une couleur semblable au vomi. Ce que vous voulez vraiment, c'est une "couleur dominante". Il y a plusieurs façons de l'obtenir (histogramme de la teinte avec répartition dynamique, etc.) mais je pense que c'est probablement plus précis pour le résultat que tu veux obtenir.