Search code examples
ruby-on-rails-3google-mapsgmaps4rails

Is it possible to separate groups of points by colour on a gmaps4rails Google maps display?


I have a map display of addresses which are used for deliveries. Each address is on a particular delivery route, so it would be really handy to have the points displayed in different colours depending on the delivery route.

There are potentially a few hundred delivery addresses displayed but typically only a few delivery routes. Reading the documentation, this is possible by using different images but as I don't control the number of routes, I would rather be able to set a colour change of the existing default icon dynamically. So far I have the following in my controller:

@json = @company.addresses.where(:route_id => @premise.routes).to_gmaps4rails do |address, marker|
  marker.title "#{address.route.name}"
  # address route can be differentiated with address.route.id

end

The goal is for all addresses with a particular route id to be the same colour.


Solution

  • My answer is rather long winded but seems to work ok. I've taken some code from a blog post I found which can generate colours which are likely to be both different and readable.

    I assign a different letter for each market based on the first letter of the route name. A colour is then assigned which is unique and consistent for each route. Which means even if two routes have the same first letter, there's a good chance they'll have different colours.

    No doubt there is plenty of refactoring to be done!

    def index
      @premise = @company.premises.find(params[:premise]) if params[:premise]
    
      #only generate the map info if a premise has been selected
      if @premise.present?
        @json = @company.addresses.approved.where(:route_id => @premise.routes).to_gmaps4rails do |address, marker|
          marker.picture({
            :picture => "http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=#{address.route.name[0]}|#{random_colour_by_index(address.route.name)}|000000"
          })
          marker.title "#{address.route.name}"
        end
      end
    end
    
    private
    
    def random_colour_by_index(index)
      @colour ||= Hash.new
      @colour[index] ||= array_rgb_to_hex(hsv_to_rgb(rand, 0.5, 0.95))
    end
    
    def array_rgb_to_hex(rgb)
      rgb.inject("") { |hex, element| hex + single_rgb_to_hex(element) }
    end
    
    def single_rgb_to_hex(rgb)
      hex = rgb.to_s(16)
      rgb < 16 ? "0#{hex}" : hex
    end
    
    def hsv_to_rgb(h, s, v)
      h_i = (h*6).to_i
      f = h*6 - h_i
      p = v * (1 - s)
      q = v * (1 - f*s)
      t = v * (1 - (1 - f) * s)
      r, g, b = v, t, p if h_i==0
      r, g, b = q, v, p if h_i==1
      r, g, b = p, v, t if h_i==2
      r, g, b = p, q, v if h_i==3
      r, g, b = t, p, v if h_i==4
      r, g, b = v, p, q if h_i==5
      [(r*256).to_i, (g*256).to_i, (b*256).to_i]
    end