開源方案搭建可離線的精美矢量切片地圖服務-8.mapbox 之sprite大圖圖標文件生成(附源碼)

 

系列文章目錄

開源方案搭建可離線的精美矢量切片地圖服務-1.開篇(附成果演示地址)css

開源方案搭建可離線的精美矢量切片地圖服務-2.PostGIS+GeoServer矢量切片 html

開源方案搭建可離線的精美矢量切片地圖服務-3.Mapbox個性化地圖定製入門前端

開源方案搭建可離線的精美矢量切片地圖服務-4.Mapbox樣式設計git

開源方案搭建可離線的精美矢量切片地圖服務-5.Mapbox離線項目實現github

開源方案搭建可離線的精美矢量切片地圖服務-6.Mapbox之.pbf字體庫json

開源方案搭建可離線的精美矢量切片地圖服務-7.Arcgis Pro企業級應用網絡

開源方案搭建可離線的精美矢量切片地圖服務-8.mapbox 之sprite大圖圖標文件生成(附源碼)字體

項目成果展現(全部項目文件都在阿里雲的共享雲虛擬主機上,訪問地圖能夠會有點慢,請多多包涵)。

01:中國地圖:http://test.sharegis.cn/mapbox/html/3china.html

02:德國-德累斯頓市:http://test.sharegis.cn/mapbox/html/6germany.htmlui

1.什麼是sprite文件

      sprite 文件主要是將一堆小圖生成一種大圖的方法,而且將每張小圖的位置信息保存下來,方便讀取。在網絡請求中會減小請求的數量,mapbox借鑑前端中CSS Sprite方法存儲圖標信息的。sprite.png文件保存圖標,sprite.json保存名稱及位置信息,下圖圖展現的是小圖標與大圖文件的示例。下面我講一下兩種文件互轉。阿里雲

image   <=互轉=>     image

     下面是此次項目實現的功能,包含Sprite大圖的合成與分割,也包含對單個圖標文件的寬度與高度的調整。

image

2.sprite大圖轉小圖

      咱們上一節講到是使用arcgis pro會將.mxd地圖配圖文件轉爲mapbox的樣式文件,一樣會生成sprite.png和sprite.json的圖標文件。因爲arcgis字體庫的限制,生成的圖標可能不符合的要求,咱們有修改圖標的須要,這裏咱們不只要替換大圖中的小圖標並且要記錄圖標的的位置信息到sprite.json中。下面寫了一個從大圖文件中生成單個小圖標文件的分割功能。

      實現思路:首先讀取大圖圖片,而後根據json文件中的位置信息,json中的圖標信息以下,xy表明圖標的左上角在大圖中的位置,width height表明圖標的大小,pixelRatio表明像素單位,spriteicon/county爲文件名。

"spriteicon/county": {
     "x": 75,
     "y": 0,
     "width": 32,
     "height": 14,
     "pixelRatio": 1,
     "sdf": false
}

讀取單個圖標文件的像素信息,寫到一個新建的Bitmap畫布中,實現成果與代碼以下:

image 轉換爲單個文件image

//sprite json文件
            string text = ReadFile(textBox3.Text); JObject obj = JObject.Parse(text); JToken item = null; //將json轉爲對象
            List<Param> paramlist = new List<Param>(); for (int i = 0; i < obj.Count; i++) { if (item == null) { item = obj.First; } else { item = item.Next; } Param p = new Param(); p.name = item.Path.Substring(2, item.Path.Length - 4).Replace("/", "-").Replace(":", "&"); p.x = (int)item.First["x"]; p.y = (int)item.First["y"]; p.width = (int)item.First["width"]; p.height = (int)item.First["height"]; paramlist.Add(p); } using (Bitmap map = (Bitmap)Image.FromFile(textBox3.Text+@"\sprite.png")) { using (Bitmap editMap = new Bitmap(map, map.Width, map.Height)) { foreach (var itemp in paramlist) { //保存圖片的畫布
                        Bitmap itemMap = new Bitmap(itemp.width, itemp.height); for (int i = 0; i < itemp.width; i++) { for (int j = 0; j < itemp.height; j++) { //獲取像素
                                Color color = editMap.GetPixel(itemp.x + i, itemp.y + j); itemMap.SetPixel(i, j, color); } } //保存
                        string savepath = System.Environment.CurrentDirectory + @"\spriteicon" + itemp.name+ ".png"; itemMap.Save(savepath); } } }

3.小圖標的調整

      對於一些規則的小圖標,例如標記路面信息的label,他的寬度由路的屬性信息決定,展現咱們要對不一樣長度的文字設置不一樣大小label這裏咱們要對多個圖標的寬度和高度進行調整,這是隻是對lable這樣規則的圖標進行調整,例如

image 寬度增長20pximage

實現思路:咱們選擇規則圖形的中心線,寬度調整就是以中心線進行左右拉伸複雜增長寬度,實現代碼以下:

