jQuery plugin for 'responsive cropping'. Dynamically crop images to fill available space without cutting out the image's subject. Great for full-screen images.

Overview

jQuery FocusPoint

FocusPoint 2

I started work on a major update to this plugin a couple of years ago, but it has been in limbo for a while and probably won't be picked up again unless someone wants to sponsor the work (please get in touch if you do!). I didn't get as far as removing the jQuery dependancy but please feel free to use the v-2-dev branch to benefit from a few new features:

  • Better resizing performance
  • More familiar coordinate system (like that used in CSS)
  • Suppor for ideal and minimum cropping region

If you love this plugin feel free to send me an encouraging email or consider sponsoring an update. You're also welcome to make a small donation if you like. I receive an average of one per year, so it won't go unnoticed. 😄 💰

Intelligent cropping for flexible image containers

image

Websites don't have a single layout any more. The space you have for an image may be portrait on a laptop, landscape on a tablet, and square on a mobile - particularly if you're using a full-screen image.

If you have to use the same image file in all these contexts, you might not be happy with the results you get when you 'fill' the allocated space with your image. Your subject might be clipped or completely missing, or just really awkward looking.

FocusPoint makes sure your image looks great in any container, by ensuring the 'spare' parts of your image (negative space) are cropped out before the important parts.

For a quick overview of the plugin check out this video by Petr Tichy.

Examples

Here are some examples showing the same image cropped a variety of different ways at once. Make sure you play with resizing the browser window to get a feel for what FocusPoint does.

And here is a full screen demo.

How does it work?

The idea is that most images have a focal point or subject that is the most important part of the image. In the case of a traditional portrait photo this would be the subject's face (or specifically the spot right between their eyes). In the image above it's arguably the point halfway between the two people's faces.

FocusPoint requires you to indicate where this focal point is located within your image, and then works in the background to ensure that point is never cropped out.

How to use

1. Calculate your image's focus point

An image's focus point is made up of x (horizontal) and y (vertical) coordinates. The value of a coordinate can be a number with decimal points anywhere between -1 and +1, where 0 is the centre. X:-1 indicates the left edge of the image, x:1 the right edge. For the y axis, y:1 is the top edge and y:-1 is the bottom.

image

Confused? Don't worry, there's a handy script included to help you find the focus coordinates of an image with a single click. Check out the helper tool (vastly improved courtesy of @auginator).

2. Include javascript and CSS

You'll need to include jQuery (v1.9 or greater), the FocusPoint script, and FocusPoint css file. Example:

">
<link rel="stylesheet" href="focuspoint.css">
<script src="jquery.js">script>
<script src="focuspoint.js">script>

3. Mark up your image container

Specify the image dimensions and focus point coordinates on the image container. The image will take up whatever space is available in the container, so make sure there is some space to fill by setting a height for the container in your CSS. Example:

">
<div class="focuspoint"
data-focus-x="0.331"
data-focus-y="-0.224"
data-image-w="400"
data-image-h="300">
	<img src="image.jpg" alt="" />
div>

Note: setting data-image-w and data-image-h is optional but recommended. Omitting these value means your image will not be positioned correctly inside the frame until it has finished loading, which may cause a visible jump.

4. Fire FocusPoint plugin

Usually the best place for this will be inside your $(document).ready() function.

//Fire plugin
$('.focuspoint').focusPoint();

That's it!

Configuration options

FocusPoint comes with a few options you can change to suit your needs.

Option Values Default Description
reCalcOnWindowResize true or false true Whether or not to re-adjust image when the window is resized
throttleDuration Int e.g. 0 or 100 17 Throttling rate in milliseconds. Set to 0 to disable throttling.

Example usage:

$('.focuspoint').focusPoint({
	throttleDuration: 100 //re-focus images at most once every 100ms.
});

FocusPoint functions

Once you have initialised FocusPoint on an image container you can access FocusPoint methods like this: $(someContainer).data('focusPoint').methodName().

Or the shorter way, like this: $(someContainer).focusPoint('methodName')

