使用 PaintCode 繪製自定義的省份地圖控件

Demo連接git

準備工做

須要用到的軟件 (解壓密碼 xclient.info)
  • Sketch程序員

    Sketch 是一款Mac上小巧但功能強大的矢量繪圖軟件,這是專爲設計師而打造的矢量繪圖軟件,擁有簡約的設計,調色板,面板,菜單,窗口,控件和功能強大的矢量繪圖和文字工具;包含針對UI設計的操做和交互模式,讓你設計圖標、移動手機UI、網站UI等更加簡單高效。github

  • PaintCodeobjective-c

    PaintCode 是一款 Mac 上的 iOS 矢量繪圖編程軟件,不管是程序員仍是設計師,PaintCode 可以讓你像在PS中畫圖同樣繪製各類UI圖形,PaintCode 會自動幫你生成針對 Mac OS X 或 iOS 平臺 Objective-C 或 C# 代碼,可以節約大量的編程時間,支持將代碼直接導入到 Xcode 中或導出爲 PSD 文件,支持最新的 iOS 和 iWatch SDK,很是的實用!編程

地圖 svg 文件的獲取

推薦使用 HighChart 地圖數據,在這裏你能夠自由的選擇國內的某個省份地圖下載相應的 svg 文件,這裏選擇福建省做爲一個例子。數組

image-20191027233307531

使用 Sketch 對下載的 svg 文件進行再加工

因爲經過 HighChart 地圖數據下載的 svg 文件有一些 logo 文字信息的部分圖層是咱們開發時不須要的,並且會干擾地圖的顯示,因此使用 Sketch 去除這些部分。ide

使用 Sketch 打開下載的 svg 文件,屏蔽這些無用的信息圖層svg

image-20191027234921580

從新導出得新 svg 文件纔是咱們接下來要用到地圖文件工具

image-20191027235144789

使用 PaintCode 根據 svg 文件生成 Objective-C 代碼

經過 PaintCode 打開 svg 文件字體

image-20191028000419208

咱們能夠看到 PaintCode 已經自動爲咱們生成了 Objective-C 代碼,可是這只是圖塊的 UIBezierPath 路徑代碼,咱們還須要添加文字和圖釘的相應位置,接下來咱們經過 PaintCode 添加這些內容。

  • 添加市名

    添加 Text,設置文字,調節文字位置以及字體大小爲11,PaintCode 也自動生成了相應的代碼。

    image-20191028001128976

  • 添加圖釘位置

    添加圖釘 Rect,調節 Rect 的位置,寬高都設置爲20。

    image-20191028001948626

  • 導出代碼

    按照上面的步驟添加其餘的市名和圖釘位置,而且導出代碼文件。

    image-20191028002543468

整理代碼文件

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);

}

複製代碼
  1. 新建一個 FujianMapPath 文件繼承於 ChinaMapPath 類,這個文件用來存放整理分類後的代碼
  2. 圖塊部分

    咱們只須要摘取 UIBezierPath 的路徑部分代碼便可,也就是每個 bezierPath 在如下代碼以前的路徑代碼(換個說法就是刪除每一個bezierPath 的如下代碼)

    [fillColor setFill];
                            [bezier2Path fill];
                            [strokeColor setStroke];
                            bezier2Path.lineWidth = 1;
                            bezier2Path.miterLimit = 4;
                            [bezier2Path stroke];
    複製代碼

    整理後的 bezierPath 放在 FujianMapPathpathArray 中。

  3. 文字部分

    咱們只須要摘取每段 textRect 的 frame 便可,

    CGRect textRect = CGRectMake(128, 71, 39, 26);
    複製代碼

    整理後的 textRect 放在 FujianMapPathtextRectArray 中,使用 NSValue存儲。文字內容須要另外存儲在在 FujianMapPathtextArray 中。

  4. 圖釘部分

    咱們只須要摘取每段 rectanglePath 的起始點便可,

    UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(135, 56, 20, 20)];
    =>  CGPointMake(135, 56)
    複製代碼

    整理後的 point 放在 FujianMapPathpinPointArray 中。

須要注意的是,咱們自行繪製的文字部分和圖塊部分的市區順序通常是不一致的,因此咱們要根據圖塊順序調換 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];
}
複製代碼

效果:

image-20191028011542388

總結

以上步驟看起來繁瑣,實際上操做起來並非很複雜,主要的代碼部分 PaintCode 已經爲咱們生成好了,能夠在有 svg 圖片的前提下生成任意的地圖區域控件,CXProvincesMapView 中國省份地圖區域的控件也是這樣子生成的。假如你不須要文字或者圖釘部分,你能夠不用另外繪製文字或者圖釘,相對應的數組傳入空值就好了。

完結散花(^▽^),但願這篇教程對你有幫助!

相關文章
相關標籤/搜索