DirectoryInfo folder = new DirectoryInfo(System.Environment.CurrentDirectory); List<string> filenames = new List<string>(); int addnum = Convert.ToInt32(textBox2.Text); foreach (var NextFolder in folder.GetFiles("*.png")) { if (NextFolder.Name.Contains(textBox1.Text)) { filenames.Add(NextFolder.Name); } } foreach (var item in filenames) { using (Bitmap map = (Bitmap)Image.FromFile(System.Environment.CurrentDirectory + "/" + item)) { using (Bitmap editMap = new Bitmap(map.Width + addnum, map.Height )) { int centernum = map.Width / 2; for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { //獲取像素
                                Color color = map.GetPixel(i, j); if (i == centernum) { editMap.SetPixel(i, j, color); if (addnum > 0) { for (int m = 0; m < addnum; m++) { editMap.SetPixel(i + m + 1,j, color); } } } else if (i < centernum) { editMap.SetPixel(i, j, color); } else { editMap.SetPixel(i + addnum,j, color); } } } //保存
                        string savepath = System.Environment.CurrentDirectory + @"\result\" + item; editMap.Save(savepath); } } }

4.小圖轉sprite大圖

      將小圖標合成一張sprite大圖並在sprite.json中記錄生成的位置信息,這裏最主要的就是圖標的擺放規則,

(1)獲取全部的圖標文件,按照高度從小到大排列

(2)根據大圖生成的默認寬度,循環小圖片,造成一行一行的圖片集合。

(3)根據行數和寬度生成大圖的寬度。

(4)循環小圖標,在大圖中畫出小圖標,並記錄位置信息。

實現成果與代碼以下:

image 轉換爲sprite文件image

DirectoryInfo folder = new DirectoryInfo(System.Environment.CurrentDirectory); List<Param> paramlist = new List<Param>(); foreach (var NextFolder in folder.GetFiles("*.png")) { using (Bitmap map = (Bitmap)Image.FromFile(System.Environment.CurrentDirectory + "/" + NextFolder.Name)) { Param p = new Param(); p.name = NextFolder.Name.Replace(".png", ""); p.width = map.Width; p.height = map.Height; paramlist.Add(p); } } //圖片默認寬度爲255,
            int widthnum = 255; paramlist = paramlist.OrderBy(m => m.name).OrderBy(m => m.height).ToList(); //一行一行的圖片集合
            List<List<Param>> rowparams = new List<List<Param>>(); List<Param> paramnowlist = new List<Param>(); int countnum = 0; for (int i = 0; i < paramlist.Count; i++) { countnum += paramlist[i].width; if (countnum > widthnum) { i = i - 1; countnum = 0; rowparams.Add(paramnowlist); paramnowlist = new List<Param>(); } else { paramnowlist.Add(paramlist[i]); } if (i == paramlist.Count - 1) { rowparams.Add(paramnowlist); break; } } //計算應有的高度
            int allheight = 0; foreach (var item in rowparams) { allheight += item.Select(m => m.height).Max(); } string spritejson = "{"; //開始畫大圖
            using (Bitmap editMap = new Bitmap(widthnum, allheight)) { //保存起始高度
                int heighttemp = 0; for (int i = 0; i < rowparams.Count; i++) { int tempwidthnum = 0; for (int j = 0; j < rowparams[i].Count; j++) { using (Bitmap map = (Bitmap)Image.FromFile(System.Environment.CurrentDirectory + "/" + rowparams[i][j].name + ".png")) { //循環小圖片
                            for (int x = 0; x < map.Width; x++) { for (int y = 0; y < map.Height; y++) { //獲取像素
                                    Color color = map.GetPixel(x, y); editMap.SetPixel(x+ tempwidthnum, y+ heighttemp, color); } } } spritejson += "\""+ rowparams[i][j].name.Replace("-", "/").Replace("&",":") + "\":{\"x\":"; spritejson += tempwidthnum + ",\"y\":" + heighttemp + ",\"width\":" + rowparams[i][j].width; spritejson += ",\"height\":" + rowparams[i][j].height + ",\"pixelRatio\":1,\"sdf\":false},"; //增長寬度
                       tempwidthnum += rowparams[i][j].width; } heighttemp += rowparams[i].Select(m => m.height).Max(); } //保存大圖
                string savepath = System.Environment.CurrentDirectory + @"\result\sprite.png"; editMap.Save(savepath); } spritejson= spritejson.TrimEnd(','); spritejson += "}"; //寫入文件
            using (StreamWriter fw= new StreamWriter(System.Environment.CurrentDirectory + @"\result\sprite.json")) { fw.WriteLine(spritejson); }

5.結尾

     咱們這裏的sprite大圖生成了sprite.json來保存位置信息,其實css sprite的實現也是相似的。使用圖片定位技術來實現的,例如像下面的這段css代碼同樣來對圖片作定位的,你們能夠簡單修改一下源碼即可實現,這裏就很少介紹了。

.bg-spriteicon {
    width: 17px; height: 17px;
    background: url('css_sprites.png') -138px -47px;
}

源碼地址:連接:https://pan.baidu.com/s/1tLihDaZFa--xFCzI42tfEA 密碼:f3dm

github地址:https://github.com/HuHongYong/Mapbox-sprite-generation

做者:ATtuing

出處:http://www.cnblogs.com/ATtuing

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。

相關文章
相關標籤/搜索