如何在 Google Apps 脚本中根据单元格的背景颜色反转字体颜色?

问题描述 投票:0回答:3

我想知道如何根据背景颜色自动反转单元格值的字体颜色以使其可读。

我使用以下脚本在将十六进制颜色代码粘贴到给定单元格时自动设置背景颜色如何将单元格更改为 Google 电子表格中单元格的十六进制值的颜色?,带有 示例表这里

function onEdit(e) {
  r = e.range;

  if(r.getSheet().getSheetName() == "colors"){ //the sheet I want to apply this to is called colors

    var rows = r.getNumRows();
    var columns = r.getNumColumns();
    var colors = [] //this is our 2 dimensional array of colors in case you copy and paste a large amount of colors

    for (var i = 1; i <= rows; i++) { //go down each row
      var row = [] //create a new row array to clear the old one when we go down a row
      for (var j = 1; j <= columns; j++) { //then go across each column
        row.push(r.getCell(i,j).getValue()) //put together the row of colors
      }
      colors.push(row); //insert our row of colors so we can go down the next row
    }
    r.setBackgrounds(colors) //batch update in case you update many colors in one copy and paste otherwise it will be very slow
  }
}

但剩下的问题是字体没有显示在深色背景单元格上。

我还发现了这个相关问题如何根据背景颜色决定白色或黑色的字体颜色?。 以及那些带有函数的 Javascript 特定答案,但我无法使它们与 GAS 中的上述脚本一起使用。

JavaScript代码1

JavaScript代码2

JavaScript代码3

JavaScript代码4

JavaScript代码5

JavaScript代码6

我还查看了 setFontColors(colors) 的文档,发现我们可以使用上面脚本中的

r.setFontColors(colors)
方法。 我尝试调用上面的 JavaScript 代码 1 到 6,但没有成功。

例如,我尝试过这种基于 JavaScript 代码 3 )的方法:

function onEdit(e) {
  r = e.range;

  if(r.getSheet().getSheetName() == "colors"){ //the sheet I want to apply this to is called colors

    var rows = r.getNumRows();
    var columns = r.getNumColumns();
    var colors =  [] //this is our 2 dimensional array of colors in case you copy and paste a large amount of colors

    for (var i = 1; i <= rows; i++) { //go down each row
      var row = [] //create a new row array to clear the old one when we go down a row
      for (var j = 1; j <= columns; j++) { //then go across each column
        row.push(r.getCell(i,j).getValue()) //put together the row of colors
      }
      colors.push(row); //insert our row of colors so we can go down the next row
    }
    r.setBackgrounds(colors) //batch update in case you update many colors in one copy and paste otherwise it will be very slow
    r.setFontColors(lum([111, 22, 255]));
  }
}

function lum(rgb) {
    var lrgb = [];
    rgb.forEach(function(c) {
        c = c / 255.0;
        if (c <= 0.03928) {
            c = c / 12.92;
        } else {
            c = Math.pow((c + 0.055) / 1.055, 2.4);
        }
        lrgb.push(c);
    });
    var lum = 0.2126 * lrgb[0] + 0.7152 * lrgb[1] + 0.0722 * lrgb[2];
    return (lum > 0.179) ? '#000000' : '#ffffff';
}

我错过了什么?

感谢您的见解!

google-apps-script google-sheets colors rgb
3个回答
3
投票

我相信您的目标如下。

  • 将十六进制值放入单元格后,您希望使用输入的十六进制值设置背景颜色。那时,您要根据背景颜色设置每个单元格的字体颜色。

修改要点:

  • 在您的脚本中,我认为

    colors
    的值可以通过
    r.getValues()
    检索。在这种情况下,不需要使用 for 循环。

  • 来自

    r.setFontColors(lum([111, 22, 255]));
    ,当你想给范围设置相同的字体颜色时,可以进行如下修改。

    • 来自

        r.setFontColors(lum([111, 22, 255]));
      
    •   r.setFontColor(lum([111, 22, 255]));
      

