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