{"id":18368807,"url":"https://github.com/greena13/sprite_map","last_synced_at":"2025-04-10T19:38:36.226Z","repository":{"id":56896692,"uuid":"84535809","full_name":"greena13/sprite_map","owner":"greena13","description":"Rails engine for generating dynamic sprite maps","archived":false,"fork":false,"pushed_at":"2017-03-10T08:12:45.000Z","size":6,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T08:35:48.978Z","etag":null,"topics":["optimization","rails-engine","sprite-map","sprite-sheet"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/greena13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-10T08:11:08.000Z","updated_at":"2017-03-10T08:17:30.000Z","dependencies_parsed_at":"2022-08-21T01:20:34.944Z","dependency_job_id":null,"html_url":"https://github.com/greena13/sprite_map","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Fsprite_map","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Fsprite_map/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Fsprite_map/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Fsprite_map/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/greena13","download_url":"https://codeload.github.com/greena13/sprite_map/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248281426,"owners_count":21077423,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["optimization","rails-engine","sprite-map","sprite-sheet"],"created_at":"2024-11-05T23:27:30.821Z","updated_at":"2025-04-10T19:38:36.205Z","avatar_url":"https://github.com/greena13.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SpriteMap\n\nRails engine for generating and caching dynamic sprite maps from Paperclip attachments at runtime - perfect for optimising common searches or filters\n\n## Guiding Principles\n\n* Should work in terms of images, not domain concepts - you can combine images from multiple model types and styles (but **not** image formats).\n* Should give you complete freedom when selecting a rendering option - works with rails html templates, JSON decorators, etc\n* Should be as performant as possible - sprite maps are only generated when needed and cached. All work that can be pre-processed is done in advance.\n* Should be as lightweight as possible - if you already have Paperclip installed, then you don't require any additional dependencies\n\n## When should I NOT use SpriteMap?\n\n* When you want a library that works **without** Ruby on Rails or Paperclip\n* When your sprite maps can be determined at deploy time and do not depend on runtime data or behaviour. [SpriteSheet](https://github.com/jakesgordon/sprite-factory) seems to be the leading gem for this, but there are [many others](https://www.ruby-toolbox.com/search?utf8=%E2%9C%93\u0026q=sprite) available.\n* When you have not already considered optimising your production stack with technology like [HTTP/2](https://http2.github.io/faq/#why-is-http2-multiplexed ) compatible servers\n* When you test SpriteMap on your production stack and it does not result in a measurable improvement in end user experience\n* When you do not want or need the additional complexity of using sprite maps over individual images\n\n## When should I use SpriteMap?\n\n* When your sprite maps depend on runtime data, such as common search queries or filters\n* When you have already considered HTTP/2 and it is not available on your server, some of your supported clients, or you [aren't convinced HTTP/2 is as fast as a sprite map](http://blog.octo.com/en/http2-arrives-but-sprite-sets-aint-no-dead/)\n* When you see a measurable improvement in the average user experience by using SpirteMap\n \n## Current limitations\n\n* Only jpeg/jpg images are supported\n\n## Usage\n \n ```ruby\n@images = Image.where(id: search_results_ids) \n\nimage_map = @images.inject({}) do |memo, photo|\n \n   memo[photo.image_fingerprint + '-preview'] = photo.image.path(:preview)\n   memo\n   \n end\n \n @sprite_map = SpriteMap.find_or_create_by_image_map(image_map)\n```\n\n### Rails Views\n\n```ruby\n# Controller action\n\nrender @images, locals: { sprite_map: @sprite_map }\n\n# View partial\n\n\u003c% pos = sprite_map.positions[image.fingerprint + '-preview'] %\u003e\n\u003c%= image_tag 'placholder.gif', style=\"width: #{pos[:width]}px; height: #{pos[:height]}px; background: url(#{sprite_map.url}) #{pos[:x]}px #{pox[:y]}px no-repeat}\" %\u003e\n```\n\n### JSON Decorators\n\n```ruby\n# Controller action\n\n@images = ImageDecorator.decorate_collection(@images, context: { sprite_map: sprite_map })\n\nrender json: @images, status: :ok\n\n\n# Decorator\n\nclass ImageDecorator \u003c Draper::Decorator\n  def url\n    context[:sprit_map].url\n  end\n  \n  def position\n    context[:sprite_map].positions[object.fingerprint + '-preview']\n  end\nend\n```\n \n## How it works\n\nSpriteMap accepts an object or map of identifiers to filepaths. The identifiers should be unique to the image as they will be used for cache validation. It's recommended you calculate file fingerprints in advance using Paperclip and then append the style to the hash (the fingerprint is for the original file, only). Pathnames are used instead file instances, because: \n\n1. Paperclip provides easy access to the filepaths of images already uploaded\n2. We don't want to perform file reads or instantiate complex objects unless we know we have to.\n\nThe identifiers are sorted (so the order images appear in the object don't matter, nor does it necessarily correspond with th order of the position the image will occupy in the final spritemap) and a MD5 hash is calculated from them. This is used as the identifier of the sprite map. The database is checked to see if there is already an entry with that hash (indicating the sprite map has already been created) and if so, it is instantiated.\n\nIf there is not already a sprite map, one is created by retrieving the image files at the provided filepaths, reading them in and concatenating them into a single file, which is then saved in the database using Paperclip to prevent having to generate it again.\n\n## Installation\n\n### Install SpriteMap\n\nAdd this line to your application's Gemfile:\n\n    gem 'sprite_map'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install sprite_map\n    \n### Run SpriteMap's migrations\n    \nCopy the migrations to your Rails application\n\n    rake sprite_map:install:migrations\n        \nRun the migrations\n\n    rake db:migrate\n    \n### Recommended: Generate fingerprints/checksums for your Paperclip attachments\n\nIt's also recommended that you generate fingerprints for your images as these will serve as useful identifiers for invalidating generated sprite maps. Please see the Paperclip documentation for how to do this:\n\n\n#### Paperclip 5.x\n\nFollow the [Paperclip 5.x documentation](https://github.com/thoughtbot/paperclip#checksum--fingerprint) and you're done.\n\n#### Paperclip 4.x\n\nFollow the [Paperclip 4.x documentation](https://github.com/thoughtbot/paperclip/tree/v4.3.7#md5-checksum--fingerprint) and then [regenerate your images](https://github.com/thoughtbot/paperclip/wiki/Thumbnail-Generation#generatingregenerating-your-thumbnails).\n\n## Interface\n\n### SpriteMap::ImageMap class object\n\n#### find_or_create_by_image_map(image_map)\n\n`image_map` must be an object of identifiers and file pathnames or urls. \n\n* keys: It's recommended you pre-calculate a fingerprint for all your images ([see here](Recommended:-Generate-fingerprints/checksums-for-your-Paperclip-attachments)) and then append the style name as done in the [usage example](Usage).\n* values: Filepaths to your images. These can be attained using Paperclip's `path` method: `model.image.path(:style)`.\n \n This method creates a new sprite map from the files listed in `image_map` and returns an instance of `SpriteMap::ImageMap` (an ActiveRecord instance). If there is already a sprite map that corresponds with the list of images (and more specifically, their unique identifiers) then it is returned instead of recreating it. \n \n It's also recorded in the database that this sprite map has been used, to help keep track of when each sprite map was last accessed.\n  \n### SpriteMap::ImageMap instance\n\n#### positions\n\nReturns the positions object, keyed by the files' unique identifiers. Each position object has the following structure:\n\n```ruby\n{\n  x: x, #horizontal position in pixels of the top left-hand corner of the image\n  y: y, #vertical position in pixels of the top left-hand corner of the image\n  width: width, #width of image in pixels\n  height: height #height of image in pixels\n}\n\n```\n\nThis is the object you will need to work with in your view layer to correctly display the correct section of the sprite map.\n\n### url\n\nReturns the url of the sprite image for you to do whatever you want with - insert into a Rails view, document or JSON response.\n\n\n#### image\n\nThe Paperclip attachment instance for the image. Normally you do not need to interact with this directly.\n\n#### fingerprint\n\nReturns the MD5 fingerprint for the sprite map. Normally you should not need this as SpriteMap automatically generates this value and uses it for cache invalidation.\n\n## To Do\n\n* Support other image types and error handling for when images of different types are supplied\n* Rake task for removing old sprite maps\n* Test suite\n\n## Contributing\n\nAll contributions, suggestions and issue are welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreena13%2Fsprite_map","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgreena13%2Fsprite_map","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreena13%2Fsprite_map/lists"}