I recently built a Google Plus inspired image Gallery as an extension for the Alfresco ECM product which won first place in Alfresco developer challenge. Now I’d like to share my insights, explain how I built it and give you a starting point to build your own galleries based on the great G+ gallery design.
The G+ image grid disected
The main focus of this article will be on the image grid. Let’s start with a look on the features of the original G+ image grid to find out what it takes to recreate it. To illustrate the features I am using Thomas Hawk’s G+ gallery which has some amazing images (check it out).
- Justifed alignment: All images are displayed in rows and aligned to left and right borders.
- Even spacing: All Images are evenly spaced (6px spacing, i.e. 3px margin around each image).
- Natural order: Images don’t have a special ordering to better fit in the grid. I first thought the perfect alignment was solved with some sort of bin packing algorithm, but that is not the case und is not needed. Images are usually sorted by date from latest to oldest.
- Cropped thumbnails: To achieve the justified layout some portions of the images are hidden (cropped). When I first checked out the G+ gallery I saw most of the cropping done with HTML but now it looks like Google generates thumbnails in any arbitrary resolution or cropping on the server-side.
Both images have a similar URL which only differs in a part which specifies the resolution. The left image contains the path /w300-h150-n-k/ whereas the right image contains the path /w150-h150-n-k/ and therefore is cropped differently on the server side. - Big title image: There is a “title” image or (album cover image) which spans two rows.
- Comment badges: The number of comments is displayed on each image thumbnail.
- Dynamic resolution: The size of the images depends on the width of the browser window. G+ uses small images for smaller browser windows and larger images for wider browser windows, i.e. the image resolution adapts to the screen size. This is espacially useful for mobile devices which have lower resultion than desktop browsers.
- Window resize: The image sizes change and the grid images are re-aligned dynamically when the browser window is resized.
- Dynamic row height: This is a really subtle feature: Depending on the dimensions of the images in one row (e.g. if a lot of images in portrait format) some rows are rendered bigger in height than others. This helps portrait shots not to become too small.
- Popup Preview: When you hover over an image an animated popup appears and displays the image in a larger rendition.
- Infinite scroll: When you scroll to the bottom of the page more images are loaded automatically.
As far I have seen G+ servers generate different sizes of thumbnails that are used for the window specific thumbnail size, dynamic row height and the preview popup. At times your browser will load 10-20 differently sized thumbnails of an image.
I bet the feature list above is not even complete but it shows the design and engineering effort that went into this seemingly simple gallery grid.
What if you don’t have Google’s infrastructure and manpower?
For my one man competition contribution I couldn’t possibly implement all those features. I axed the double-row-spanning title image, different thumbnail sizes and the preview popup:
- Only one thumbnail size (120 pixel height, width depending on image aspect ratio)
- No server side cropping, only a single static thumbnail for each image.
Still I came pretty close to the original with all the other features.
How does the cropping in the Browser work?
To better understand how the G+ image grid worked I studied the HTML source, which basically looks like this:
The main insight I took from this is they way the images can be cropped: using a DIV with overflow:hidden and changing margin-left of the image to define the x-offset.
How to align the images?
Once I started experimenting I realized that the image alignment is not that hard to do. Let’s say we have three images and are using a fixed thumbnail height of 120 pixel.
image 1: 200x120 image 2: 180x120 image 3: 120x120
Let’s also assume we want to fit these images in a row with a given width of 460 pixels.
I started to build rows of images by adding image by image until the window width is met or surpassed.
1 image: 200 OK (<460) 2 images: 200 + 180 = 380 OK (<460) 3 images: 380 + 120 = 500 surpassed (break >460, 40 pixels too long)
So putting all three images in a row would make it 40 pixel too long. The only thing that needs to be done now is to crop all the images by overall 40 pixels to perfectly align them with the window width.
My naive approach was to simply devide the excess pixels, so 40 pixel / 3 images = 13 pixels/image You have to be careful with the integer division though. To perfectly distribute the 40 pixels you need to crop one additional pixel from one of the images:
cropped image 1: 200 - 14 = 186x120 cropped image 2: 180 - 13 = 167x120 cropped image 3: 120 - 13 = 107x120
If you sum up the witdh now you get exactly 460 pixel. Combining these values with the cropping method from the previous section we get the following HTML code for the three images.
<div style="overflow:hidden; width:186px; height:120px;"> <img src="image1.jpg" style="width:200px; height:120px"; margin-left:-7px"/> </div> <div style="overflow:hidden; width:167px; height:120px;"> <img src="image2.jpg" style="width:180px; height:120px"; margin-left:-6px"/> </div> <div style="overflow:hidden; width:107px; height:120px;"> <img src="image3.jpg" style="width:120px; height:120px"; margin-left:-6px"/> </div>
As you can see the negative margin-left is used to center the cropped area horizontally. On thing I left out here is the spacing between images. We have 6 pixels of spacing between each image that have to be added in the inital sum.
This naive approch worked pretty well even with only a single thumbnail size (120 pixels height). In a later iteration I changed the distribution of the crop-pixels though, because when equally distributing the excess pixels, portrait images tend to get too small in width. That’s why I based the crop amount on the image width, with the result that wider images are cropped more than narrow ones.
The server side
As you see above the image layout algorithm needs the widths of the individual images to do it’s mojo. In my Alfresco extension I leveraged the metadata extraction capabilties to get to the thumbnail resolution. The resulting JSON data that is finally generated on the server side is a simple array with all the image data (here is a single image as an example):
{ "thumbs" : [ { "thumbUrl" : "api/node/workspace/SpacesStore/c2f5e06f-ee15-4b0f-9e6c-1f734b4db45f/content/thumbnails/galpThumb120", "title" : "2010-05-02, 2 images, IMG_2173 - IMG_2174 - 5096x2320 - SCUL-Smartblend.jpg", "twidth" : 300, "theight" : 120, "description" : "", "author" : "Administrator", "nodeRef" : "workspace://SpacesStore/c2f5e06f-ee15-4b0f-9e6c-1f734b4db45f", "name" : "2010-05-02, 2 images, IMG_2173 - IMG_2174 - 5096x2320 - SCUL-Smartblend.jpg" } ]}
The most important information here are the thumbnail dimensions and the thumbUrl that are used for the gallery grid. If you are interested in the details of the server side code in my Gallery+ extension you can have a look in the webscript.
Standalone JQuery demo version
To demonstrate the grid rendering independently of the full the Alfresco extension I moved the grid generation code to a standalone website with the Javascript logic based on jQuery (the original extension is based on YUI). You can see the example in action at the following URL: http://fmaul.de/gallery-grid-example/
If you try it out, make sure to resize your browser to see the dynamic resizing in action. This is not a full jQuery gallery component, sorry – it is just meant to demonstrate the rendering but you are welcome to further extend the code to a full blown jQuery gallery.
Note that the example gallery is not backed by a REST or thumbnail server, it uses this static JSON file as image source for the purpose of demonstration. The page is built using html5 boilerplate and therefore my complete implementation can be found in the scripts.js file.
Thank you for taking the time to figure this out and posting. Seems like you’re the only one so far that’s been able to crack how Google did their’s and is willing to share the secret.
Did you make it into a plugin for wordpress?
Looks like a great start, the only info I was able to find about Google Plus gallery so far. Thanks for sharing your work!
Excellent work.. Will try to implement the same in my website..
What is the logic on wrapping to next line? I see that you split the excess into the pictures on that line. Is it just that once you have hit the page width and/or exceeded, it’ll wrap?
Hi Johnie, yes I let the browser wrap the images automatically. They are basically all in one long row but the image widths are calculated in such a way that the images wrap at a specific point.
I love the script but there’s a small change I would make: When resizing the browser the images flicker because their width is constantly being recalculated.
I think it’s better to (like G+) only recalculate the images when resizing is complete. So I replaced the window resize event handler:
var resizeTO = false,
$imgarea = $(‘#imagearea’);
$(window).resize(function(){
$imgarea.width($imgarea.width());
if(resizeTO !== false)
clearTimeout(resizeTO);
resizeTO = setTimeout(function() {
$(‘#imagearea’).css(‘width’, ”)
// layout the images with new width
GPlusGallery.showImages($imgarea, items);
}, 200); //200 is time in miliseconds
});
Maybe you could put the code on github?
Hi there, great gallery, I really like it!
Is it okay for you if I take your code and create a WordPress plugin out of it?
Greetings
Pingback: Flickr ‘Justified’ Layout in JQuery | Wackylabs.net
Good job. So I understand there really aren’t any other alternatives? I’ve copied pretty much everything over so I can test it: http://www.mirelmasic.nl/troep/gallery, but the images.json file is beyond my understanding (which isn’t big btw).
I don’t understand how the thumburl links to a folder and not a jpg, same for noderef. I don’t even know what noderef means.
How did you create the json file? Did you create the thumbnails manually? And why the popup when clicking on an image?
cheers, Mirel
Hi Mirel, I generated the JSON file with an Alfresco Server which was the original platform I developed this on. Don’t be confused by the URLs of the thumbnails. Originally it is a server side script which provided the images but it could simply be image files in a directory. You only need to have a relative URL in the JSON file pointing to the thumbnail image.
Hello,
Back in October 2011, I also wrote a Google+ like photo gallery using jQuery. I called it jGlance and can be found here : http://moewashere.com/jglance/ . It included a demo, docs, and instructions. It also features the hover states.
I found it interesting that another fellow developer did the same thing. Good work!
I forgot to mention that jGlance is on github, https://github.com/moeishaa/jglance , and anybody is welcome to check it out.
Thanks
Pingback: Google Plus Image Gallery | Moe Was Here
Thanks for this article! You said Google crops images and when I look at your demo gallery I see that you also crop all images.
I analyzed Google’s gallery layout too and I think Google crops just a small number of images: The big title image and images that are extremely wide or extremely high. All other images are in their original ratio. Maybe you want to improve your work
Google image resizer is free to use if you have your photos on Google+! You can access your photos like this: https://www.googleapis.com/plus/v1/activities/z12ixpgiewebzln5m04chfsyalasjjnwulo0k?alt=json&fields=object(attachments(fullImage(height%2Curl%2Cwidth)))&key=AIzaSyAHKz9oRYV7zZr-Qd9g2IgJeOHiKmoAjJM
(not sure if this will work with your IP and my API key, but if you register your key, you’ll get it) and request to photo like this:
https://lh4.googleusercontent.com/-6vJ4jekctNw/T75andEs9MI/AAAAAAAAAMs/KrDtPpEaKAg/w561-h372-n-k/DSC_4810.jpg
/w561-h372-n-k does all the speedy magic!
Awesome! If it’s ok with you, will try to implement it in a website.
Thanks for sharing all your effort.
Oh, i’m searching this style. Thank you very much!
Could you please show how we could add a larger image at the start of the stack, maybe covering the height of 2 lines of thumbnails
ive tried, but spacing seems to break
Awesome explanation.. !!
I am using the jQuery plugin by Pedro Botelho, however I would like to add the 2 row initial image capability. If anyone has some suggestions how that can be done, I would love to get the code.
Todd
I wrote my own Google+ like photo viewer. You can check it here.
http://www.otdelkalux.ru/portfolio/green_hill_14/
Source:
static.otdelkalux.ru/gplus/jquery.gplus.js
static.otdelkalux.ru/gplus/gplus.css
It uses Google’s Picasa photohosting, that does all the heavy resizing job for free. (it has limits though, but is good enough for small projects)
That is what I was looking for – thank you!
Hi there
On the Piwigo gallery there is a similar script called Gthumb+ http://fr.piwigo.org/ext/extension_view.php?eid=591
And if a dev wants js sources : http://piwigo.org/dev/browser/extensions/GThumb/js
released under Gnu licence
Great piece of code!
I had one concern. When adding more items it seems to break the alignment on the right side.
Can duplicate/test by just calling you images.json .getJSON twice.
Pingback: Crafting The Perfect Photo and Video Viewing Experience | Trovebox | Photo Management for Organizations
Is it possible to get a YouTube style theme and dashlets etc… for Alfresco?
Hi I was wondering if you could help. We’ve used this dashlet very successfully within our organisation however we are hoping to migrate to Alfresco v5 but we are receiving the following error
09200021 Wrapped Exception (with status template): 09201595 Failed to execute script ‘classpath*:alfresco/templates/webscripts/de/fme/dashlets/gallery.get.js’: 09201594 A transaction has not be started for method ‘isSiteAdmin’ on org.alfresco.service.cmr.site.SiteService
Can you help us fix this? I
Failure to start up and run means the spark has a problem.
When storing the chainsaw, keep it out of the reach of children, and make sure that the blade
is away from anything that could get caught on it.
A 30cc lightweight chainsaw with a 14 inch bar may still be
unable to cut through a 28-inch trunk.
There are not any clear signs of vitamin or mineral deficiency
within the body, just make sure believe what you eat is not made up of
each of the healthy food choices that reazlly must be consumed everyday,
you need to immediately ask your doctor’s opinion. They come in a superb price – with penty of excellent
comnpanies providing yoou having a great level off creative goods.
Some retailers don’t list the recommended dosage but this really
is something worth knowing when confronted with Kratom. Thee most typical causes wiith this
excess loss in potassium are:.
We’re a group of volunteers and starting a brand new scheme inn our
community. Your site provided us with valuable info too work on.
You have performed an impressive job annd our entire neighborhood might be
thankful too you.
Also visit myy web site – url
The entire effect of these rugs to a room should be considered when purchasing
one. Most of the time, when the topic is all about wastewater and sewage,
the image people often get is that of bad smells and all that
grime. Many of the Earthships have propane tanks for
cooking and a backup hot water supply; these are the only utility bills.
When getting rid of drain clogs, avoid using chemical cleaners.
In other words, structures would be designed or modified to collect the natural rainfall that
falls onto the property, purify it and then store it in cisterns until the water
is needed by the occupants of the building. Today there are various insulation materials that are used directly over the
exterior of the tire before the finish is applied.
About The – Author: Harris – Noah is an expert author
on pet products related topics and currently workingfor.
In other words, structures would be designed
or modified to collect the natural rainfall that falls onto the property, purify it and then store it in cisterns until
the water is needed by the occupants of the building. Today there are various insulation materials that are
used directly over the exterior of the tire
before the finish is applied.
About The – Author: Harris – Noah is an expert
author on pet products related topics and currently workingfor.
Their payloads are spread out over the entire dump
body in order to maintain the weight requirements
of the federal bridge laws. The most popular types and styles of
these include the following:.
Hello, for all time i used to check weblog posts here in the early hours in the morning, as i like to gain knowledge of more and more.
You will be blown away to know that over 90% among all fit personalities have their own personal trainers to keep all of them on track.
Maintain your general health by subscribing to San Antonio Fitness
Examiner and follow Dane on Twitter. Therefore, it is advisable to acquire assistance
of the personal trainer Vancouver services.
Many consumers are also under the impression that supplements are inherently ‘natural’ and
safe, but the lack of regulation surrounding the testing, manufacturing, and labeling of supplements can lead to
potentially harmful products. Sometimes eating of bad calories
result in making the dieter overweight which is really a matter
of concern because it directly targets the working efficiency of
its user. As after the tiring workouts session the body of bodybuilder is malnourished then the requirements of post workout supplements increases.
For newest news you have to pay a quick visit the web and on world-wide-web I found this web page as a finest web page for
newest updates.
Also, you should start with a low dosage and work your way up.
In fact the height of a teenager increases dramatically.
Research strongly suggests that people with high levels of Omega-3 fatty acids in their blood experience positive brain qualities such as fewer signs of blood flow obstructions and fewer episodes
of Dementia.
Brain O Brain capsules tackle stress and produce high level of energy, the herbs used in the preparation of these capsules contain iron in high amount which enhances the capacity oxygen carrying of the blood by increasing the number of red blood cells.
In fact the height of a teenager increases dramatically.
Do a simple search on Google or Amazon for a keyword like
“dog supplements” and instantly you will get hundreds of thousands of
results.
This is especially useful if the person you’re inquiring about
has a less than common name. That means you literally can make money 24 hours a day.
The website templates are well-equipped with HTML coding which could
result into better looking websites in minor budget also.
A newsletter is an effective element for any dog training website.
You certainly get the best web design output which brings considerable returns to your business.
they may be prepared to click a few Google Ads on your website.
Most of the card dealers sell their cards online through websites that specialize in international calling
cards. Not only do you want lots of people to visit your
website but you also want your visitors to stay on your site
and see if the deal is worthwhile by simply checking out your site.
However, there are certain things which can assist you
differentiate which one is best and which is not.
The website will also serve as a portal for all things convention related,
from a countdown clock to information on logistics, credentials, media walkthroughs
and housing. If these eight steps seem overwhelming, welcome to the club.
I discovered the way to make money on the internet.
Make money on autopilot is available for all of us.
The combination of your logo and tagline should appear on every page to create
a sense of cohesion. Incompatibility: Rails’ structured
and organized approach can be its strength as well as weakness in terms
of flexibility and compatibility.
Make money on autopilot is available for all of us. Small
claims court cases are much cheaper than superior court cases for both the plaintiff (the person doing the suing) and the defendant (the person being sued) because the parties
are not allowed to have any attorneys represent them and other rules that simplify the lawsuit process, making the
whole thing much cheaper, faster, and easier. Incompatibility: Rails’ structured and organized approach
can be its strength as well as weakness in terms of flexibility and compatibility.
Falcon and Armonie are the two setters that I recommend to Aussie friends to start with English crosswords – they are generally straightforward, have elegant and precise clues and rarely require much local knowledge.
If you search online, used Bicycles For Sale offers significant savings.
Best way for you to find out if I lie is to try it for yourself.
Here we will discuss some more on virtual bicycle exercising.
GPU XFX Double D HD-695X-CDFC Radeon HD 6950 2GB –
$200. There’s also a new decoy grenade that emits gun sounds to distract
or confuse enemies by giving the illusion of there being
another player near. The default setting is for all strikes to
be considered weak strikes, fast strikes that are difficult
to counter, but attacks that don’t pack a lot
of power.