Automatically change images in a responsive design to scale
A lot of new sites uses responsive design. The key feature with this of course that the web page scale to the current view port of the device a user is using. Images and other elements are often set to width:100% in the css. The problem that we then have to solve is to return to the user a images that is in the correct size in pixels.
I have wrote a concept around this based on the current alloy template site.
First of all I want to change all images that are returned from a request. I wrote my self a module ChangeImageSource that I can add in the master page like this.
<div id="MainBodyArea">
<Itera:ChangeImageSource runat="server" ID="ChangeImageArea">
<asp:ContentPlaceHolder ID="MainBodyRegion" runat="server">
<div id="MainBody">
<AlloyTech:MainBody runat="server" />
</div>
</asp:ContentPlaceHolder>
</Itera:ChangeImageSource>
</div>
<div id="SecondaryBodyArea">
<Itera:ChangeImageSource runat="server" ID="ChangeImageSource1" AddBox="border">
<asp:ContentPlaceHolder ID="SecondaryBodyRegion" runat="server">
<div id="SecondaryBody">
<EPiServer:Property PropertyName="SecondaryBody" EnableViewState="false" runat="server" />
</div>
</asp:ContentPlaceHolder>
</Itera:ChangeImageSource>
</div>
</asp:ContentPlaceHolder>
This module replace every images inside its content with a reference to a empty images, and add the original image in a new attribute called orgsrc.
<img orgsrc="/PageFiles/5/Desert.jpg" alt=""
src="/Itera.ResponsiveResize/ZeroSize.png" class="scaleImage">
The code that replace all images in a given tag is done like this using HtmlAgilityPack
{
if (this.Page.Request["dontChangeImages"] == null)
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter htw = new HtmlTextWriter(sw);
base.Render(htw);
string content = sb.ToString();
//writer.Write("content length=" + content.Length);
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(content);
var images = doc.DocumentNode.SelectNodes("//img[@src]");
if (images != null)
{
foreach (HtmlNode image in images)
{
HtmlAttribute src = image.Attributes["src"];
image.Attributes.Add("orgsrc", src.Value);
src.Value = "/Itera.ResponsiveResize/ZeroSize.png";
if (image.Attributes["width"] != null)
{
image.Attributes.Remove("width");
}
if (image.Attributes["height"] != null)
{
image.Attributes.Remove("height");
}
if (image.Attributes["class"] == null)
{
image.Attributes.Add("class", AddClass);
}
else
{
image.Attributes["class"].Value = image.Attributes["class"].Value + " scaleImage";
}
if (!string.IsNullOrEmpty(AddBox))
{
var newNode = HtmlNode.CreateNode("<div class='" + AddBox + "'>" + image.OuterHtml+ "</div>");
image.ParentNode.ReplaceChild(newNode, image);
}
}
}
writer.Write("<div id='" + UnikID + "'>");
writer.Write(doc.DocumentNode.OuterHtml);
writer.Write("</div>");
writer.Write("<div id='Log" + UnikID + "'></div>");
}
else
{
base.Render(writer);
}
}
Then the module add some JavaScript that after the page is loaded find all images in the current zone and uses JQuery to find the current width in pixels and change the image source to a reference to a scaled images with the correct width. And if the pages is resized it will change the images. To save some cpu, it will use a images that is round up to the next hundred. The actually resizing of the pictures can be done with a lot of different te4chinces , but this demo uses ImageResizer
$(document).ready(function () {
$('#133d8cb8fb224834bbfdde298adbec25 img').each(function (i) {
if (!$(this).attr('orgsrc')) {
var img = $(this).attr('src');
$(this).attr('orgsrc', img);
}
ResizeImageWith100Procent133d8cb8fb224834bbfdde298adbec25($(this));
});
});
$(window).resize(function () {
$('#log133d8cb8fb224834bbfdde298adbec25').append('<div>resize finished</div>');
$('#133d8cb8fb224834bbfdde298adbec25 img').each(function (i) {
if ($(this).attr('orgsrc')) {
ResizeImageWith100Procent133d8cb8fb224834bbfdde298adbec25($(this));
}
});
});
function ResizeImageWith100Procent133d8cb8fb224834bbfdde298adbec25(obj)
{
var orgsrc = obj.attr('orgsrc');
var width = obj.width();
width /= 100;
width = Math.ceil(width);
width *= 100;
if (obj.attr('src').indexOf('width_' + width) == -1) {
obj.attr('src', orgsrc + '?width=' + width );
}
}

<img orgsrc="/PageFiles/5/Desert.jpg" alt=""
src="/PageFiles/5/Desert.jpg?width=500" class="half100Procent scaleImage">
<img orgsrc="/PageFiles/5/product3Prev.png" alt="prevproduct1"
src="/PageFiles/5/product3Prev.png?width=200" class="border scaleImage">


<img orgsrc="/PageFiles/5/Desert.jpg" alt=""
src="/PageFiles/5/Desert.jpg?width=400" class="border scaleImage">

<img orgsrc="/PageFiles/5/product3Prev.png" alt="prevproduct1"
src="/PageFiles/5/product3Prev.png?width=400" class="border scaleImage">
What you need to do is to unzip the file and add the dll’s from the project to your bin folder, and
change the web.config to use ImageResizer.
Then you need to add the web control in the master page
Have added a working web.config and a working master.page from the
alloy project along with the zip of the project
Comments