画像の支配色を返すカスタムhook
投稿日: 2025年10月03日
画像の背景色を、画像に近い色味にしたいと思いました。
↓こんな感じ
画像から支配色のカラーコードを取得するライブラリがメンテされていないものばかりだったのですが、
canvasを用いることすぐに作れたので、共有します。
useImageAverageColor.ts
import { useEffect, useState } from "react";
const FALLBACK_COLOR = "#fff";
export function useImageAverageColor(src: string | null | undefined) {
const [color, setColor] = useState<string>(FALLBACK_COLOR);
useEffect(() => {
if (!src) {
setColor(FALLBACK_COLOR);
return;
}
if (typeof window === "undefined") {
return;
}
let isCancelled = false;
const img = new window.Image();
img.crossOrigin = "anonymous";
img.src = src;
const handleLoad = () => {
if (isCancelled) return;
const width = 32;
const height = 32;
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
if (!ctx) return;
try {
ctx.drawImage(img, 0, 0, width, height);
const { data } = ctx.getImageData(0, 0, width, height);
let r = 0;
let g = 0;
let b = 0;
let count = 0;
for (let i = 0; i < data.length; i += 4) {
r += data[i];
g += data[i + 1];
b += data[i + 2];
count++;
}
if (count === 0) return;
const red = Math.round(r / count);
const green = Math.round(g / count);
const blue = Math.round(b / count);
setColor(`rgb(${red}, ${green}, ${blue})`);
} catch {
// CORS 制限などで getImageData が失敗した場合
setColor(FALLBACK_COLOR);
}
};
const handleError = () => {
if (isCancelled) return;
setColor(FALLBACK_COLOR);
};
img.onload = handleLoad;
img.onerror = handleError;
return () => {
isCancelled = true;
img.onload = null;
img.onerror = null;
};
}, [src]);
return color;
}
使い方
const agerageColor = useImageAverageColor("https://hogehoge.com/image_path")