但是,从您的脚本来看,我认为您可能想按每种背景颜色设置字体颜色。如果我的理解正确的话,下面的修改如何?

修改后的脚本:

// I modified this function.
function onEdit(e) {
  var r = e.range;
  if (r.getSheet().getSheetName() == "colors") {
    var colors = r.getValues();
    r.setBackgrounds(colors);
    var fonrColors = r.getBackgroundObjects().map(r => r.map(c => {
      var obj = c.asRgbColor();
      return lum([obj.getRed(), obj.getGreen(), obj.getBlue()]);
    }))
    r.setFontColors(fonrColors);
  }
}

// This is from your script.
function lum(rgb) {
  var lrgb = [];
  rgb.forEach(function (c) {
    c = c / 255.0;
    if (c <= 0.03928) {
      c = c / 12.92;
    } else {
      c = Math.pow((c + 0.055) / 1.055, 2.4);
    }
    lrgb.push(c);
  });
  var lum = 0.2126 * lrgb[0] + 0.7152 * lrgb[1] + 0.0722 * lrgb[2];
  return (lum > 0.179) ? '#000000' : '#ffffff';
}
  • 在这次修改中,为了将十六进制转换为RGB,我使用了

    getBackgroundObjects()
    的方法。当然,您可以使用 Javascript 对其进行转换。如果您不想使用
    getBackgroundObjects()
    ,请检查此线程

  • 在此修改中,当您将十六进制值放入单元格时,将使用十六进制值设置背景颜色,并使用脚本的函数

    lum
    根据背景颜色设置字体颜色。

参考资料:


1
投票

setFontColors
的必需参数是一个二维数组

尝试将

r.setFontColors(lum([111, 22, 255]));
更改为以下代码:

const fontColor = lum([111, 22, 255]);
const fontColorsRow = new Array(columns).fill(fontColor);
const fontColors = new Array(rows).fill(fontColorsRow);
r.setFontColors(fontColors);

参考:

设置字体颜色(颜色)


1
投票

简短回答

要根据背景颜色在黑色或白色之间翻转文本颜色,您需要将背景颜色转换为亮度,并选择特定的亮度值进行翻转,通常约为 0.36 Y(标准 CIE 相对亮度)效果很好。

更长的答案

现实情况是,有许多心理物理因素会影响从黑色或白色文本翻转的最佳点,而且它们并不全与特定颜色有关。字体大小和粗细、周围的颜色以及房间内的环境照明都会影响“理想的翻转点”。

我在关于溢出的另一个答案中用简单的代码片段讨论了这个问题。在回答之后,我还创建了一个 CodePen,其中包含实例,您可以使用它。

“超级简单又脏”的是:

// First convert your sRGB values to luminance:

let sY = Math.pow(sR/255.0,2.2) * 0.2126 +
         Math.pow(sG/255.0,2.2) * 0.7152 +
         Math.pow(sB/255.0,2.2) * 0.0722; // Andy's Easy Luminance for sRGB. For Rec709 HDTV change the 2.2 to 2.4

// AND THEN SET THE TEXT COLOR PER:

  let textColor = (sY < 0.36) ? "#fff" : "#000"; // Low budget down and dirty text flipper.

这是最少、最简单的代码,应该很容易移植。我不熟悉Google脚本,但基本上你只需要将每个8位颜色除以255.0,然后应用2.2指数,然后乘以系数(红色为0.2126,绿色为0.7152,蓝色为0.0722)并相加。

以约 0.36 翻转 - 可翻转范围约为 0.34 至 0.42~ish,具体取决于。

如果您真的想深入了解文本对比的本质世界以提高可读性,请查看 APCA 和 SAPC — 在 SAPC 开发站点单击“研究模式”来进行演示概念的交互式实验。这些是确定自发光显示器对比度的新方法。

编辑添加,有一个新的 GitHub 存储库“最大对比度”,它具有 APCA 兼容的字体颜色翻转器。

© www.soinside.com 2019 - 2024. All rights reserved.