48e3dde9ec8b75f0cc1ccc00d5d3f7d2

Actually this already worked for me. I needed a list of the steps between a start and an end color.

But I'm sure there are further ruby tricks I can learn from some geniuses. Any ideas how to improve this piece of code?

def to_rgb(hex)
  md = hex.match /#?([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])/i
  return md[1].to_i(16), md[2].to_i(16), md[3].to_i(16)
end

def to_hex(rgb)
  "#" + rgb.map {|i| i.to_s(16) }.map {|h| h.size==1 ? '0'+h : h }.join
end

def color_fade(min, max, steps)
  step = (max-min).to_f / (steps-1)
  min.step(max, step).to_a.map {|f| f.to_i}
end

def color_range(from_color, to_color, steps)
  from = to_rgb(from_color)
  to = to_rgb(to_color)
  (0..2).to_a.map {|i| color_fade(from[i], to[i], steps) }.transpose.map {|rgb| to_hex(rgb) }
end

color_range('#204a87', '#729fcf', 8).each {|color| puts color}

#204a87
#2b5691
#37629b
#436ea5
#4e7ab0
#5a86ba
#6692c4

Refactorings

No refactoring yet !

D85d44a0eca045f40e5a31449277c26c

Ben Marini

November 4, 2009, November 04, 2009 21:15, permalink

1 rating. Login to rate!

I think this does what you need...

def color_range(start,finish, intervals)
  range = Range.new(start[1..-1].hex, finish[1..-1].hex)
  incr  = (range.last - range.first) / intervals
  range.step(incr) { |hex| yield "##{hex.to_s(16)}" }
end

color_range('#204a87', '#729fcf', 8) { |color| puts color }
A74c34f1043b833b1fcc86ce9f3521ee

pahanix

November 4, 2009, November 04, 2009 22:05, permalink

No rating. Login to rate!

I think, you need 9 points for 8 steps. For example from FF to FF you need 2 points [FF,FF] for 1 step

require 'generator'

require 'rubygems'
require 'activesupport'

def to_rgb(hex)
  hex.scan(/[a-f\d]{2}/).map(&:hex)
end

def to_hex(rgb)
  rgb.inject('#') {|s, i| s << "%02x" % i }
end

# chanel_(from, to, 1) # => [from, to]
def chanel_path(from, to, step)
  delta = (to-from)/step.to_f
  returning [] do |array|
    (step+1).times { |i| array << (from + i*delta).round }
  end
end

def color_range(from, to, step)
  enumerator = SyncEnumerator.new(to_rgb(from), to_rgb(to)).
  enumerator.map { |row| chanel_path(row.first, row.last, step) }.transpose.map {|rgb| to_hex(rgb) }  
end

color_range('#204a87', '#729fcf', 8).each_with_index {|color, i| puts "step #{i} - #{color}" }
color_range('#729fcf', '#204a87', 8).each_with_index {|color, i| puts "step #{i} - #{color}" }

# step 0 - #204a87
# step 1 - #2a5590
# step 2 - #355f99
# step 3 - #3f6aa2
# step 4 - #4975ab
# step 5 - #537fb4
# step 6 - #5e8abd
# step 7 - #6894c6
# 
# step 8 - #729fcf
# step 0 - #729fcf
# step 1 - #6894c6
# step 2 - #5e8abd
# step 3 - #537fb4
# step 4 - #4975ab
# step 5 - #3f6aa2
# step 6 - #355f99
# step 7 - #2a5590
# step 8 - #204a87
48e3dde9ec8b75f0cc1ccc00d5d3f7d2

blindgaenger

November 5, 2009, November 05, 2009 21:21, permalink

No rating. Login to rate!

@Ben: Och, it's so simple when you actually see it. And I wasted my time by splitting things up. … Thanks!

Your refactoring





Format Copy from initial code

or Cancel