Created
March 12, 2014 01:07
-
-
Save NateWr/9498581 to your computer and use it in GitHub Desktop.
Integrate Imager.js with WordPress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Integrate Imager.js with WordPress | |
* | |
* Imager.js is BBC's solution for serving responsive and retina images, without | |
* the double payload issues that affect other solutions. For more information: | |
* | |
* https://github.com/BBC-News/Imager.js/ | |
* | |
* This collection of functions modifies the output of WordPress's | |
* the_post_thumbnail() function, as well as the default gallery, to comply | |
* with Imager.js's formatting. But it is not a complete solution. You'd need | |
* to set up the proper image sizes in the $retina_image_sizes array below, | |
* integrate the Imager.js library, and initialize it on the .imager-placeholder | |
* class. | |
* | |
* This code has not been banged around much. I'm posting it up early in the | |
* hope that someone can help me figure out how to integrate Imager.js with | |
* inline images as well as the attachment pages. I have searched through the | |
* code as best I can, but inline images represent a pretty complex problem, | |
* because the output is saved directly in the editor. I don't really want to | |
* filter the_content() with a big preg_match either, because that seems pretty | |
* taxing for the server. | |
* | |
* Version: 0.0.1 | |
* Author: Nate Wright | |
* Author URI: https://github.com/NateWr | |
* License: GNU General Public License v2.0 or later | |
* License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
*/ | |
/** | |
* Your theme needs to define a set of image sizes that should be "retina'd". | |
* This array needs to be accessible from imager_rename_retina_images(). | |
* | |
$retina_image_sizes = array( | |
'sample-sml' => array( 140, 140 ), | |
'sample-med' => array( 340, 340 ), | |
'sample-lrg' => array( 600, 600 ) | |
); | |
* | |
* Then loop over each image size and register a 2x version... | |
* | |
foreach ( $retina_image_sizes as $id => $size ) { | |
add_image_size( $id, $size[0], $size[1], true ); | |
add_image_size( $id . '-2x', ( $size[0] * 2 ), ( $size[1] * 2 ), true ); | |
} | |
* | |
* ...then let the magic work. | |
*/ | |
/** | |
* Rename the 2x image size filenames so they are compatible with imager.js | |
* | |
* @h/t http://wordpress.stackexchange.com/questions/123240/rename-image-uploads-replacing-width-and-height-in-filename-with-medium | |
* @since 0.0.1 | |
*/ | |
if ( !function_exists( 'imager_rename_retina_images' ) ) { | |
function imager_rename_retina_images( $image ) { | |
// Split the $image path into directory/extension/name | |
$info = pathinfo($image); | |
$dir = $info['dirname'] . '/'; | |
$ext = '.' . $info['extension']; | |
$name = wp_basename( $image, $ext ); | |
// Get image information | |
$img = wp_get_image_editor( $image ); | |
$img_size = $img->get_size(); | |
// Pull in the array of retina images somehow | |
global $retina_image_sizes; | |
// Modify filenames for retina image sizes | |
foreach ( $retina_image_sizes as $id => $size ) { | |
if ( $img_size['width'] == ( $size[0] * 2 ) && $img_size['height'] == ( $size[1] * 2 ) ) { | |
$name = str_replace( | |
array( $img_size['width'], $img_size['height'] ), | |
array( $size[0], $size[1] ), | |
$name | |
); | |
$name .= '-2x'; | |
} | |
} | |
// Rename our new image | |
$new_name = $dir . $name . $ext; | |
$did_it = rename( $image, $new_name ); | |
if( $did_it ) { | |
return $new_name; | |
} | |
return $image; | |
} | |
} // endif; | |
add_filter( 'image_make_intermediate_size', 'imager_rename_retina_images' ); | |
/** | |
* Redefine an image's attributes to output a placeholder div compatible with | |
* imager.js responsive and retina image replacement. | |
* | |
* @since 0.0.1 | |
*/ | |
if ( !function_exists( 'imager_image_attributes' ) ) { | |
function imager_image_attributes( $attr, $attachment ) { | |
// This prevents it from firing without the full image src | |
if ( strpos( $attr['class'], 'attachment-full' ) !== false ) { | |
$attr['data-src'] = get_imager_src( $attr['src'] ); | |
$attr['data-alt'] = $attr['alt']; | |
$attr['data-class'] = $attr['class']; | |
$attr['class'] = 'imager-placeholder'; | |
// Encode a 1x1 transparence pixel for the src attribute, in order to | |
// prevent the browser making another request to the server. Note that this | |
// incures a small performance hit on mobile devices, which must decode the | |
// image. I don't know enough about CPU issues to know whether this is | |
// significant. | |
$attr['src'] = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'; | |
unset( $attr['alt'] ); | |
} | |
return $attr; | |
} | |
} // endif; | |
add_filter( 'wp_get_attachment_image_attributes', 'imager_image_attributes', 100, 2 ); | |
/** | |
* Set the post thumbnail size to "full", so that we retrieve the image path | |
* with no image dimensions. That way we can easily tack on the imager.js | |
* attributes as needed. | |
* | |
* @since 0.0.1 | |
*/ | |
if ( !function_exists( 'imager_post_thumbnail_size' ) ) { | |
function imager_post_thumbnail_size( $size ) { | |
return 'full'; | |
} | |
} // endif; | |
add_filter( 'post_thumbnail_size', 'imager_post_thumbnail_size' ); | |
/** | |
* Filter gallery shortcode so that it retrieves the filename for the full | |
* image, which we need to output a proper imager.js data-src attribute. | |
* | |
* @since 0.0.1 | |
*/ | |
if ( !function_exists( 'imager_gallery_atts' ) ) { | |
function imager_gallery_atts( $out, $pairs, $atts ) { | |
$out['size'] = 'full'; | |
return $out; | |
} | |
add_filter( 'shortcode_atts_gallery', 'imager_gallery_atts', 10, 3 ); | |
} | |
/** | |
* Generate a data-src attribute for an image placeholder with imager.js | |
* | |
* @since 0.0.1 | |
*/ | |
if ( !function_exists( 'get_imager_src' ) ) { | |
function get_imager_src( $url ) { | |
$parts = pathinfo( $url ); | |
return trailingslashit( $parts['dirname'] ) . $parts['filename'] . '-{width}{pixel_ratio}.' . $parts['extension']; | |
} | |
} // endif; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment