开源方案搭建可离线的精美矢量切片地图服务-8.mapbox 之sprite大图图标文件生成(附源码)
系列文章目录
开源方案搭建可离线的精美矢量切片地图服务-1.开篇(附成果演示地址)
开源方案搭建可离线的精美矢量切片地图服务-2.PostGIS+GeoServer矢量切片
开源方案搭建可离线的精美矢量切片地图服务-3.Mapbox个性化地图定制入门
开源方案搭建可离线的精美矢量切片地图服务-4.Mapbox样式设计
开源方案搭建可离线的精美矢量切片地图服务-5.Mapbox离线项目实现
开源方案搭建可离线的精美矢量切片地图服务-6.Mapbox之.pbf字体库
开源方案搭建可离线的精美矢量切片地图服务-7.Arcgis Pro企业级应用
开源方案搭建可离线的精美矢量切片地图服务-8.mapbox 之sprite大图图标文件生成(附源码)
项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵)。
01:中国地图:http://test.sharegis.cn/mapbox/html/3china.html
02:德国-德累斯顿市:http://test.sharegis.cn/mapbox/html/6germany.html
1.什么是sprite文件
sprite 文件主要是将一堆小图生成一种大图的方法,并且将每张小图的位置信息保存下来,方便读取。在网络请求中会减少请求的数量,mapbox借鉴前端中CSS Sprite方法存储图标信息的。sprite.png文件保存图标,sprite.json保存名称及位置信息,下图图展示的是小图标与大图文件的示例。下面我讲一下两种文件互转。
<=互转=> 
下面是这次项目实现的功能,包含Sprite大图的合成与分割,也包含对单个图标文件的宽度与高度的调整。

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画布中,实现成果与代码如下:
转换为单个文件
//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 = ; i < obj.Count; i++)
{
if (item == null)
{
item = obj.First;
}
else
{
item = item.Next;
}
Param p = new Param();
p.name = item.Path.Substring(, item.Path.Length - ).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 = ; i < itemp.width; i++)
{
for (int j = ; 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这样规则的图标进行调整,例如
宽度增加20px
实现思路:我们选择规则图形的中心线,宽度调整就是以中心线进行左右拉伸复杂增加宽度,实现代码如下:
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 / ;
for (int i = ; i < map.Width; i++)
{
for (int j = ; j < map.Height; j++)
{
//获取像素
Color color = map.GetPixel(i, j);
if (i == centernum)
{
editMap.SetPixel(i, j, color);
if (addnum > )
{
for (int m = ; m < addnum; m++)
{
editMap.SetPixel(i + m + ,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)循环小图标,在大图中画出小图标,并记录位置信息。
实现成果与代码如下:
转换为sprite文件
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 = ;
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 = ;
for (int i = ; i < paramlist.Count; i++)
{
countnum += paramlist[i].width;
if (countnum > widthnum)
{
i = i - ;
countnum = ;
rowparams.Add(paramnowlist);
paramnowlist = new List<Param>();
}
else
{
paramnowlist.Add(paramlist[i]);
}
if (i == paramlist.Count - )
{
rowparams.Add(paramnowlist);
break;
}
}
//计算应有的高度
int allheight = ;
foreach (var item in rowparams)
{
allheight += item.Select(m => m.height).Max();
}
string spritejson = "{";
//开始画大图
using (Bitmap editMap = new Bitmap(widthnum, allheight))
{
//保存起始高度
int heighttemp = ;
for (int i = ; i < rowparams.Count; i++)
{
int tempwidthnum = ;
for (int j = ; j < rowparams[i].Count; j++)
{
using (Bitmap map = (Bitmap)Image.FromFile(System.Environment.CurrentDirectory + "/" + rowparams[i][j].name + ".png"))
{
//循环小图片
for (int x = ; x < map.Width; x++)
{
for (int y = ; 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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
开源方案搭建可离线的精美矢量切片地图服务-8.mapbox 之sprite大图图标文件生成(附源码)的更多相关文章
- 开源方案搭建可离线的精美矢量切片地图服务-3.Mapbox个性化地图定制入门
1.简介 mapbox是一家非常牛的公司,比如像特斯拉.DJI大疆创新.孤独星球.Airbnb.GitHub.Cisco.Snap.飞猪.Keep.Bosch这些在国内外各自领域中响当当的企业都是它的 ...
- 开源方案搭建可离线的精美矢量切片地图服务-6.Mapbox之.pbf字体库
项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...
- 开源方案搭建可离线的精美矢量切片地图服务-5.Mapbox离线项目实现
项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...
- 开源方案搭建可离线的精美矢量切片地图服务-4.Mapbox样式设计
项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...
- 开源方案搭建可离线的精美矢量切片地图服务-7.Arcgis Pro企业级应用
1.前言 上篇讲.pbf字体库的时候说到我们使用的字体通过Arcgis Pro 生成,Arcgis Pro样式基于Mapbox做的矢量切片地图渲染.这篇主要讲一下Arcgis Pro矢量切片生成的的具 ...
- 开源方案搭建可离线的精美矢量切片地图服务-2.PostGIS+GeoServer矢量切片
项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...
- Python的开源人脸识别库:离线识别率高达99.38%(附源码)
Python的开源人脸识别库:离线识别率高达99.38%(附源码) 转https://cloud.tencent.com/developer/article/1359073 11.11 智慧上云 ...
- Socket实现仿QQ聊天(可部署于广域网)附源码(2)-服务器搭建
1.前言 这是本系列的第二篇文章,第一篇文章得到了很多朋友们的支持,在这里表示非常的感谢.对于这一系列文章需要补充的是这只是一篇入门级别的Socket通信文章,对于专业人员来说完全可以跳过.本文只介绍 ...
- (原创)通用查询实现方案(可用于DDD)[附源码] -- 简介
[声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html). [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...
随机推荐
- SRM483
250pt 题意:给定一个[0,1)间的实数,一个分母不超过maxDen的分数逼近.. 思路:直接枚举.然后判断. code: #line 7 "BestApproximationDiv1. ...
- VS2008 安装WINCE插件报错 ToolsMsmCA(Error)解决方案___VS2008
在win7系统,VS2008环境下安装EFMS9280_SDK.msi文件出现报错 ToolsMsmCA(Error):IHxFilters filter registration failure: ...
- 火狐浏览器(Firefox)打开EBS form的设置方法
http://yedward.net/?id=247 客户在使用EBS的时候,很多都是使用IE浏览器打开,但是EBS并不仅仅只是支持IE,对于谷歌浏览器(Chrome).火狐浏览器(Firefox)也 ...
- unigui web app之title buttons
unigui web app之title buttons title buttons:窗体标题按钮 通过 窗体标题按钮,可以方便地导航,比如返回主页. 处理窗体标题按钮的点击事件: procedure ...
- Ubuntu 安装Sqldeveloper
linux下最好用的Oracle开发工具可能就是sqldeveloper了 首先在http://otn.oracle.com/ 上下载最新的Linux - sqldeveloper 我下载的时候版本是 ...
- 通过键盘控制改变物体transform值
通过键盘控制改变物体transform值 private Vector3 trans; //使用Rotate绕y 轴旋转 transform.Rotate(new Vector3(0,Input.Ge ...
- 使用EF6连接mariaDB出现中文查找不到数据的问题
1.问题描述 这两天使用ef6.0查询mariaDB出现了数据查询不到的情况 2.问题分析 后来发现除了这段数据查询不到,其他都能查询,于是逐步对比代码,发现其他数据都是英文的,而这句是中文的于是把条 ...
- 【转】Windows Server 2016 安装 IIS 服务时提示指定备用源路径
原文地址:http://www.codingwhy.com/view/973.html 在Windows Serever 2016中安装IIS的时候,遇到以下提示 是否需要指定备用源路径?一个或多个安 ...
- python3之paramiko模块
1.paramiko模块介绍 paramiko模块提供了基于ssh连接,进行远程登录服务器执行命令和上传下载文件的功能.这是一个第三方的软件包,使用之前需要安装. 2.paramiko的使用方法 (1 ...
- Linux系统文件压缩与备份(5)
在 Linux 系统选有相当多的压缩命令可以使用,这些压缩指令可以让我们更方便的从网上下载大型文件,本章第一节内容我们就来谈谈这个 Linux 系统下常用的几种压缩格式吧. 谈完了压缩后,我们接着来说 ...