1. 程式人生 > 實用技巧 >Web優化之雪碧圖

Web優化之雪碧圖

最近訪問凡客誠品產品頁留意了一下,這個頁面的一些圖動態做成了雪碧圖,如:

從這張圖片我們可以看到.SpriteWashings這個樣式的背景圖是通過joinp_w_picpaths.ashx動態生成,這個想法很好,但是沒有生成樣式。所以它的html使用了style="background-position: 0px -80px"這個來定位,個人認為這種方式不好,應該通過新增class 來定位,這就需要生成雪碧圖的時候要生成相應的樣式。

生成雪碧圖的原理很簡單:根據多個圖片地址生成對應的Bitmap,在把這些Bitmap畫到一個Bitmap上。

其核心程式碼如下:

複製程式碼

privatestaticboolGenerateSprite(ImageSettingssettings,intx,inty,List<Bitmap>p_w_picpaths,StringBuildercssCompatOutput)
{if(settings.TileInYAxis)
{
y+=p_w_picpaths.Count;
}else
{
x+=p_w_picpaths.Count;
}using(Bitmapsprite=newBitmap(x,y))
{using(GraphicsdrawingSurface=Graphics.FromImage(sprite))
{

drawingSurface.Clear(settings.BackgroundColor);intxOffset=0;intyOffset=0;foreach(Bitmapp_w_picpathinp_w_picpaths)
{
drawingSurface.DrawImage(p_w_picpath,newRectangle(xOffset,yOffset,p_w_picpath.Width,p_w_picpath.Height));if(p_w_picpath.Tag!=null)
GenerateCss(xOffset,yOffset,p_w_picpath,cssCompatOutput,settings);if(settings.TileInYAxis)
{
yOffset+=p_w_picpath.Height+1;
}else
{
xOffset+=p_w_picpath.Width+1;
}
}try
{using(EncoderParametersspriteEncoderParameters=newEncoderParameters(1))
{
spriteEncoderParameters.Param[0]=newEncoderParameter(System.Drawing.Imaging.Encoder.Quality,settings.Quality);

sprite.Save(Path.Combine(settings.SpritePath,GenerateSpriteFileName(settings.SpriteName,settings.Format)),GetEncoderInfo(settings.Format),spriteEncoderParameters);
}returntrue;
}catch(Exceptionex1)
{try
{

sprite.Save(Path.Combine(settings.SpritePath,GenerateSpriteFileName(settings.SpriteName,settings.Format)));returntrue;
}catch(Exceptionex2)
{//sprite.Save(Path.Combine(settings.SpritePath,GenerateSpriteFileName(settings.SpriteName,"png")));
returnfalse;
}
}

}

}

}

複製程式碼

自己做了一個簡單的demo,程式碼結構如下:

SpriteImage是製作雪碧圖的核心程式碼封裝成dll,SpriteImageCreate是一個form工具。

執行效果如下:

看到效果了吧,我們的工具要求生成雪碧圖同時也生成css。

我們來看看web的應用吧:

複製程式碼

publicActionResultIndex()
{stringbasedirectory=Path.Combine(this.Request.PhysicalApplicationPath,"Content");
FileInfo[]files=newDirectoryInfo(Path.Combine(basedirectory,"Images")).GetFiles();
List<string>filesPath=files.Select(x=>x.FullName).ToList();
ViewData.Add("Sprites",filesPath);returnView(ViewData);
}
[ChildActionOnly]publicActionResultSprite(List<string>p_w_picpaths)
{if(p_w_picpaths==null||p_w_picpaths.Count<1)returnView();string[]filenames=p_w_picpaths.Select(x=>
{intstartindex=x.LastIndexOf("\\");intendindex=x.LastIndexOf(".");returnx=x.Substring(startindex+1,endindex-startindex-1);
}).ToArray();stringspritname=string.Join("",filenames).GetHashCode().ToString();stringbasedirectory=Path.Combine(this.Request.PhysicalApplicationPath,"Content/Sprites");stringcssFile=Path.Combine(basedirectory,spritname+".css");intindex=this.Request.Url.OriginalString.LastIndexOf(this.Request.Url.LocalPath);stringprfx=this.Request.Url.OriginalString.Substring(0,index);if(!System.IO.File.Exists(cssFile))
{
ImageSettingssetting=newImageSettings(spritname,basedirectory)
{
CssSpriteUrl=prfx+"/Content/Sprites/",
TileInYAxis=false
};
StringBuildersb=newStringBuilder();varret=ImageOptimizations.Optimizations(setting,sb,p_w_picpaths);if(ret)
{using(StreamWritersw=newStreamWriter(cssFile,false,Encoding.UTF8))
{
sw.Write(sb.ToString());
}
}
}if(System.IO.File.Exists(cssFile))
{stringretFormat="<linktype=\"text/css\"rel=\"Stylesheet\"href=\"{0}\"/>";stringurl=prfx+"/Content/Sprites/"+spritname+".css";returnContent(string.Format(retFormat,url));
}returnView();
}

複製程式碼

其中Index的目的是模擬一個動態的圖片地址資料,在看看你我們view的程式碼:

複製程式碼

@{
ViewBag.Title="HomePage";varfiles=ViewData["Sprites"]asList<string>;
}
@sectionHeadSection{
@{Html.RenderAction("Sprite","Home",new{p_w_picpaths=files});}
}
<div>
@{foreach(variteminfiles)
{intindex=item.LastIndexOf("\\");stringsubname=item.Substring(index+1);
subname=subname.Replace(".","_");

<divclass="@subname"style="float:left">
</div>
}
}
</div>

複製程式碼

程式碼是不是很簡單,看看執行結果:




看到以上html程式碼,你能看出來我的雪碧圖是動態生成的嘛?我不只是動態生成了雪碧圖而且也生成了樣式。

最總的html只是一個樣式引用

<link type="text/css" rel="Stylesheet" href="http://localhost:1468/Content/Sprites/602831660.css" />

來看看我們的樣式檔案:

大家看了我的樣式檔案,也就一定明白我的程式碼<divclass="joinp_w_picpaths1_png" style="float:left " >為什麼用的是class而不是什麼定位了


轉載於:https://blog.51cto.com/huyusheng/1925306