最近访问凡客诚品产品页留意了一下,这个页面的一些图动态做成了雪碧图,如:

从这张图片我们可以看到.SpriteWashings这个样式的背景图是通过joinp_w_picpaths.ashx动态生成,这个想法很好,但是没有生成样式。所以它的html使用了style="background-position: 0px -80px"这个来定位,个人认为这种方式不好,应该通过添加class 来定位,这就需要生成雪碧图的时候要生成相应的样式。

生成雪碧图的原理很简单:根据多个图片地址生成对应的Bitmap,在把这些Bitmap画到一个Bitmap上。

其核心代码如下:

    private static bool GenerateSprite(ImageSettings settings, int x, int y, List p_w_picpaths, StringBuilder cssCompatOutput)
        {            if (settings.TileInYAxis)
            {
                y += p_w_picpaths.Count;
            }            else
            {
                x += p_w_picpaths.Count;
            }            using (Bitmap sprite = new Bitmap(x, y))
            {                using (Graphics drawingSurface = Graphics.FromImage(sprite))
                {

                    drawingSurface.Clear(settings.BackgroundColor);                    int xOffset = 0;                    int yOffset = 0;                    foreach (Bitmap p_w_picpath in p_w_picpaths)
                    {
                        drawingSurface.DrawImage(p_w_picpath, new Rectangle(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 (EncoderParameters spriteEncoderParameters = new EncoderParameters(1))
                        {
                            spriteEncoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, settings.Quality);

                            sprite.Save(Path.Combine(settings.SpritePath, GenerateSpriteFileName(settings.SpriteName, settings.Format)), GetEncoderInfo(settings.Format), spriteEncoderParameters);
                        }                        return true;
                    }                    catch (Exception ex1)
                    {                        try
                        {

                            sprite.Save(Path.Combine(settings.SpritePath, GenerateSpriteFileName(settings.SpriteName, settings.Format)));                            return true;
                        }                        catch (Exception ex2)
                        {                            // sprite.Save( Path.Combine(settings.SpritePath, GenerateSpriteFileName(settings.SpriteName, "png")));
                            return false;
                        }
                    }

                }

            }

        }

自己做了一个简单的demo,代码结构如下:

SpriteImage是制作雪碧图的核心代码封装成dll,SpriteImageCreate是一个form工具。

运行效果如下:

看到效果了吧,我们的工具要求生成雪碧图同时也生成css。

我们来看看web的应用吧:

 public ActionResult Index()
        {            string basedirectory = Path.Combine(this.Request.PhysicalApplicationPath, "Content");
            FileInfo[] files = new DirectoryInfo(Path.Combine(basedirectory, "Images")).GetFiles();
            List filesPath = files.Select(x => x.FullName).ToList();
            ViewData.Add("Sprites", filesPath);            return View(ViewData);
        }
        [ChildActionOnly]        public ActionResult Sprite(List p_w_picpaths)
        {            if (p_w_picpaths == null || p_w_picpaths.Count < 1)                return View();            string[] filenames = p_w_picpaths.Select(x =>
            {                int startindex = x.LastIndexOf("\\");                int endindex = x.LastIndexOf(".");                return x = x.Substring(startindex + 1, endindex - startindex - 1);
            }).ToArray();            string spritname = string.Join("", filenames).GetHashCode().ToString();            string basedirectory = Path.Combine(this.Request.PhysicalApplicationPath, "Content/Sprites");            string cssFile = Path.Combine(basedirectory, spritname + ".css");            int index = this.Request.Url.OriginalString.LastIndexOf(this.Request.Url.LocalPath);            string prfx = this.Request.Url.OriginalString.Substring(0, index);            if (!System.IO.File.Exists(cssFile))
            {
                ImageSettings setting = new ImageSettings(spritname, basedirectory)
                {
                    CssSpriteUrl = prfx + "/Content/Sprites/",
                    TileInYAxis = false
                };
                StringBuilder sb = new StringBuilder();                var ret = ImageOptimizations.Optimizations(setting, sb, p_w_picpaths);                if (ret)
                {                    using (StreamWriter sw = new StreamWriter(cssFile, false, Encoding.UTF8))
                    {
                        sw.Write(sb.ToString());
                    }
                }
            }            if (System.IO.File.Exists(cssFile))
            {                string retFormat = " ";                string url = prfx + "/Content/Sprites/" + spritname + ".css";                return Content(string.Format(retFormat, url));
            }            return View();
        }

其中Index的目的是模拟一个动态的图片地址数据,在看看你我们view的代码:

@{
    ViewBag.Title = "Home Page";    var files = ViewData["Sprites"] as List;
}
@section HeadSection{
    @{ Html.RenderAction("Sprite", "Home", new { p_w_picpaths = files });}
}
    @{        foreach (var item in files)         {            int index = item.LastIndexOf("\\");            string subname = item.Substring(index + 1);             subname = subname.Replace(".", "_");                               
        }     }

代码是不是很简单,看看运行结果:




看到以上html代码,你能看出来我的雪碧图是动态生成的嘛?我不只是动态生成了雪碧图而且也生成了样式。

最总的html只是一个样式引用

 

来看看我们的样式文件:

大家看了我的样式文件,也就一定明白我的代码 class="joinp_w_picpaths1_png"  style="float:left " >为什么用的是class而不是什么定位了