准备工作
需要用到的软件 (解压密码 xclient.info)
-
Sketch 是一款Mac上小巧但功能强大的矢量绘图软件,这是专为设计师而打造的矢量绘图软件,拥有简约的设计,调色板,面板,菜单,窗口,控件和功能强大的矢量绘图和文字工具;包含针对UI设计的操作和交互模式,让你设计图标、移动手机UI、网站UI等更加简单高效。
-
PaintCode 是一款 Mac 上的 iOS 矢量绘图编程软件,无论是程序员还是设计师,PaintCode 能够让你像在PS中画图一样绘制各种UI图形,PaintCode 会自动帮你生成针对 Mac OS X 或 iOS 平台 Objective-C 或 C# 代码,能够节约大量的编程时间,支持将代码直接导入到 Xcode 中或导出为 PSD 文件,支持最新的 iOS 和 iWatch SDK,非常的实用!
地图 svg 文件的获取
推荐使用 HighChart 地图数据,在这里你可以自由的选择国内的某个省份地图下载相应的 svg 文件,这里选择福建省作为一个例子。
使用 Sketch 对下载的 svg 文件进行再加工
由于通过 HighChart 地图数据下载的 svg 文件有一些 logo 文字信息的部分图层是我们开发时不需要的,而且会干扰地图的显示,所以使用 Sketch 去除这些部分。
使用 Sketch 打开下载的 svg 文件,屏蔽这些无用的信息图层
重新导出得新 svg 文件才是我们接下来要用到地图文件
使用 PaintCode 根据 svg 文件生成 Objective-C 代码
通过 PaintCode 打开 svg 文件
我们可以看到 PaintCode 已经自动为我们生成了 Objective-C 代码,但是这只是图块的 UIBezierPath 路径代码,我们还需要添加文字和图钉的相应位置,接下来我们通过 PaintCode 添加这些内容。
-
添加市名
添加 Text,设置文字,调节文字位置以及字体大小为11,PaintCode 也自动生成了相应的代码。
-
添加图钉位置
添加图钉 Rect,调节 Rect 的位置,宽高都设置为20。
-
导出代码
按照上面的步骤添加其他的市名和图钉位置,并且导出代码文件。
整理代码文件
PaintCode 生成的文件包含了图块,文字,图钉三项内容的绘制代码,我们需要对这三项内容进行抽取和整理,这里以福建省为例。
+ (void)drawCanvas2WithFrame: (CGRect)targetFrame resizing: (FujianResizingBehavior)resizing
{
//// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();
//// Resize to Target Frame
CGContextSaveGState(context);
CGRect resizedFrame = FujianResizingBehaviorApply(resizing, CGRectMake(0, 0, 308, 340), targetFrame);
CGContextTranslateCTM(context, resizedFrame.origin.x, resizedFrame.origin.y);
CGContextScaleCTM(context, resizedFrame.size.width / 308, resizedFrame.size.height / 340);
UIColor* strokeColor = [UIColor colorWithRed: 0.8 green: 0.8 blue: 0.8 alpha: 1];
UIColor* fillColor = [UIColor colorWithRed: 0.486 green: 0.71 blue: 0.925 alpha: 1];
//// 页面1
{
//// chart-(1)
{
//// Clipped
{
//// Group 编组 5
{
//// Group 6
{
//// Bezier 形状 2 Drawing
UIBezierPath* bezier2Path = [UIBezierPath bezierPath];
[bezier2Path moveToPoint: CGPointMake(215.48, 200.9)];
[bezier2Path addLineToPoint: CGPointMake(214.85, 200.27)];
[bezier2Path addLineToPoint: CGPointMake(215.17, 199.01)];
[bezier2Path addLineToPoint: CGPointMake(215.8, 199.32)];
[bezier2Path addLineToPoint: CGPointMake(216.43, 198.06)];
......
[bezier2Path closePath];
[bezier2Path moveToPoint:
[bezier2Path closePath];
[fillColor setFill];
[bezier2Path fill];
[strokeColor setStroke];
bezier2Path.lineWidth = 1;
bezier2Path.miterLimit = 4;
[bezier2Path stroke];
}
......
}
}
}
}
//// Text Drawing
CGRect textRect = CGRectMake(128, 71, 39, 26);
{
NSString* textContent = @"南平市";
NSMutableParagraphStyle* textStyle = [[NSMutableParagraphStyle alloc] init];
textStyle.alignment = NSTextAlignmentLeft;
NSDictionary* textFontAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize: 11], NSForegroundColorAttributeName: UIColor.blackColor, NSParagraphStyleAttributeName: textStyle};
CGFloat textTextHeight = [textContent boundingRectWithSize: CGSizeMake(textRect.size.width, INFINITY) options: NSStringDrawingUsesLineFragmentOrigin attributes: textFontAttributes context: nil].size.height;
CGContextSaveGState(context);
CGContextClipToRect(context, textRect);
[textContent drawInRect: CGRectMake(CGRectGetMinX(textRect), CGRectGetMinY(textRect) + (textRect.size.height - textTextHeight) / 2, textRect.size.width, textTextHeight) withAttributes: textFontAttributes];
CGContextRestoreGState(context);
}
......
//// Rectangle Drawing
UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(135, 56, 20, 20)];
[UIColor.grayColor setFill];
[rectanglePath fill];
......
CGContextRestoreGState(context);
}
-
新建一个 FujianMapPath 文件继承于 ChinaMapPath 类,这个文件用来存放整理分类后的代码
-
图块部分
我们只需要摘取
UIBezierPath的路径部分代码即可,也就是每一个bezierPath在以下代码之前的路径代码(换个说法就是删除每个bezierPath的以下代码)[fillColor setFill]; [bezier2Path fill]; [strokeColor setStroke]; bezier2Path.lineWidth = 1; bezier2Path.miterLimit = 4; [bezier2Path stroke];整理后的
bezierPath放在FujianMapPath的pathArray中。 -
文字部分
我们只需要摘取每段
textRect的 frame 即可,CGRect textRect = CGRectMake(128, 71, 39, 26);整理后的
textRect放在FujianMapPath的textRectArray中,使用NSValue存储。文字内容需要另外存储在在FujianMapPath的textArray中。 -
图钉部分
我们只需要摘取每段
rectanglePath的起始点即可,UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(135, 56, 20, 20)]; => CGPointMake(135, 56)整理后的
point放在FujianMapPath的pinPointArray中。
需要注意的是,我们自行绘制的文字部分和图块部分的市区顺序一般是不一致的,所以我们要根据图块顺序调换 textArray、textRectArray 和 pinPointArray 中市区的顺序
使用 CXProvincesMapView 展示我们获取的代码数据
/// 自定义的地图快捷创建方法
/// @param mapPath svg 绘图数据
/// @param mapSize svg 绘图尺寸,即 svg 文件中图层的宽高
/// @param frame 视图控件的frame
- (instancetype)initWithMapPath:(ChinaMapPath *)mapPath andMapSize:(CGSize)mapSize andFrame:(CGRect)frame;
示例:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 福建省市数据
FujianMapPath *mapPath = [[FujianMapPath alloc] init];
self.chinaMapView = [[CXProvincesMapView alloc]initWithMapPath:mapPath andMapSize:CGSizeMake(308, 340) andFrame:CGRectMake(0, 0, self.view.bounds.size.width, 400)];
_chinaMapView.backgroundColor = [UIColor colorWithRed:230/255.0 green:1.0 blue:1.0 alpha:1.0];
_chinaMapView.maximumZoomScale = 5.0;
_chinaMapView.center = self.view.center;
_chinaMapView.delegate = self;
// _chinaMapView.pinAnimation = NO;
// 直接设置图片
// _chinaMapView.pinImage = [UIImage imageNamed:@"pin"];
// 添加按钮点击
UIButton *pinButton = [[UIButton alloc]initWithFrame:_chinaMapView.pinView.bounds];
[pinButton setImage:[UIImage imageNamed:@"pin"] forState:UIControlStateNormal];
[pinButton addTarget:self action:@selector(pinTest) forControlEvents:UIControlEventTouchUpInside];
[_chinaMapView.pinView addSubview:pinButton];
[self.view addSubview:_chinaMapView];
}
效果:
总结
以上步骤看起来繁琐,实际上操作起来并不是很复杂,主要的代码部分 PaintCode 已经为我们生成好了,可以在有 svg 图片的前提下生成任意的地图区域控件,CXProvincesMapView 中国省份地图区域的控件也是这样子生成的。假如你不需要文字或者图钉部分,你可以不用另外绘制文字或者图钉,相对应的数组传入空值就行了。
完结散花(^▽^),希望这篇教程对你有帮助!