【问题标题】:How do I do math with colors like SASS but in Ruby?我如何使用 SASS 等颜色但在 Ruby 中进行数学运算?
【发布时间】:2011-02-12 11:23:52
【问题描述】:

在 SASS 中我可以做到:

!pink = #ff43a7
!darker_pink = !pink - #333333

我想在 Ruby 中也一样。

【问题讨论】:

  • 我对这个的应用感到困惑; SASS 是用 Ruby 构建的。你是说在 ERb 中这样做吗?

标签: ruby colors hex sass


【解决方案1】:

可以在 Ruby 中通过在值前面加上 0x 来表示十六进制:

pink = 0xff43a7
darker_pink = pink - 0x333333

颜色助手

def color(hex)
  "#%06x" % hex
end

在 ERb 模板中的使用

.container {
  color: <%= color pink %>;
  border: 1px solid <%= color darker_pink %>;
}

输出

.container {
  color: #ff43a7;
  border: 1px solid #cc1074;
}

【讨论】:

  • 您必须在 0 和 255 处为引脚通道值添加边界检查。
  • 您应该使用#%06x 而不仅仅是#%x。否则,以零开头的颜色将被错误地格式化。例如,0x000fff 的值将导致 #fff(即 CSS 中的白色)。
  • 我同意@drawnonward;如果没有通道限制,0x010000 - 0x000001 的结果可能不是预期的结果,即“从该颜色中去除了一点蓝色”。
【解决方案2】:

使用 Sass 模块

如果您已经拥有 Sass 库,则可以实例化并使用它的对象。

例如:

red  = Sass::Script::Color.new([255, 0, 0])
gray = Sass::Script::Color.new([128, 128, 128])
red.lightness < gray.lightness # => true

一定有内置方法可以将#00FF00之类的十六进制字符串转成Color对象,但是没有看到,我写了这个函数:

# @param color_string - hex string, like '#22FF22'. MUST be 6 characters,
# because I don't feel like dealing with the use-case for 3. :)
def color_from_hex_string(color_string)
  # Drop the leading '#', if any
  color_string = color_string[1..-1] if color_string.start_with?('#')
  raise ArgumentError.new('Hex string must be 6 characters') unless color_string.length == 6

  # Turn into array of 2-digit decimal numbers. 
  # Eg, '808080' becomes [128, 128, 128]; '#ff0000' becomes [255, 0, 0]
  rgb_array = color_string.split('').each_slice(2).map do |slice|
    slice.join('').to_i(16).to_s(10)
  end

  # Use that to build a new Color object
  color = Sass::Script::Color.new(rgb_array)

  # Set this option so it won't complain (?)
  color.options = {:style => :compressed}

  return color
end

【讨论】:

  • color_string = color_string[1..-1] if color_string.start_with?('#') 可以变成color_string.sub!(/^(?:#|0?x)/, '')
  • rgb_array = color_string.split('').each_slice(2).map 可以变成color_string.scan(/../).mapslice.join('').to_i(16).to_s(10) 可以变成slice.hex.to_s(10)
【解决方案3】:

在 Sass 中添加/减去颜色的基本方法是无稽之谈,只有在使用灰度调整时才真正有效。这就是为什么在 Sass 3 中,我们现在全面支持 HSL 域中的操作,这与人们对颜色的看法密切相关。

由于 Sass 是用 Ruby 编写的,您至少可以阅读我们的代码以了解发生了什么。

这是Color classfunctions that operate on them

这确实是不平凡的代码。为什么不直接使用 Sass?

【讨论】:

    【解决方案4】:

    按照@drawnownward 和@lpsquiggle 的意愿完善@macek 的答案:

    你可以创建两个助手,像这样:

      def color(color)
        "#%06x" % color
      end
    
      def darker_color(color)
        x = color.match(/0x(..)(..)(..)/)
        r = x[1].sub(/[0-3]/, '5')
        g = x[2].sub(/[0-3]/, '5')
        b = x[3].sub(/[0-3]/, '5')
        rgb = "0x#{r}#{g}#{b}"
        "#%06x" % (rgb.hex - 0x444444)
      end
    

    优点:如果您定义了一个低值的颜色十六进制(此处为 0 到 3 之间),这些值将在减法之前被提升,因此它们在之后最终为 0,而不是环绕并变成c、d、e 或 f(这会给你一种你没想到的颜色)。它只对每个#rrggbb 对中的第一个值执行此操作,因此#313131 变为#0d0d0d,这在技术上并不正确,但它比#fdfdfd 好得多,所以这似乎是一个足够好的折衷方案,因为你会想要在其他情况下保留第二个值。

    那么,在你的 Erb 模板中,你会这样写:

    .container {
      color: <%= color pink %>;
      border: 1px solid <%= darker_color pink %>;
    }
    

    代替:

    .container {
      color: <%= color pink %>;
      border: 1px solid <%= color darker_pink %>;
    }
    

    希望对某人有所帮助。

    【讨论】:

    • 貌似darker_color方法的前五行可以换成rgb = color[/^0x(.{6})/, 1].tr('0-3', '5')
    【解决方案5】:

    我刚刚遇到了一些事情,我想为一组不同的色调分配颜色。 SASS 源没有太大帮助,因为我没有看到从 HSV 获取 RGB 的方法。

    color gem 有我需要的东西。

    我写了这个助手:

    def region_color(index, size)
      h = (index.to_f / (size - 1).to_f)
      Color::HSL.from_fraction(h, 0.95, 0.3).html
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 2015-03-21
      • 1970-01-01
      • 2014-03-29
      相关资源
      最近更新 更多