【问题标题】:How to inverse font color based on cell's background Color in Google Apps Script?如何根据 Google Apps 脚本中单元格的背景颜色反转字体颜色?
【发布时间】:2021-12-27 02:10:58
【问题描述】:

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

我使用以下脚本在将十六进制颜色代码粘贴到给定单元格How do I change a cell to the color of the hexadecimal value of a cell in Google Spreadsheets?sample sheet here 时自动设置背景颜色

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
  }
}

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

我也发现了这个相关的问题How to decide font color in white or black depending on background color?。 还有那些带有函数的 Javascript 特定答案,但我无法让它们与 GAS 中的上述脚本一起工作。

JavaScript code 1

JavaScript code 2

JavaScript code 3

JavaScript code 4

JavaScript code 5

JavaScript code 6

我还查看了setFontColors(colors) 的文档,发现我们可以在上面的脚本中使用r.setFontColors(colors) 方法。 我尝试调用上面的 JavaScript 代码 1 到 6,但没有成功。

例如,我根据JavaScript code 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


    【解决方案1】:

    我相信你的目标如下。

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

    修改点:

    • 在您的脚本中,我认为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(),请查看this thread

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

    参考资料:

    【讨论】:

    • 嗨@Tanaike,很高兴再次收到您的来信,希望您一切顺利!非常感谢详细的脚本(一如既往的好)和见解!原始脚本不是我的,但我想我会按照 OP 的建议尝试修改它。感谢setFontColor() 的更正(我原以为是SetFontColors() 会逐个单元格地进行颜色处理:))。非常感谢getBackgroundObjects() 的参考,它有很大帮助(我从文档中看到它返回Color[][](相对于String[][]setBackgrounds())。接下来我会仔细研究你的函数!好好的!
    • @Lod 感谢您的回复。我很高兴你的问题得到了解决。也谢谢你。
    【解决方案2】:

    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);
    

    参考:

    setFontColors(colors)

    【讨论】:

    • 嗨@idfurw,非常感谢您提供有趣的见解!经过一些试验,我设法使它也可以与您的代码一起使用。完整代码在这里:pastebin.com/pwBMafKFBe well!
    【解决方案3】:

    简答

    要根据背景颜色在黑色或白色之间翻转文本颜色,您需要将背景颜色转换为亮度,并选择一个特定的亮度值进行翻转,通常在 0.42 Y 左右即可。

    更长的答案

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

    我在another answer on overflow 中使用简单的代码 sn-ps 讨论了这个问题。在那个答案之后,我还创建了一个 CodePen with live examples 你可以玩。

    “超级简单粗暴”是:

    // 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.42) ? "#fff" : "#000"; // Low budget down and dirty text flipper.
    
    

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

    在 0.4 左右翻转 - 可翻转范围约为 0.36 到 0.43 ish,具体取决于。

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

    【讨论】:

    • 非常感谢您的精彩解释和所有共享资源。这些太棒了!我会尽快测试!再次感谢,祝您身体健康!
    猜你喜欢
    • 2013-06-03
    • 2014-02-21
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2021-02-21
    相关资源
    最近更新 更多