uni-app 实现图片主题色的获取

uni-app 实现图片主题色的获取

<canvas canvas-id="getImageThemeColorCanvas" id="getImageThemeColorCanvas">
</canvas>

canvas 元素默认宽为 300,高为 150。需要注意的是,上述代码不可或缺。

/**
 * 获取图片主题色
 * @param path
 * 图片的路径,可以是相对路径,临时文件路径,存储文件路径,网络图片路径
 * @param canvasId
 * 画布表示
 * @param callback
 * 回调函数,返回图片主题色的 RGB 颜色值
 */
function getImageThemeColor(path, canvasId, callback) {
  uni.getImageInfo({
    src: path,
    success: function (img) {
      // 创建一个 Canvas 对象
      const ctx = uni.createCanvasContext(canvasId);
      // 将图片绘制到 Canvas 上
      const imgWidth = 300;
      const imgHeight = 150;
      ctx.drawImage(img.path, 0, 0, imgWidth, imgHeight);
      ctx.save();
      ctx.draw(true, () => {
        uni.canvasGetImageData({
          canvasId: canvasId,
          x: 0,
          y: 0,
          width: imgWidth,
          height: imgHeight,
          success(res) {
            let data = res.data;
            let arr = [];
            let r = 1,
              g = 1,
              b = 1;
            // 取所有像素的平均值
            for (let row = 0; row < imgHeight; row++) {
              for (let col = 0; col < imgWidth; col++) {
                if (row == 0) {
                  r += data[imgWidth * row + col];
                  g += data[imgWidth * row + col + 1];
                  b += data[imgWidth * row + col + 2];
                  arr.push([r, g, b]);
                } else {
                  r += data[(imgWidth * row + col) * 4];
                  g += data[(imgWidth * row + col) * 4 + 1];
                  b += data[(imgWidth * row + col) * 4 + 2];
                  arr.push([r, g, b]);
                }
              }
            }
            // 求取平均值
            r /= imgWidth * imgHeight;
            g /= imgWidth * imgHeight;
            b /= imgWidth * imgHeight;
            // 将最终的值取整
            r = Math.round(r);
            g = Math.round(g);
            b = Math.round(b);

            if (!!callback) {
              // 返回图片主题色的 RGB 颜色值
              callback(`${r},${g},${b}`);
            }
          },
        });
      });
    },
  });
}

上述代码通过使用 uni-app 的 API uni.getImageInfouni.createCanvasContextuni.canvasGetImageData 实现图片主题色获取,以兼容 H5 和 微信小程序等,并以 canvas 默认的宽高进行绘制。

调用示例:

const imgUrl = "https://asset.example.com/bjpic/mscrmqh/temp/1691118468757.png";
getImageThemeColor(imgUrl, "getImageThemeColorCanvas", (retRGBColor) => {
  console.log("retRGBColor", retRGBColor);
});

解决 H5 在获取跨域网络图片主题色时报错

错误提示:

canvasGetImageData:fail SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data."

跨域问题解决办法可参考:JavaScript 跨域问题

以通过使用代理服务器解决为例

实现思路:跨域访问 -> 同源访问

通过代理,将跨域访问地址https://asset.example.com/bjpic/mscrmqh/temp/1691118468757.png)替换为同源访问地址http://127.0.0.1:7788/bjpic/mscrmqh/temp/1691118397601.png

开发环境配置

以下通过使用 Webpack 配置代理服务器为例:

// vue.config.js

module.exports = {
  devServer: {
    host: "0.0.0.0",
    port: 9999,
    proxy: {
      "/bjpic": {
        target: "https://asset.example.com",
      },
    },
  },
};

生产环境配置

以下通过使用 Nginx 配置代理服务器为例:

# 代理跨域图片
location /bjpic {
    proxy_pass https://asset.example.com;
}

在 H5 获取跨域网路图片主题色时,将图片地址替换为同源访问地址:http://127.0.0.1:7788/bjpic/mscrmqh/temp/1691118397601.png

将上述调用示例修改为:

const imgUrl = "http://127.0.0.1:7788/bjpic/mscrmqh/temp/1691118397601.png";
getImageThemeColor(imgUrl, "getImageThemeColorCanvas", (retRGBColor) => {
  console.log("retRGBColor", retRGBColor);
});
posted @ 2023-03-16 15:46  飞仔FeiZai  阅读(907)  评论(0编辑  收藏  举报