Function Description
adjustFocus() Re-do calculations and re-position an image in it's frame. Call if container dimensions change.
windowOn() Start window event listener and re-focus image when window is resized
windowOff() Stop re-focusing image when window is resized

Using FocusPoint in content sliders

Currently FocusPoint can't do it's calculations properly if an image container or it's parent is set to display:none, as it won't have any dimensions. This can cause problems with sliders that hide non-active slides. A work-around for now is to trigger adjustFocus() on the image container as soon as it become visible.

Tips & Tricks

Image composition

In order for this concept of 'fluid cropping' to work well, your images will need to include some negative space around the subject that you are happy to be cropped out when necessary. You don't need space on every side of the subject - but for maximum flexibility you'll want to include both some vertical and horizontal negative space.

Pure CSS alternative

You can get a similar effect to this technique using only CSS and the background-position and background-size properties. Browser support isn't as good (at the moment) and your image won't be positioned exactly the same way - but it's pretty close. The CSS technique leans towards preserving the original composition while FocusPoint is biased towards keeping the subject of the image in the centre of the frame. Depending on your requirements either technique may suit you better.

SilverStripe CMS integration

This plugin plays really well with the silverstripe-focuspoint module, which lets you set the focuspoint on any image with just a click, and makes the info available in your front-end templates so you don't have to do any math. It also provides really easy 'destructive' cropping outputting resampled images cropped to a particular width and height based on the same logic.

Feedback welcome!

Nothing would encourage me to keep updating this script more than hearing how it's been used in the real world. Get in touch with me at jonathonmenz.com to let me know how you've used this plugin or any suggestions you have for improving it. Please report bugs or issues on github.

Note: To date I'm not yet aware of any live websites (apart from my own) that use this plugin - so please get in touch if you launch a site that uses FocusPoint!

Tip jar

If FocusPoint helped you impress a client and you want to say thanks, you're welcome to leave a small donation to help fund the purchase of coffee, which will help me stay awake during future development.

Donate

Donations received / Warm fuzzies generated: 6
Caffé Lattes funded: 17 😌
Thanks! Daniil, Cohan, Romulo, Lemuel, David

Changelog

v1.1.1 2014-09-23

Minor fixes

v1.1.0 2014-09-18

Refactored code (thanks @xat)
Added ability to start/stop window-resize listener (thanks @xat)
Use % instead of px for positioning, for better scaling
Added shortcuts to plugin methods

v1.0.3 2014-09-06

Throttled window resize updates

v1.0.2 2014-09-05

Made setting image width and height on shell optional (thanks @luruke)

v1.0.1 2014-09-04

Cleaned up variables

v1.0.0 2014-08-19

Initial release

