自定义标记使用GMUClusterManager

9
我想使用GMUClusterManager来显示自定义标记。我按照标记聚类这里的所有步骤进行了操作,但是出现了像这样的蓝色和红色标记。 enter image description here 但是当我放大地图时,它只显示红色标记,而我不想要那个。 有一个实例方法,我在其中实现了我的逻辑,但没有用。
    - (instancetype)initWithMapView:(GMSMapView *)mapView clusterIconGenerator:(id<GMUClusterIconGenerator>)iconGenerator
{
    if ((self = [super init])) {

        GMSMarker *marker= [GMSMarker markerWithPosition:CLLocationCoordinate2DMake(24.0, 75.30)];

        UIView *customMarker =[[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 40)];
        customMarker.backgroundColor = [UIColor blueColor];

        marker.iconView = [self EmployeeMarker:0] ;
        marker.appearAnimation = kGMSMarkerAnimationPop;
        marker.map = mapView;
    }
    return self;
}

-(UIView *)EmployeeMarker:(int)labelTextInt{
    UIView *customMarker =[[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 40)];
    UIImageView *imgViewCustomMarker = [[UIImageView alloc]initWithFrame:CGRectMake(0, 15, 24, 25)];
    imgViewCustomMarker.image = [UIImage imageNamed:@"iconMapUser.png"];
    [customMarker addSubview:imgViewCustomMarker];
    UIView *viewRatingCustom = [[UIView alloc] initWithFrame:CGRectMake(15, 0, 40, 15)];
    viewRatingCustom.backgroundColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:192.0/255.0 alpha:1.0];
    UILabel *lblRatingEmployees = [[UILabel alloc] initWithFrame:CGRectMake(8, 1, 17,8)];
    lblRatingEmployees.textColor = [UIColor colorWithRed:0.00/255.0 green:100.0/255.0 blue:150.0/255.0 alpha:1.0];
    lblRatingEmployees.text = @"1";
    lblRatingEmployees.font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
    [lblRatingEmployees sizeToFit];
    [viewRatingCustom addSubview:lblRatingEmployees];
    UIImageView *imageViewStar = [[UIImageView alloc] initWithFrame:CGRectMake(25, 3, 10, 8)];
    imageViewStar.image = [UIImage imageNamed:@"iconBlueStar.png"];
    [viewRatingCustom addSubview:imageViewStar];
    [customMarker addSubview:viewRatingCustom];
    return customMarker;
}

我使用了这种方法来显示默认为红色的标记可能数量。

id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];

id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];


id<GMUClusterRenderer> renderer =
  [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView
                                clusterIconGenerator:iconGenerator];

_clusterManager =
  [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];

 // Generate and add random items to the cluster manager.

// [self generateClusterItems];


for (int i = 0; i<latitudeArray.count; i++) {

    id<GMUClusterItem> item =

    [[POIItem alloc]initWithPosition:CLLocationCoordinate2DMake([[latitudeArray objectAtIndex:i]doubleValue], [[longitudeArray objectAtIndex:i]doubleValue]) name:@"Name"];

    [_clusterManager addItem:item];
}

添加委托和集群方法。

 [_clusterManager cluster];
 [_clusterManager setDelegate:self mapDelegate:self];

所以请帮我添加自定义标记,替换默认的红色标记。

请查看 https://github.com/googlemaps/google-maps-ios-utils/blob/master/CustomMarkers.md https://github.com/googlemaps/google-maps-ios-utils/issues/21 - Nike Kov
5个回答

7

您需要创建一个符合 GMUClusterIconGenerator 协议的自定义类:

CustomClusterIconGenerator.h 文件:

@interface CustomClusterIconGenerator : NSObject
<GMUClusterIconGenerator>

@end

CustomClusterIconGenerator.m文件

@implementation CustomClusterIconGenerator

- (UIImage *)iconForSize:(NSUInteger)size {
    // Return custom icon for cluster
    return [UIImage imageNamed:@"Your Custom Cluster Image"];
}

- (UIImage *)iconForMarker {
    // Return custom icon for pin
    return [UIImage imageNamed:@"Your Custom Marker Image"];
}

- (CGPoint)markerIconGroundAnchor {
    // If your marker icon center shifted, return custom value for anchor
    return CGPointMake(0, 0);
}

- (CGPoint)clusterIconGroundAnchor {
    // If your cluster icon center shifted, return custom value for anchor
    return CGPointMake(0, 0);
}

@end

然后,相反地,不是


id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];

使用

CustomClusterIconGenerator *iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];

这里是我项目的一个示例: 在这里输入图像描述

CustomClusterIconGenerator iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init]; 在这个位置出现了错误。 - Mad Burea
iconForMarker不起作用了.. 因为聚合标记使用了这段代码 - (UIImage *)iconForSize:(NSUInteger)size - Mad Burea
@MadBurea 抱歉,打错字了。应该是 CustomClusterIconGenerator *iconGenerator。我已经更新了答案。 - Vitalii Gozhenko
关于iconForSize,也许自从我上次使用以来库已经更新了。这没问题,可以随意使用iconForSize。您始终可以查看GMUClusterIconGenerator协议声明 :-) - Vitalii Gozhenko
iconForSize 用于那个大红绿圆形聚类,而不是缩放后显示的标记。因为我想创建自定义标记而不是大红绿聚类,所以它没有用处。 - Mad Burea
1
@MadBurea iconForMarker 用于标记,而 iconForSize 用于聚类。 - Vitalii Gozhenko

