【问题标题】:xslt change text based on background color brightnessxslt 根据背景颜色亮度更改文本
【发布时间】:2017-09-17 11:46:23
【问题描述】:

xsl 中有没有办法根据背景颜色亮度将文本颜色更改为黑色或白色?

所以在下面的示例中,根据背景颜色亮度,两个问候语都应该有白色文本。 xsl 中是否有内置函数来完成此操作?

xsl

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"/>

  <xsl:template match="greetings">
    <xsl:apply-templates select="greeting"/>
  </xsl:template>

  <xsl:template match="greeting">
    <html>
      <body>
        <h1>
          <span>
            <xsl:attribute name="style">
              background-color: <xsl:value-of select="@backcolor"/>
              color: <!-- Is there a way to make color black or white based on background color brightness? -->
            </xsl:attribute>
            <xsl:value-of select="."/>
          </span>
        </h1>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

xml

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="colortest.xslt"?> <!--todo: change this if copying to new file-->
<!--todo: change preceding line if copying to new file-->
<greetings>
  <greeting id="1" backcolor="f59595">
    Hello World!
  </greeting>
  <greeting id="2" backcolor="ff0000">
    Hola!
  </greeting>
</greetings>

【问题讨论】:

  • 是否需要测试背景颜色的“亮度”,并确定选择白色或黑色文本? listItemColor 变量的格式是什么?
  • 没错,黑色或白色取决于亮度。 listItemColor 可能是十六进制值。但是如果有办法使用颜色名称和十六进制,那也很好。但很可能是十六进制。
  • 你的问题不清楚。请提供一个(或两个)输入示例,以及一组明确的规则来确定所需的输出。
  • 您是否尝试以编程方式生成样式表?因为这就是它的样子。但如果这就是你所做的,我想你会这么说的。因为我们所拥有的只是(a)一个关于颜色和亮度之类的问题描述,而不是元素和属性,以及(b)一些(没有任何上下文)根本没有意义的代码。向我们展示转换的输入和所需输出,并解释它们之间的关系。
  • 我很抱歉造成混淆,我会拿出一个工作示例并更新我的原始帖子。再次,请原谅我,并在这件事上与我同在。

标签: xslt xslt-1.0


【解决方案1】:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xml" href="XSLTFile2.xslt"?>
<greetings>
  <greeting id="1" backcolor="f59595">
    Hello World!
  </greeting>
  <greeting id="2" backcolor="ff0000">
    Hola!
  </greeting>
</greetings>

好的,如果您想使用 css 来控制背景颜色,请在您的 XML 中使用 xml-stylesheet 将其指向执行以下操作的 XSLT 文件。此代码将根据 listItemColor 变量选择正确的样式表,并将 XML 中的 xml-stylesheet 替换为正确的 css 样式表。 (虽然我仍然不知道 listItemColor 是如何获得它的值的。也许你可以告诉我们。)

创建两个样式表,一个用于浅色,一个用于深色。

以下是 XSLTFile2.xslt 文件:

<xsl:variable name="listItemColor" select="'b'"/>

<xsl:template match="processing-instruction('xml-stylesheet')">
  <xsl:choose>
    <xsl:when test="listItemColor ='a'">
      <xsl:processing-instruction name="xml-stylesheet">
        <xsl:text>type="text/css" href="colortest.css"</xsl:text>
      </xsl:processing-instruction>
    </xsl:when>
    <xsl:otherwise>
      <xsl:processing-instruction name="xml-stylesheet">
        <xsl:text>type="text/css" href="colortest2.css"</xsl:text>
      </xsl:processing-instruction>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- Do any other processing. -->

<!-- Identity template.-->
<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>

【讨论】:

  • 根据规范说明修改答案。
  • 因此,Rod 的想法是转换 XML 以使用不同的样式表。然后在该样式表中有不同的设置。然后,当他在浏览器中打开转换后的 XML 时,它要么是浅色文本,要么是深色文本。我改变了我的例子来展示这一点。但是,罗德必须弄清楚细节。
【解决方案2】:

您必须计算出 RGB 背景颜色的“亮度”值,然后在其上设置一个阈值来确定前景颜色是黑色还是白色(以获得最佳对比度)。 不幸的是,XSLT(和 XPath)不提供任何处理颜色的函数——并且看到你被 XSLT 1.0 所困(我假设——因为你在浏览器中使用它?)事情变得有点冗长。 ..但仍有可能...

试试这样的...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:variable name="vHexDigits" select="'0123456789abcdef'"/>

<xsl:template match="greetings">
    <html>
        <body>
            <xsl:apply-templates select="greeting"/>
        </body>
    </html>
</xsl:template>

<xsl:template match="greeting">
    <xsl:variable name="vLuminance">
        <xsl:call-template name="RGB2Luminance">
            <xsl:with-param name="pRed" select="(string-length(substring-before($vHexDigits, substring(@backcolor,1,1))) * 16) + string-length(substring-before($vHexDigits, substring(@backcolor,2,1)))"/>
            <xsl:with-param name="pGreen" select="(string-length(substring-before($vHexDigits, substring(@backcolor,3,1))) * 16) + string-length(substring-before($vHexDigits, substring(@backcolor,4,1)))"/>
            <xsl:with-param name="pBlue" select="(string-length(substring-before($vHexDigits, substring(@backcolor,5,1))) * 16) + string-length(substring-before($vHexDigits, substring(@backcolor,6,1)))"/>
        </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="vForegroundColor">
        <xsl:choose>
            <!-- assume our black/white forground threshold is 0.5 -->
            <xsl:when test="$vLuminance &gt; 0.5">
                <xsl:text>black</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>white</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <h1>
        <span style="background-color: {@backcolor}; color: {$vForegroundColor};">
            <xsl:value-of select="."/>
        </span>
    </h1>
</xsl:template>

<xsl:template name="RGB2Luminance">
    <xsl:param name="pRed"/>
    <xsl:param name="pGreen"/>
    <xsl:param name="pBlue"/>
    <xsl:variable name="vR" select="$pRed div 255"/>
    <xsl:variable name="vG" select="$pGreen div 255"/>
    <xsl:variable name="vB" select="$pBlue div 255"/>
    <xsl:variable name="vMax">
        <xsl:choose>
            <xsl:when test="$vR &gt;= $vG and $vR &gt;= $vB">
                <xsl:value-of select="$vR"/>
            </xsl:when>
            <xsl:when test="$vG &gt;= $vR and $vG &gt;= $vB">
                <xsl:value-of select="$vG"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$vB"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="vMin">
        <xsl:choose>
            <xsl:when test="$vR &lt;= $vG and $vR &lt;= $vB">
                <xsl:value-of select="$vR"/>
            </xsl:when>
            <xsl:when test="$vG &lt;= $vR and $vG &lt;= $vB">
                <xsl:value-of select="$vG"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$vB"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:value-of select="($vMax + $vMin) div 2"/>
</xsl:template>
</xsl:stylesheet>

【讨论】:

  • 这里实际计算的不是luminance,而是HSL色彩空间中的lightness。并且 luminancelightness 都不是“brightness” - 但这是一罐不值得在这里打开的蠕虫。
  • @michael.hor257k - 事实上,我很快就从 XSLT 2.0 函数中破解了代码,忘记了 HSL 中的“L”代表“轻盈”。谢谢
猜你喜欢
  • 2016-06-02
  • 2012-08-05
  • 2019-01-08
  • 2015-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
相关资源
最近更新 更多