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而不是什么定位了

    完整的源代码下载

  • 相关阅读:
    天梯赛5-12 愿天下有情人都是失散多年的兄妹 【dfs】
    poj2718 Smallest Difference【贪心】
    HDU problem 5635 LCP Array【思维】
    codeforces 782C Andryusha and Colored Balloons【构造】
    HDU 4278 Faulty Odometer【进制转换】
    codeforces B. The Meeting Place Cannot Be Changed【二分】
    POJ 3264 Balanced Lineup 【线段树】
    HDU 1850
    CodeForces-714C
    HDU Problem 1247 Hat's Words 【字典树】
  • 原文地址:https://www.cnblogs.com/majiang/p/2580841.html
Copyright © 2011-2022 走看看