class Gradient::Map

Attributes

locations[R]
points[R]

Public Class Methods

deserialize(points=[]) click to toggle source
# File lib/gradient/map.rb, line 7
def deserialize(points=[])
  new(points.map { |point| Gradient::Point.deserialize(*point) })
end
new(*points) click to toggle source
# File lib/gradient/map.rb, line 12
def initialize(*points)
  # Sort points using a stable sort algorithm
  @points = points.flatten.sort_by.with_index { |x, idx| [x, idx] }
  @locations = @points.map { |point| point.location }
end

Public Instance Methods

as_json(json={}) click to toggle source
# File lib/gradient/map.rb, line 51
def as_json(json={})
  serialize
end
at(location, opts = {}) click to toggle source
# File lib/gradient/map.rb, line 32
def at(location, opts = {})
  if range.include? location then
    if 0 == (i = points.find_index { |p| p.location >= location }) then
      points[0].dup
    else
      interpolate_points(points[i-1], points[i], location)
    end
  end
end
inspect() click to toggle source
# File lib/gradient/map.rb, line 18
def inspect
  "#<Gradient Map #{points.map(&:inspect).join(" ")}>"
end
range() click to toggle source
# File lib/gradient/map.rb, line 22
def range
  @range ||=
    begin
      ends = [:first, :last]
        .map { |method| points.send(method) }
        .map(&:location)
      Range.new(*ends)
    end
end
serialize() click to toggle source
# File lib/gradient/map.rb, line 47
def serialize
  @points.map(&:serialize)
end
to_css(**args) click to toggle source
# File lib/gradient/map.rb, line 42
def to_css(**args)
  @css_printer ||= Gradient::CSSPrinter.new(self)
  @css_printer.css(**args)
end

Private Instance Methods

interpolate_floats(x0, x1, weight) click to toggle source
# File lib/gradient/map.rb, line 79
def interpolate_floats(x0, x1, weight)
  x0 * (1.0 - weight) + x1 * weight
end
interpolate_points(point_left, point_right, location) click to toggle source
# File lib/gradient/map.rb, line 57
def interpolate_points(point_left, point_right, location)
  points = [point_left, point_right]
  color_left, color_right = points.map(&:color)
  location_left, location_right = points.map(&:location)
  separation = location_right - location_left
  if separation == 0.0 then
    point_right.dup
  else
    weight = (location - location_left)/separation
    r, g, b = [:r, :g, :b].map do |channel|
      interpolate_floats(color_left.send(channel),
                         color_right.send(channel),
                         weight)
    end
    color = Color::RGB.from_fraction(r, g, b)
    opacity = interpolate_floats(point_left.opacity,
                                 point_right.opacity,
                                 weight)
    Point.new(location, color, opacity)
  end
end