【发布时间】:2011-02-12 11:23:52
【问题描述】:
在 SASS 中我可以做到:
!pink = #ff43a7
!darker_pink = !pink - #333333
我想在 Ruby 中也一样。
【问题讨论】:
-
我对这个的应用感到困惑; SASS 是用 Ruby 构建的。你是说在 ERb 中这样做吗?
在 SASS 中我可以做到:
!pink = #ff43a7
!darker_pink = !pink - #333333
我想在 Ruby 中也一样。
【问题讨论】:
可以在 Ruby 中通过在值前面加上 0x 来表示十六进制:
pink = 0xff43a7
darker_pink = pink - 0x333333
def color(hex)
"#%06x" % hex
end
.container {
color: <%= color pink %>;
border: 1px solid <%= color darker_pink %>;
}
.container {
color: #ff43a7;
border: 1px solid #cc1074;
}
【讨论】:
#%06x 而不仅仅是#%x。否则,以零开头的颜色将被错误地格式化。例如,0x000fff 的值将导致 #fff(即 CSS 中的白色)。
0x010000 - 0x000001 的结果可能不是预期的结果,即“从该颜色中去除了一点蓝色”。
如果您已经拥有 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(/../).map 和slice.join('').to_i(16).to_s(10) 可以变成slice.hex.to_s(10)。
在 Sass 中添加/减去颜色的基本方法是无稽之谈,只有在使用灰度调整时才真正有效。这就是为什么在 Sass 3 中,我们现在全面支持 HSL 域中的操作,这与人们对颜色的看法密切相关。
由于 Sass 是用 Ruby 编写的,您至少可以阅读我们的代码以了解发生了什么。
这是Color class 和functions that operate on them。
这确实是不平凡的代码。为什么不直接使用 Sass?
【讨论】:
按照@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')
我刚刚遇到了一些事情,我想为一组不同的色调分配颜色。 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
【讨论】: