Vue 3: 通过图片链接获取图片颜色,间接设置背景颜色

发布于:2024-12-18 ⋅ 阅读:(191) ⋅ 点赞:(0)

       在现代Web开发中,动态获取和处理图像数据是一个常见的需求。例如,你可能希望自动提取一张图片的主色调,以便根据这些颜色进行UI主题调整或其他视觉效果的处理。本文将介绍如何在Vue 3项目中,通过一个图片链接获取图片的颜色信息。

适用场景:设置背景色(例如:根据音乐图片设置主题色)
案例地址:(音乐模块的歌词)

天梦星科技官网icon-default.png?t=O83Ahttps://tmxkj.top/#/music案例截图:

1.废话不多说直接上代码(代码已经封装好,直接调用即可)

async function analyzeImageColors(imageUrl) {
    try {
        const image = new Image();
        image.crossOrigin = 'Anonymous'; // This is important for CORS issues
        image.src = imageUrl;

        await new Promise((resolve, reject) => {
            image.onload = () => resolve();
            image.onerror = (err) => reject(err);
        });

        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        canvas.width = image.width;
        canvas.height = image.height;
        context.drawImage(image, 0, 0, image.width, image.height);

        const imageData = context.getImageData(0, 0, image.width, image.height).data;
        return getColorsFromImageData(imageData, image.width, image.height);
    } catch (error) {
        console.error('Error analyzing image:', error);
        return null;
    }
}

/**
 * 获取图片颜色
 * @param imageData
 * @param width
 * @param height
 * @description 颜色分别是四个角是颜色,中间是颜色,主体颜色,平均颜色,一共七个颜色
 * @returns {{
 * middleColors: string[]
 * average: string,
 * corners: (string|null)[],
 * dominant: null,
 * secondDominant: null
 * }}
 */
function getColorsFromImageData(imageData, width, height) {
    const colorCount = {};
    let r = 0, g = 0, b = 0;
    let totalPixels = width * height;

    // Initialize corner colors and middle color arrays
    const corners = [null, null, null, null];
    const middleColors = [];

    for (let i = 0; i < imageData.length; i += 4) {
        const red = imageData[i];
        const green = imageData[i + 1];
        const blue = imageData[i + 2];
        const alpha = imageData[i + 3];

        if (alpha === 0) continue; // Skip transparent pixels

        const colorKey = `${red},${green},${blue}`;
        if (!colorCount[colorKey]) {
            colorCount[colorKey] = 0;
        }
        colorCount[colorKey]++;

        r += red;
        g += green;
        b += blue;

        // Determine if the pixel is a corner or middle pixel
        const x = (i / 4) % width;
        const y = Math.floor((i / 4) / width);
        if (x === 0 && y === 0) {
            corners[0] = colorKey;
        } else if (x === width - 1 && y === 0) {
            corners[1] = colorKey;
        } else if (x === 0 && y === height - 1) {
            corners[2] = colorKey;
        } else if (x === width - 1 && y === height - 1) {
            corners[3] = colorKey;
        } else if (x === Math.floor(width / 2) && y === Math.floor(height / 2)) {
            middleColors.push(colorKey);
        }
    }

    // Find the dominant and second dominant colors
    let dominantColor = null;
    let secondDominantColor = null;
    let maxCount = 0;
    let secondMaxCount = 0;

    for (const [color, count] of Object.entries(colorCount)) {
        if (count > maxCount) {
            secondMaxCount = maxCount;
            secondDominantColor = dominantColor;
            maxCount = count;
            dominantColor = `rgba(${color})`;
        } else if (count > secondMaxCount) {
            secondMaxCount = count;
            secondDominantColor = `rgba(${color})`;
        }
    }

    // Calculate average color
    const averageColor = `rgba(${Math.round(r / totalPixels)}, ${Math.round(g / totalPixels)}, ${Math.round(b / totalPixels)})`;

    return {
        corners: corners.map(color => color ? `rgba(${color})` : null),
        middleColors: middleColors.map(color => `rgba(${color})`),
        dominant: dominantColor,
        secondDominant: secondDominantColor,
        average: averageColor,
    };
}

/**
 * 创建渐变色180deg
 * @param mainColor   1主色
 * @param topRight    2右上角颜色
 * @param center      3中心颜色
 * @param bottomRight 4右下角颜色
 * @param deg         5径向,默认180deg
 * @returns {string} 返回渐变色字符串
 */
function createRadialGradient(mainColor,topRight,center,bottomRight,deg=180) {
    return `background: ${mainColor};background: linear-gradient(${deg}deg, ${topRight} 0%,${center}  50%, ${bottomRight} 100%);`
}


export {
    analyzeImageColors,
    createRadialGradient
};

2.调用方法

/**
 * 设置背景颜色
 * @param url
 * @returns {Promise<string|string>}
 */
function setBackgroundColor(url) {
  analyzeImageColors(url ||  'https://ts3.cn.mm.bing.net/th?id=OIP-C.8tlwbGsJvlNZwGAGL36W8AHaFS&w=295&h=211&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2').then(res => {
    backgroundStyle.value = createRadialGradient(res.dominant, res.corners[1], res.middleColors, res.corners[3]) || '';
  })
}


网站公告

今日签到

点亮在社区的每一天
去签到