zoukankan      html  css  js  c++  java
  • Web优化之雪碧图—动态生成雪碧图 读凡客产品页所想

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

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

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

    其核心代码如下:

        private static bool GenerateSprite(ImageSettings settings, int x, int y, List<Bitmap> images, StringBuilder cssCompatOutput)
            {
                if (settings.TileInYAxis)
                {
                    y += images.Count;
                }
                else
                {
                    x += images.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 image in images)
                        {
                            drawingSurface.DrawImage(image, new Rectangle(xOffset, yOffset, image.Width, image.Height));
                            if (image.Tag != null)
                                GenerateCss(xOffset, yOffset, image, cssCompatOutput, settings);
    
                            if (settings.TileInYAxis)
                            {
                                yOffset += image.Height + 1;
                            }
                            else
                            {
                                xOffset += image.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<string> filesPath = files.Select(x => x.FullName).ToList();
                ViewData.Add("Sprites", filesPath);
                return View(ViewData);
            }
            [ChildActionOnly]
            public ActionResult Sprite(List<string> images)
            {
                if (images == null || images.Count < 1)
                    return View();
                string[] filenames = images.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, images);
                    if (ret)
                    {
                        using (StreamWriter sw = new StreamWriter(cssFile, false, Encoding.UTF8))
                        {
                            sw.Write(sb.ToString());
                        }
                    }
                }
    
                if (System.IO.File.Exists(cssFile))
                {
                    string retFormat = " <link type=\"text/css\" rel=\"Stylesheet\" href=\"{0}\" />";
                    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<string>;
    }
    @section HeadSection{
        @{ Html.RenderAction("Sprite", "Home", new { images = files });}
    }
    <div>
        @{
            foreach (var item in files)
            {
                int index = item.LastIndexOf("\\");
                string subname = item.Substring(index + 1);
                subname = subname.Replace(".", "_");
                
            <div class="@subname"  style="float:left " >
            </div>
            }
        }
    </div>

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




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

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

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

    来看看我们的样式文件:

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

    完整的源代码下载

  • 相关阅读:
    Markdown学习
    二叉树的最近公共祖先
    javaCompiler简析
    自定义类加载器
    聚合和组合的区别
    拓扑排序
    C++ map和unordered_map
    静态文件加载路径
    文件上传
    jackson
  • 原文地址:https://www.cnblogs.com/majiang/p/2580841.html
Copyright © 2011-2022 走看看