发布于 2026-01-05 3 阅读
0

如何在图片上制作动态文字叠加层

如何在图片上制作动态文字叠加层

如果你开发过网页应用,肯定对这种情况很熟悉。很多时候,你需要给图片添加文字。如果图片是用户上传的,那么很难预测什么颜色的文字与图片搭配。请看以下示例:

“Rachel Rose”这个文字在深色背景上看起来很棒,但如果背景是白色呢?这可能会造成问题,因为你永远无法预测用户会上传什么内容。

一个简单的解决方法是像这样对图像使用模糊滤镜……

    .image-blur{
        filter: blur(1px);
    }
Enter fullscreen mode Exit fullscreen mode

或者在图像上添加一层深色图层。有很多方法可以做到这一点,但这些方法都依赖于对图像的修改。但是,如果我们不改变图像,而是改变文本颜色呢?

“为什么不呢?”这是我最近想到这个问题时对自己说的。那么,让我们在这篇文章中探讨一下如何做到这一点。

怎么做?

我创建了一个简单的页面来演示这个问题。如果你想边学边做,只需克隆这个仓库即可。

GitHub 标志 sarthology / dynalay-demo

如何在图像上制作动态文本叠加层

Dynalay演示

一种在图像上创建动态文字叠加层的简单方法。点击此处查看。

截屏

先决条件

在本地运行此程序之前,您必须已安装以下软件。

  • 节点
  • Webpack

安装

它是用 Node.js 构建的,所以启动过程非常简单。

  1. npm install
  2. npm run start:dev

就这样,你会在 localhost:8080 上看到它运行。

贡献

欢迎大家为这个项目贡献力量,并像对待自己的项目一样对待它。😊

作者

萨尔塔克·夏尔马




克隆完成后,使用此提交来检出未解决的问题。

   git checkout 0817434   
   npm install
   npm run start:dev
Enter fullscreen mode Exit fullscreen mode

目前,我们的网页有两种背景:深色和浅色。网页上还有两个按钮用于切换背景。这是它最初的样子。

为了实现这一点,我们将使用画布。思路是将图像加载到画布中,然后获取图像的每一个像素。每个像素的颜色将被转换为其RGB值。因此,如果将这三个值取平均值,即可得到该像素的亮度(更多信息请点击此处)。这些值介于 0(最暗)和 255(最亮)之间。通过比较每个像素的亮度,我们可以判断图像是暗还是亮。

太好了,既然我们已经了解了算法,那就让我们编写一些代码吧。

首先,创建一个函数,将背景中的 src 加载到隐藏img元素中。

    const isDark = (src)=>{
        //create a hidden img element
        let img = document.createElement("img");
        img.src = src;
        img.style.display = "none";
        document.body.appendChild(img);
    }
Enter fullscreen mode Exit fullscreen mode

然后使用以下方法在画布上绘制图像

const isDark = (src)=>{

    //create a hidden img element
    let img = document.createElement("img");
    img.src = src;
    img.style.display = "none";
    document.body.appendChild(img);

    img.onload = function() {
        // create canvas
        let canvas = document.createElement("canvas");
        canvas.width = this.width;
        canvas.height = this.height;

        let ctx = canvas.getContext("2d");
        ctx.drawImage(this,0,0);
    }
}
Enter fullscreen mode Exit fullscreen mode

现在我们需要获取每个像素的 RGB 值。为此,我们使用getImageData

    let imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
Enter fullscreen mode Exit fullscreen mode

输出结果将类似于

太好了!现在我们有了数据,但是它是一个巨大的数组,其中每个像素的 RGB 值都是像这样单独存储的。

所以我们需要像这样一起循环遍历它们四个。

        let imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
        let data = imageData.data;
        let r,g,b,avg;
        for(let x = 0, len = data.length; x < len; x+=4) {
            r = data[x];
            g = data[x+1];
            b = data[x+2];
            avg = Math.floor((r+g+b)/3);
        }
Enter fullscreen mode Exit fullscreen mode

avg现在得到了每个像素的平均RGB值。接下来,将所有像素的平均值相加,然后除以图像中的像素总数,即可得到平均亮度。

       let brightness = Math.floor(colorSum / (this.width*this.height));
Enter fullscreen mode Exit fullscreen mode

所以最终的函数看起来会像这样:

const isDark = (src) => {
    return new Promise((resolve, reject) => {
        //create a hidden img element
        let img = document.createElement("img");
        img.src = src;
        img.style.display = "none";
        document.body.appendChild(img);

        let colorSum = 0;
        img.onload = function () {
            // create canvas
            let canvas = document.createElement("canvas");
            canvas.width = this.width;
            canvas.height = this.height;

            let ctx = canvas.getContext("2d");
            ctx.drawImage(this, 0, 0);

            let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            let data = imageData.data;
            let r, g, b, avg;
            for (let x = 0, len = data.length; x < len; x += 4) {
                r = data[x];
                g = data[x + 1];
                b = data[x + 2];

                avg = Math.floor((r + g + b) / 3);
                colorSum += avg;
            }

            let brightness = Math.floor(colorSum / (this.width * this.height));
            resolve(brightness >= 128 ? false : true);
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

我们用这个函数来检查图像是否偏暗。

    isDark('./images/dbg.jpg').then((data) => {
        dynamicHeader.classList.remove("light-text");
        if(data) dynamicHeader.classList.add("light-text");
    });
Enter fullscreen mode Exit fullscreen mode

这就是我们的结果:

但好像少了点什么。啊哈,一点风格!

.dynamic-header {
    transition: color 2s;
}
Enter fullscreen mode Exit fullscreen mode

现在完美了。

结论

希望你们喜欢这个小实验,并从中有所收获。实现相同结果的方法有很多,如果你有其他方法,欢迎在下方留言。你或许会想在实际项目中使用这个方法,或许不会,但我正在考虑将其开发成一个 npm 包,以便更进一步。如果你想参与,请私信我@sarthology或直接在下方留言。

好了各位!下次再见。感谢阅读。

文章来源:https://dev.to/xenoxdev/how-to-make-dynamic-text-overlays-on-images-dcc