5
在Swift 4.2中:
将以下扩展添加到您的控制器,并确保您的控制器是GMUClusterRendererDelegate的代理:
每次要渲染标记(聚合标记和聚合项标记)时,willRenderMarker都会调用它,因此您可以通过简单的if语句来检查它。因此,在向用户显示之前,您可以修改其图标等。
extension YourController: GMUClusterRendererDelegate {
    func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
        // if your marker is pointy you can change groundAnchor
        marker.groundAnchor = CGPoint(x: 0.5, y: 1)
        if  let markerData = (marker.userData as? PersonMarker) {
           let icon = markerData.imageURL
           marker.iconView = CustomMarkerView(forUrl: url)
        }
    }
}

PersonMarker是您的标记类,它是NSObjectGMUClusterItem的子类:(您可以使用GMUClusterItem的默认类,但如果需要其他属性,可以对其进行子类化)

class PersonMarker: NSObject, GMUClusterItem {

  var position: CLLocationCoordinate2D
  var imageURL : String?
  var name: String?
  var userdId: String?
  var lastSeen: String?

  init(position: CLLocationCoordinate2D, url: String?, name: String?, userId: String?, lastSeen: String?) {
      self.position = position
      self.imageURL = url
      self.name = name
      self.userdId = userId
      self.lastSeen = lastSeen
  }

}

您可以像这样将PersonMarker添加到您的GMUClusterManager中:
let position = CLLocationCoordinate2D(latitude: item.latitude!, longitude: item.longitute!)
let person = PersonMarker(position: position, url: item.user?.avaterUrl, name: item.user?.name, userId: item.user?.userId, lastSeen: item.lastUpdate)
clusterManager.add(person)

1
让渲染器 = CustomRendererMarkers(mapView: mapView, clusterIconGenerator: iconGenerator) 渲染器.delegate = self - hitesh

3
自从版本1.1.0以来,已添加了新功能,用于轻松定制标记(阅读更多)。
您可以添加GMUClusterRendererDelegateGMUDefaultClusterRenderer.h,并添加方法- (void)renderer:(id<GMUClusterRenderer>)renderer willRenderMarker:(GMSMarker *)marker;
在那里,您可以自定义标记和聚类。例如:
- (void)renderer:(id<GMUClusterRenderer>)renderer willRenderMarker:(GMSMarker *)marker{
    if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
        marker.icon=[UIImage imageNamed:@"custom_cluster_image.png"];
    }else if ([marker.userData conformsToProtocol:@protocol(GMUClusterItem)]) {
        marker.icon=[UIImage imageNamed:@"custom_marker_image.png"];
    }
}

记得正确设置代理:

id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:iconGenerator];
((GMUDefaultClusterRenderer *)renderer).delegate=self;

3
你需要自定义一个实现了 GMUClusterIconGenerator 接口的类,其中需要包含一个设计好的 func icon(forSize size: UInt) -> UIImage! 方法,该方法返回代表聚合标识符的 UIImage
建议先创建一个视图并添加相关功能,将聚合标题作为标签添加到视图中,然后从你的 UIView 中创建 UIImage
这样,你就能够按照以下方式创建自定义聚合生成器:
let iconGenerator = ClusterIconGenerator()

示例结果:

在此输入图像描述


工作生成器:

class ClusterIconGenerator: NSObject, GMUClusterIconGenerator {

    private struct IconSize {

        private let initialFontSize: CGFloat = 12
        private let fontMultiplier: CGFloat = 0.1

        private let initialSize: CGFloat = 25
        private let sizeMultiplier: CGFloat = 0.18

        /**
         Rounded cluster sizes  (like 10+, 20+, etc.)
         */
        private let sizes = [10,20,50,100,200,500,1000]

        let size: UInt

        /**
         Returns scale level based on size index in `sizes`. Returns `1` if size doesn't have rounded representation
         */
        private var scaleLevel: UInt {
            if let index = sizes.lastIndex(where: { $0 <= size }) {
                return UInt(index) + 2
            } else {
                return 1
            }
        }

        /**
         Returns designed title from cluster's size
         */
        var designedTitle: String {
            if let size = sizes.last(where: { $0 <= size }) {
                return "\(size)+"
            } else {
                return "\(size)"
            }
        }

        /**
         Returns initial font size multiplied by recursively created multiplier
         */
        var designedFontSize: CGFloat {
            let multiplier: CGFloat = (1...scaleLevel).reduce(1) { n,_ in n + n * fontMultiplier }
            return initialFontSize * multiplier
        }

        /**
         Returns initial `CGSize` multiplied by recursively created multiplier
         */
        var designedSize: CGSize {
            let multiplier: CGFloat = (1...scaleLevel).reduce(1) { n,_ in n + n * sizeMultiplier }
            return CGSize(width: initialSize * multiplier, height: initialSize * multiplier)
        }

    }

    /**
     Returns image based on current cluster's size
     */
    func icon(forSize size: UInt) -> UIImage! {

        let iconSize = IconSize(size: size)

        let frame = CGRect(origin: .zero, size: iconSize.designedSize)

        let view = UIView(frame: frame)
        view.layer.cornerRadius = iconSize.designedSize.height / 2
        view.backgroundColor = .green

        let label = UILabel(frame: frame)
        label.textAlignment = .center
        label.textColor = .white
        label.text = iconSize.designedTitle
        view.addSubview(label)

        return view.asImage
    }

}

extension UIView {

    var asImage: UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }

}

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接