Comments
  • Improvements

    Improvements

    Hi Jono,

    I refactored some stuff, maybe you wanna take a look :) I tested it on my computer within chrome and firefox. If you decide to merge please also test the code before.

    xat

    opened by xat 12
  • CSS Transforms for better performance

    CSS Transforms for better performance

    Replace

    ...
    hShift = focusOffsetX * -1;
    ...
    vShift = focusOffsetY * -1;
    ...
    image.css('left', hShift + 'px');
    image.css('top', vShift + 'px');
    

    With

    ...
    hShift = focusOffsetX * -100 / scaledImageWidth;
    ...
    vShift = focusOffsetY * -100 / scaledImageHeight;
    ...
    image.css('left', hShift + '%');
    image.css('top', vShift + '%');
    

    Or for the best performance, according to tweenlight: a combo of translate and translate3d

    image.css('transform', 'translate(' + hShift + '%, ' + vShift + '%) translate3d(0, 0, 0)');
    

    Using % intead of px will avoid to have to adjust the focus during a scaled resizing of the container such as perspective change.

    enhancement 
    opened by g-van-vreckem 7
  • Add zoom support

    Add zoom support

    Hi, fantastic project you have here. Thanks :)

    I need to zoom automatically an image on load doing zoom out from the focal point. Is there a way to do this with focal point or thru jquery ?

    Thanks, Jorge Correia

    enhancement 
    opened by jcorreia 6
  • using debounce or requestAnimationFrame for MUCH better performance

    using debounce or requestAnimationFrame for MUCH better performance

    note that calling a callback directly on the resize event is considered a bad habit if major DOM calculations are to be made. This creates havoc (layout thrashing). more about this here: https://mattandre.ws/2014/05/really-fixing-layout-thrashing/

    also, try not to write so much of var. only one single var on the top of the scope is the right way to go..

    also, this is bad: image.css('left', hShift + 'px'); image.css('top', vShift + 'px');

    better: image.css({left:hShift, top:vShift });

    best: image[0].style.cssText = 'left:' + hShift + 'px;' + 'top:' + vShift + 'px;';

    since going through jQuery to change the DOM is slower than changing it directly. and since you are doing these changes excessively on the resize event, performance considerations should take place.

    enhancement 
    opened by yairEO 6
  • Add support for focusing video

    Add support for focusing video

    see #28 9567f69 Looks simple no? However:

    • The jQuery 'or' selector overhead for 'img, video' seems wasteful.
    • It's of course intended only for video with no controls.
    • There are platform issues with transform of videos, it should stick to the no transform path.

    So it would probably best to implement that in some other way. Like using a different class (focuspoint-video) with different defaults

    opened by g-van-vreckem 5
  • allow transform

    allow transform

    This is rather rough... To avoid adding dependencies, I added a transform parameter, where the proper prefixed name for the transform (or false) must be supplied outside of the code.

    Also, the focusPoint settings where not available in the adjustFocus function, so I simply added them as parameters, I'm sure that's not a good jQuery pattern. Someone knowledgeable on jQuery plugin options and settings patterns better take a look at this.

    But it is a proof of concept that the formula is good...

    Note that the transform % are expressed in relation to the image size while the left/top % are expressed in relation to the container size.

    opened by g-van-vreckem 5
  • Fixing data attributes output in helper tool

    Fixing data attributes output in helper tool

    I noticed that the helper tool was outputting incorrect data attributes for width and height.

    • "focus-w" -> "image-w"
    • "focus-h" -> "image-h"
    opened by cavemon 4
  • use focuspoint with face detection library

    use focuspoint with face detection library

    Have you thought about using this lib along with some other face detection libraries out there?
    There is nude.js, jquery.facedetection and many others libraries and algorithms exist that can be used to detect the most important part of an image.
    I think it would be a nice experiment/feature to use focuspoint to automatically focus to an important part of an image.
    I personally had issues with "half shown faces" on certain resolutions on some of my projects, and I think that this combo might be a good solution.

    idea 
    opened by gion 4
  • Performance concerns regarding size calculation

    Performance concerns regarding size calculation

    At the moment, this extension has to generate an Image_Backend for every image render, even if the file generated exists on the filesystem.

    If you look at core code, you can see the pattern used here:

    public function Fit($width, $height)
        {
            $width = $this->castDimension($width, 'Width');
            $height = $this->castDimension($height, 'Height');
            // Item must be regenerated
            $variant = $this->variantName(__FUNCTION__, $width, $height);
            return $this->manipulateImage($variant, function (Image_Backend $backend) use ($width, $height) {
                // Check if image is already sized to the correct dimension
                $currentWidth = $backend->getWidth();
                $currentHeight = $backend->getHeight();
                if (!$currentWidth || !$currentHeight) {
                    return null;
                }
    

    However focuspoint extension calls getWidth() / getHeight() outside of a manipulateImage() wrapper.

    //Only resize if necessary
            if ($image->isSize($width, $height) && !Config::inst()->get(DBFile::class, 'force_resample')) {
                return $image;
            } elseif ($cropData = $this->calculateCrop($width, $height, $imgW, $imgH)) {
                $variant = $image->variantName(__FUNCTION__, $width, $height, $cropData['CropAxis'], $cropData['CropOffset']);
                $cropped = $image->manipulateImage($variant, function (Image_Backend $backend) use ($width, $height, $cropData) {
                    $img = null;
    

    This means that rendering a page with lots of images is very slow, and has the potential to run out of memory, even if those images have already been generated.

    Suggestion is to flip all code and ensure that we wrap all generators inside a manipulateImage()

    opened by tractorcow 3
  • Using the <picture> element and focuspoint

    Using the element and focuspoint

    'm trying to use the element for responsive images with JQuery Focuspoint. This works well on page load, and the image adjusts itself to the container. But when an additional image is loaded on resize the images focuspoint doesn't seems to change.

    Is it possible to use these 2 libraries together?

    opened by gpartington 3
  • Helper tool

    Helper tool

    Here is a first crack at a helper tool based on the pen I showed you and the grid you already have in the demo.

    Features

    • Provides jquery-focuspoint data attributes & CSS background-position in inputs for easy copy/paste.
    • Input for pasting in your own image path to use in the demo - will update aforementioned fields accordingly.
    • Added GreenSock GSAP for animation
    • * Animated transition when you click on a new focuspoint
    • * Animated Target Reticle
    • Added new Image from unsplash.com (just so we have on in there without a reticle already on it).

    Issues

    • GSAP tweens get a little clunky - I think it probably has to do with calling .adjustFocus() so many times consecutively. Perhaps we should make a special method in focuspoint optimized for animation?

    Let me know what you think!

    opened by auginator 3
  • Container without fixed height.

    Container without fixed height.

    I have 16:9 images that needs to be cropped 1:1 on an image grid. The problem is that the grid is responsive, so setting a height is not possible.

    What I do in these cases is set the image as a background and a padding-top: 100% to the container. That creates a responsive square.

    Now, if I don't set a height and just use padding-top, the container height is 0 so the plugin doesn't work. But if I change this:

    var containerH = $el.height();
    

    To this:

    var containerH = $el.outerHeight();
    

    Everything works as expected.

    Is there any other way to solve my problem? That change might break something? I'm using v1.1.3.

    Thanks, azeos.

    opened by azeos 1
  • Alternative to JQuery

    Alternative to JQuery

    This is an annoying request but I have to try. My company has an older version of JQuery (1.4.4) in the system that cannot be upgraded so your plugin doesn't work out of the box.

    I've looked at a few alternatives like zepto.js but can't find one that works.

    So I wondered if you had any suggestions other than the obvious (upgrade JQuery) which isn't possible. Maybe some plain JS that could be included or ripped from JQuery?

    Great plugin! We will be using it in future projects but would love to use it on current ones.

    opened by Goramilla 4
  • Raise funds for development

    Raise funds for development

    Donate buttons have raised less than $100 in total, I would love to work on this project more often and get v2 out the door but time poor at the moment.

    Ideas:

    Anyone have an opinion on this?

    opened by jonom 5
  • Padding messing up image positioning

    Padding messing up image positioning

    Hey,

    Just been testing this out on a new site and my image wrapper that I am calling focuspoint on has top and bottom padding. This padding seems to be interfering with Focuspoint and causing the focuspoint of the image to be much higher in the container area.

    Is there a way to fix this without removing the padding? I can't set a static height to the container though.

    Thankyou.

    opened by rctneil 3
  • Images are hidden on Bootstrap Carousel Slider

    Images are hidden on Bootstrap Carousel Slider

    I have an issue with combining the bootstrap carousel slider with Focuspoint.

    The first visible item in a bootstrap slideshow is displayed correctly. Every other image is hidden(through left: -...px).

    It works when I call Focuspoint every time the slider slides but it's inconvenient. $('.carousel').bind 'slid.bs.carousel', (e)-> $('.focuspoint').focusPoint();

    Any ideas on how to go about this?

    opened by Spoowy 1
Releases(v1.1.3)
Owner
Jono Menz
Full stack developer experienced in graphic design, UX, SilverStripe and ReactJS. Open to work enquiries.
Jono Menz
Unite Gallery - Responsive jQuery Image and Video Gallery Plugin. Aim to be the best gallery on the web on it's kind. See demo here:

##Unite Gallery - Responsive jQuery Gallery Plugin Product Link: unitegallery.net This gallery has commercial versions for: WordPress , Joomla! , Pres

Max Valiano 531 Oct 24, 2022
DEPRECATED jQuery Responsive Carousel.

YEAH SO THIS IS PRETTY MUCH DEAD, DO YOURSELF A FAVOR AND SWITCH TO tiny-slider Owl Carousel 2 Touch enabled jQuery plugin that lets you create a beau

null 7.7k Jan 4, 2023
A jQuery plugin that displays a thumbnail grid expanding preview similar to the effect seen on Google Images.

jQuery GRIDDER 1.4.2 ======= A jQuery plugin that displays a thumbnail grid expanding preview similar to the effect seen on Google Images. We have all

Orion Gunning 455 Nov 6, 2022
A jquery plugin for comparing two images

jQuery Images Compare A jquery plugin for comparing two images Badges Features compatibility : ie9+ Effort to put appearance via css (easier to skin /

Sylvain Combes 49 Sep 5, 2022
jQuery plugin that blows your visitors' retinas

Dense.js Homepage | Issues | Dense is a jQuery plugin for serving retina-ready, high pixel ratio images with ease. Small, ease-to-adapt, yet very cust

Jukka Svahn 212 Jun 30, 2022
jQuery plugin that makes an image erasable (with mouse or touch movements)

jQuery.eraser v0.5.2 a jQuery plugin that makes an image erasable (with mouse or touch movements) This plugin replaces the targeted image by an intera

boblemarin 327 Oct 27, 2022
jQuery plugin based on raphael.js that allows you to display dynamic vector maps

jQuery Mapael - Dynamic vector maps The complete documentation is available on Mapael website (repository: 'neveldo/mapael-documentation'). Additional

Vincent Brouté 1k Jan 5, 2023
⚠️ [Deprecated] No longer maintained, please use https://github.com/fengyuanchen/jquery-cropper

Cropper A simple jQuery image cropping plugin. As of v4.0.0, the core code of Cropper is replaced with Cropper.js. Demo Cropper.js - JavaScript image

Fengyuan Chen 7.8k Dec 27, 2022
Nivo Slider - The Most Awesome jQuery Image Slider

Maintainer's Wanted! - Ineterested in contributing regularly to Nivo Slider development? Get in touch Nivo Slider The Nivo Slider is world renowned as

Verti Studio 1.2k Dec 24, 2022
⚠️ [Deprecated] No longer maintained, please use https://github.com/fengyuanchen/jquery-viewer

Viewer A simple jQuery image viewing plugin. As of v1.0.0, the core code of Viewer is replaced with Viewer.js. Demo Viewer.js - JavaScript image viewe

Fengyuan Chen 1k Dec 19, 2022
Codecs lets you use read, write, edit, and analyze images.

Codecs Codecs lets you use read, write, edit, and analyze images. npm install @astropub/codecs Usage import * as fs from 'node:fs/promises' import * a

Astro Community 8 Oct 10, 2022
A light wight javascript image viewing plugin with smooth animation and 0 dependence

A light wight javascript image viewing plugin with smooth animation and 0 dependence

null 50 Nov 12, 2022
⚡️The Fullstack React Framework — built on Next.js

The Fullstack React Framework "Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails Read the Documentation “Zero-API” data layer lets y

⚡️Blitz 12.5k Jan 4, 2023
FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.

FileAPI A set of JavaScript tools for working with files. Get started Download the files from the dist directory, and then: <div> <!-- "js-fileapi-

Free and open source software developed at Mail.Ru 3.6k Jan 3, 2023
A responsive image cropping tool for React

This documentation refers to v10. Go to 9.1.1 tag for v9 docs. React Image Crop An image cropping tool for React with no dependencies. CodeSanbox Demo

null 3.3k Dec 21, 2022
Responsive navigation plugin without library dependencies and with fast touch screen support.

Responsive Nav Responsive navigation plugin without library dependencies and with fast touch screen support. Responsive Nav is a tiny JavaScript plugi

Viljami Salminen 4.1k Dec 29, 2022