Javascript 使用RGBaster.js控制多幅图像的颜色

Javascript 使用RGBaster.js控制多幅图像的颜色,javascript,jquery,foreach,Javascript,Jquery,Foreach,我有这段代码,找到图像的主导颜色(使用),然后将其转换为平面颜色,并给图像旁边的信息框颜色。同时,它使文字颜色在YIQ scala之后变为白色或黑色 function getContrastYIQ(hexcolor){ var r = parseInt(hexcolor.substr(1,2),16); var g = parseInt(hexcolor.substr(3,2),16); var b = parseInt(hexcolor.substr(4,2),16);

我有这段代码,找到图像的主导颜色(使用),然后将其转换为平面颜色,并给图像旁边的信息框颜色。同时,它使文字颜色在YIQ scala之后变为白色或黑色

function getContrastYIQ(hexcolor){
    var r = parseInt(hexcolor.substr(1,2),16);
    var g = parseInt(hexcolor.substr(3,2),16);
    var b = parseInt(hexcolor.substr(4,2),16);
    var yiq = ((r*299)+(g*587)+(b*114))/1000;
    return (yiq >= 128) ? 'black' : 'white';
}



var img = $('.category').attr('data-background');
var colors = RGBaster.colors(img, {
    paletteSize: 5,
    success: function(colors){

        console.log("-----------------------------------------------");
        console.log("Dominant color:", colors.dominant);
        console.log("-----------------------------------------------");

        var rgb = colors.dominant;
        rgb = rgb.substring(4, rgb.length-1).replace(/ /g, '').split(',');

        var flatColors = FlatColors(rgb);
        var flatColor = flatColors[3];

        var textColor = getContrastYIQ(flatColor);
        console.log(textColor);

        $(".category").css('background-image', 'url(' + img + ')');
        $(".category .info").css('background-color', flatColor);
        $(".text").css('color', textColor);
        $(".text").text(flatColors[4]);
    }
});
问题来了
我有多个div,名称如下:

<div class="category" data-background="images/7.jpg">
    <div class="info">
        <p class="text">Hello World</p>
    </div>
</div>

但那没用。所以现在我需要一些帮助。

你需要承诺

您有一个回调操作—比代码的其余部分触发得晚:

function colorPick(img) {
    RGBaster.colors(img, {
    paletteSize: 5,
        success: function(colors){ 

            var rgb = colors.secondary;
            rgb = rgb.substring(4, rgb.length-1).replace(/ /g, '').split(',');

            var flatColors = FlatColors(rgb);
            console.log("Return:", flatColors[3]);

            return flatColors[3]; // returns the parent function, success                       
        }
    });

    // colorPick itself doesn't return at all, which is why you get undefined
}
您需要返回一个
承诺
——一个保存异步操作并在其完成时解析的对象:

function colorPick(img) {
    // Now colorPick returns the promise
    return new Promise(function(resolve, reject) {
        RGBaster.colors(img, {
            paletteSize: 5,
            success: function(colors){ 

                var rgb = colors.secondary;
                rgb = rgb.substring(4, rgb.length-1).replace(/ /g, '').split(',');

                // Check this shouldn't be "new FlatColors", as CapitalCase usually means it needs "new"
                var flatColors = FlatColors(rgb);
                console.log("Return:", flatColors[3]);

                // Resolve the promise
                // I've passed it the FlatColors object so the callback can access all of it
                resolve(flatColors); 
            }
        });
    });
}
然后,您可以使用
。然后使用

$('.category').each(function(){
    var $this = $(this); // avoid calling multiple times
    var img = $this.attr('data-background');

    $this.css('background-image', 'url(' + img + ')');

    // .then fires the function when the promise completes.
    colorPick(img).then(function(colors) {
        var flatColor = colors[3];

        // Set the background colour
        $this.find('.info').css('background-color', flatColor);

        var textColor = getContrastYIQ(flatColor);
        var $text = $this.find('.text');

        $text.css('color', textColor);
        $text.text(colors[4]);

        return colors; 
    }).then(console.log); // You can chain promises
});
或者使用
async
/
await
语法:

$('.category').each(async function(){
    const $this = $(this); // avoid calling multiple times
    const img = $this.attr('data-background');

    // If we can use async/await we can also use const and iterpolated strings
    $this.css('background-image', `url(${img})`);

    // await continues this function after the promise completes
    const color = await colorPick(img);
    const flatColor = colors[3];

    // Set the background colour
    $this.find('.info').css('background-color', flatColor);

    const textColor = getContrastYIQ(flatColor);
    const $text = $this.find('.text');

    $text.css('color', textColor);
    $text.text(colors[4]);

    console.log(colors);
});
我建议您等待
,但如果您支持较旧的浏览器,您可能需要传输您的JS,因为它是相当新的

该方法一次解析一种颜色,但您可能需要比较多种颜色的结果。方法是使用
Promise.all
,它等待承诺集合完成,然后返回其结果数组:

// Get the dominant colours in all the images on one array
const colors = await Promise.all(
    images.map(i => colorPick(i)));
它将所有图像映射到一个承诺数组,所有图像都等待
colorPick
函数完成,然后等待所有图像完成


最后,您的问题已标记为的副本。这个问题的首要答案是关于使用Promissions和async/await的详细信息,比我这里介绍的要详细得多。

仔细想想,返回值会到哪里去?@Teemu I用其余的更新代码;)因此,您可以查看函数
colorPick
也必须return@MasterYoda1.很棒的昵称。2.你是什么意思?@TheCrazyProfessor编辑之前我知道它要去哪里,但我想让你回答这个问题。我同意,原因并不总是很明显(只看一些问题评论(现在已删除)),这个问题每天被问10次。问题是相同的,解决方案是相同的,因此重复。副本提供了大量信息,包括使用Promissions和Wait的版本,每次询问此问题时(以任何形式)复制部分信息是没有意义的。问题完全相同。这里的问题是,为什么回调中的
返回不能像OP所期望的那样工作。他们不知道异步回调是如何工作的,因此无法提出正确的问题,但这正是他们需要问的问题。@Keith这个网站不是这样工作的。OP需要转到链接副本并阅读问题。代码示例实际上与他们的完全相同,即使他们问的问题不完全相同。一旦他们阅读了这个问题,他们应该更好地理解为什么答案是正确的。@Keith你应该按照这个规则关闭这个网站上80%的问题。像这样的问题一天会被问十几次,而我们的问题中没有“承诺”或“异步”这两个词。它们都应作为链接问题的副本关闭。这个网站的重点是提供规范的答案,而不是为人们能想到的同一个问题的每一个变体提供唯一的答案。你提供的答案比那些非常全面的答案更糟糕,这并没有帮助OP,你也没有帮助网站。你似乎只对展示你的知识感兴趣,否则你会更乐意将人们与现有的更好的答案联系起来。欢迎您继续回答问题,而不是链接到现有的重复问题,但是当您的答案与重复问题一起被删除时,请不要感到惊讶。
// Get the dominant colours in all the images on one array
const colors = await Promise.all(
    images.map(i => colorPick(i)));