Mercurial > mozilla-the-big-picture
view mbp.js @ 44:9c7c3cb5f776
simplified cropping logic
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Mon, 14 Dec 2009 11:33:35 -0800 |
parents | 1909896414d8 |
children |
line wrap: on
line source
$(window).ready( function() { var containerWidth = $("#container").width(); var rectRegexp = /rect\((\d+),? (\d+),? (\d+),? (\d+)\)/; function dWidth(element) { return parseInt($(element).attr("data-width")); } // Each entry may have multiple resolutions of the same image; // choose the one that's best for our display device, and // make sure we have a cropping area for its thumbnail. $(".mbp-entry").each( function() { var pictures = $(this).find(".picture"); var lastCrop = null; var best = null; pictures.each( function() { var crop = $(this).attr("data-crop"); if (crop) lastCrop = this; if (best) { // The "best" image is the lowest-resolution image // that's still bigger than the width of our container: // this way we never upscale, but we also don't waste // bandwidth getting a massive image that we won't // see. if (dWidth(this) < dWidth(best) && dWidth(this) >= containerWidth) { best = this; } } else best = this; }); var cropAttr = $(best).attr("data-crop"); var scaling = 1; // If our best picture doesn't have a cropping rect associated // with it, we'll use the scaled cropping rect of another // resolution. if (!cropAttr && lastCrop) { cropAttr = $(lastCrop).attr("data-crop"); scaling = dWidth(best) / dWidth(lastCrop); } if (!cropAttr) throw new Error("No 'data-crop' for " + best.href); var parts = cropAttr.match(rectRegexp); if (!parts) throw new Error("Invalid 'data-crop' for " + best.href); var crop = {top: Math.floor(parts[1] * scaling), right: Math.floor(parts[2] * scaling), bottom: Math.floor(parts[3] * scaling), left: Math.floor(parts[4] * scaling)}; var image = $("<img/>"); image.attr("src", best.href); image.attr("width", $(best).attr("data-width")); image.attr("height", $(best).attr("data-height")); image.data("crop-parts", crop); $(this).find(".link").empty().append(image); pictures.remove(); }); var images = $(".mbp-entry img"); var loadsLeft = images.length; // Create the thumbnails and attach event handlers to them. images.each( function() { function onLoaded() { $("#countdown").text(--loadsLeft); var crop = $(this).data("crop-parts"); crop.width = crop.right - crop.left; crop.height = crop.bottom - crop.top; var canvas = document.createElement("canvas"); var self = $(this.parentNode).clone(); var maxWidth = Math.max($(document.body).width(), containerWidth); self.find("img").removeAttr("width") .removeAttr("height") .css({maxWidth: maxWidth}); $(canvas).mouseenter( function() { $("#big-picture").empty(); $("#big-picture").append(self); }); $(canvas).addClass("thumbnail"); $(this).before(canvas); var ctx = canvas.getContext("2d"); ctx.drawImage(this, crop.left, crop.top, crop.width, crop.height, 0, 0, canvas.width, canvas.height); $(this).remove(); if (loadsLeft == 0) { $("#countdown").remove(); $("#container").fadeIn(); } } if (this.complete) onLoaded.call(this); else this.addEventListener("load", onLoaded, false); }); $("h1").mouseover( function() { $("#big-picture").empty(); }); $("#countdown").text(loadsLeft); });