Ios 如何在Swift中实现GMUClusterRenderer
我正在使用谷歌地图API的iOS和想要使用标记聚类实用程序。我知道了如何显示聚集标记,但我想自定义标记。有人能解释一下如何设置/更改每个标记或聚集标记的图标和标题吗?一个示例代码将非常有用Ios 如何在Swift中实现GMUClusterRenderer,ios,swift,google-maps,google-maps-markers,google-maps-sdk-ios,Ios,Swift,Google Maps,Google Maps Markers,Google Maps Sdk Ios,我正在使用谷歌地图API的iOS和想要使用标记聚类实用程序。我知道了如何显示聚集标记,但我想自定义标记。有人能解释一下如何设置/更改每个标记或聚集标记的图标和标题吗?一个示例代码将非常有用 class POIItem: NSObject, GMUClusterItem { var position: CLLocationCoordinate2D var name: String! init(position: CLLocationCoordinate2D, name:
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var name: String!
init(position: CLLocationCoordinate2D, name: String) {
self.position = position
self.name = name
}
}
class MyRenderer: NSObject, GMUClusterRenderer {
var mapView: GMSMapView
var clusterIconGenerator: GMUClusterIconGenerator
var clusterManager: GMUClusterManager
init(mapView: GMSMapView, clusterIconGenerator: GMUClusterIconGenerator, clusterManager: GMUClusterManager) {
self.mapView = mapView
self.clusterIconGenerator = clusterIconGenerator
self.clusterManager = clusterManager
}
func renderClusters(clusters: [GMUCluster]) {
}
func update() {
}
}
这就是我目前所拥有的。我不知道如何使用RenderCluster和更新功能。如果您将Google Maps iOS Utils源文件包括到项目中,有一种“脏”方法可以更改标记的图标 不幸的是,并没有公共方法来设置自定义图标,但您可以在源文件中更改它 在谷歌地图Utils/Clustering/View/GMUDefaultClusterRenderer.m中
- (void)renderCluster:(id<GMUCluster>)cluster animated:(BOOL)animated {
...
GMSMarker *marker = [self markerWithPosition:item.position
from:fromPosition
userData:item
clusterIcon:[UIImage imageNamed:@"YOUR_CUSTOM_ICON"]
animated:shouldAnimate];
...
}
我设法找到了“干净”的解决方案,尽管它仍然令人困惑。但它是有效的
1) 创建.h文件“MarkerManager”
3) 创建新的swift类,项目:
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
@objc var marker: GMSMarker!
init(position: CLLocationCoordinate2D, marker: GMSMarker) {
self.position = position
self.marker = marker
}
}
4) 扩展GMUDefaultClusterRenderer类并重写markerWithPosition方法:
import Foundation
import UIKit
class CustomMarkers: GMUDefaultClusterRenderer {
var mapView:GMSMapView?
let kGMUAnimationDuration: Double = 0.5
override init(mapView: GMSMapView, clusterIconGenerator iconGenerator: GMUClusterIconGenerator) {
super.init(mapView: mapView, clusterIconGenerator: iconGenerator)
}
func markerWithPosition(position: CLLocationCoordinate2D, from: CLLocationCoordinate2D, userData: AnyObject, clusterIcon: UIImage, animated: Bool) -> GMSMarker {
let initialPosition = animated ? from : position
let marker = GMSMarker(position: initialPosition)
marker.userData! = userData
if clusterIcon.cgImage != nil {
marker.icon = clusterIcon
}
else {
marker.icon = self.getCustomTitleItem(userData: userData)
}
marker.map = mapView
if animated
{
CATransaction.begin()
CAAnimation.init().duration = kGMUAnimationDuration
marker.layer.latitude = position.latitude
marker.layer.longitude = position.longitude
CATransaction.commit()
}
return marker
}
func getCustomTitleItem(userData: AnyObject) -> UIImage {
let item = userData as! POIItem
return item.marker.icon!
}
}
5) 在generateClusterItems方法的MapViewController初始化POITEM中:
private func generateClusterItems() {
for object in DataManager.sharedInstance.mapItemsArray {
let doubleLat = Double(object.latitude)
let doubleLong = Double(object.longitude)
let latitude = CLLocationDegrees(doubleLat!)
let longitude = CLLocationDegrees(doubleLong!)
let position = CLLocationCoordinate2DMake(latitude, longitude)
let marker = GMSMarker(position: position)
let item = POIItem(position: position, marker: marker)
self.clusterManager.add(item)
item.mapItem = object
}
}
在for循环中,您可以调用:
marker.icon = UIImage(named:"YOUR_IMAGE_NAME")
现在,您可以将逻辑设置为拥有多个自定义标记。我在Swift 4上找到了一个干净的群集标记解决方案,可以为包含群集编号的群集使用自定义图像:
class MapClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: String(size) as NSString,
inImage: UIImage(named: "cluster")!,
font: UIFont.systemFont(ofSize: 12))
return image
}
private func textToImage(drawText text: NSString, inImage image: UIImage, font: UIFont) -> UIImage {
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.black
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/2
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
text.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
而不是群集管理器的设置:
private func setupClustering() {
guard let mapView = self.mapView else { return }
let iconGenerator = MapClusterIconGenerator()
let renderer = MapClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
}
我还在Swift 4.2中使用了自定义集群渲染器
MapClusterRenderer
:
您可以使用GMUClusterRenderDelegate
:
将此扩展添加到控制器,并确保控制器是gmuclusterrenderDelegate
的代理:
willRenderMarker
将在每次渲染标记时调用标记(包括集群标记和clusterItemMarker,以便您可以通过简单的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是您的标记类,它是NSObject
和GMUClusterItem
的子类:(您可以使用GMUClusterItem
的默认类,但如果您需要一些其他属性,可以将其子类化)
您可以将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:
class HFDashBordVC: UIViewController,GMUClusterManagerDelegate,GMSMapViewDelegate{
private var clusterManager: GMUClusterManager!
var cameraPosition = GMSCameraPosition()
var markerPin = GMSMarker()
var currentLocationCircle = GMSCircle()
var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var zoomLevel: Float = 18.0
@IBOutlet var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupClustering()
}
func setupClustering() {
let iconGenerator = CustomClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = CustomRendererMarkers(mapView: mapView,
clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
}
private func setClusterParkingPin() {
clusterManager.clearItems()
for object in AppUtilites.sharedInstance.safeParkingArray {
let model = object as! AMParkModel
let lat = Double(model.latitude)!
let lng = Double(model.longitude)!
let position = CLLocationCoordinate2DMake(lat, lng)
let marker = GMSMarker(position: position)
marker.icon = HFAsset.ic_p_pin_orange.image
let userData = model
let item = POIItem(position: position, marker: marker, userData: userData)
self.clusterManager.add(item)
self.setCurrentPin(zoomLevel: 14.0)
}
}
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var userData: AnyObject!
@objc var marker: GMSMarker!
init(position: CLLocationCoordinate2D, marker: GMSMarker, userData: AnyObject) {
self.position = position
self.marker = marker
self.userData = userData
}
}
class CustomRendererMarkers: GMUDefaultClusterRenderer {
var mapView:GMSMapView?
let kGMUAnimationDuration: Double = 0.5
override init(mapView: GMSMapView, clusterIconGenerator iconGenerator: GMUClusterIconGenerator) {
super.init(mapView: mapView, clusterIconGenerator: iconGenerator)
}
func markerWithPosition(position: CLLocationCoordinate2D, from: CLLocationCoordinate2D, userData: AnyObject, clusterIcon: UIImage, animated: Bool) -> GMSMarker {
let initialPosition = animated ? from : position
let marker = GMSMarker(position: initialPosition)
marker.userData! = userData
if clusterIcon.cgImage != nil {
marker.icon = clusterIcon
}
else {
marker.icon = self.getCustomTitleItem(userData: userData)
}
marker.map = mapView
if animated
{
CATransaction.begin()
CAAnimation.init().duration = kGMUAnimationDuration
marker.layer.latitude = position.latitude
marker.layer.longitude = position.longitude
CATransaction.commit()
}
return marker
}
func getCustomTitleItem(userData: AnyObject) -> UIImage {
let item = userData as! POIItem
return item.marker.icon!
}
}
class CustomClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: (String(size) as NSString) as String,
inImage: HFAsset.ic_parking_clustering.image,
font: UIFont.init(name: "Montserrat-Medium", size: 12.0)!)
return image
}
private func textToImage(drawText text: String, inImage image: UIImage, font: UIFont) -> UIImage {
var pinCount = text
if Int(text)! > 9999 {
pinCount = "+9999"
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.white
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.backgroundColor: appThemeColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/3
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
pinCount.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if markerPin == marker {
return true
}
if ((marker.userData as? GMUStaticCluster) != nil) { // Cluster Pin tap
UIView.animate(withDuration: 0.5, delay: 0.2, options: [.curveEaseOut],
animations: {
let newCamera = GMSCameraPosition.camera(withTarget: marker.position,
zoom: self.mapView.camera.zoom + 0.8)
let update = GMSCameraUpdate.setCamera(newCamera)
self.mapView.animate(with: update)
}, completion: {
finished in
})
}
if let poiItem = marker.userData as? POIItem { // Cluster Parking Pin tap
let Detail = self.storyboard?.instantiateViewController(withIdentifier: "HFParkingFullDetailsVC")as! HFParkingFullDetailsVC
Detail.parkModel = (poiItem.userData as? AMParkModel)!
self.navigationController?.pushViewController(Detail, animated: true)
}
2:
class HFDashBordVC: UIViewController,GMUClusterManagerDelegate,GMSMapViewDelegate{
private var clusterManager: GMUClusterManager!
var cameraPosition = GMSCameraPosition()
var markerPin = GMSMarker()
var currentLocationCircle = GMSCircle()
var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var zoomLevel: Float = 18.0
@IBOutlet var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupClustering()
}
func setupClustering() {
let iconGenerator = CustomClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = CustomRendererMarkers(mapView: mapView,
clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
}
private func setClusterParkingPin() {
clusterManager.clearItems()
for object in AppUtilites.sharedInstance.safeParkingArray {
let model = object as! AMParkModel
let lat = Double(model.latitude)!
let lng = Double(model.longitude)!
let position = CLLocationCoordinate2DMake(lat, lng)
let marker = GMSMarker(position: position)
marker.icon = HFAsset.ic_p_pin_orange.image
let userData = model
let item = POIItem(position: position, marker: marker, userData: userData)
self.clusterManager.add(item)
self.setCurrentPin(zoomLevel: 14.0)
}
}
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var userData: AnyObject!
@objc var marker: GMSMarker!
init(position: CLLocationCoordinate2D, marker: GMSMarker, userData: AnyObject) {
self.position = position
self.marker = marker
self.userData = userData
}
}
class CustomRendererMarkers: GMUDefaultClusterRenderer {
var mapView:GMSMapView?
let kGMUAnimationDuration: Double = 0.5
override init(mapView: GMSMapView, clusterIconGenerator iconGenerator: GMUClusterIconGenerator) {
super.init(mapView: mapView, clusterIconGenerator: iconGenerator)
}
func markerWithPosition(position: CLLocationCoordinate2D, from: CLLocationCoordinate2D, userData: AnyObject, clusterIcon: UIImage, animated: Bool) -> GMSMarker {
let initialPosition = animated ? from : position
let marker = GMSMarker(position: initialPosition)
marker.userData! = userData
if clusterIcon.cgImage != nil {
marker.icon = clusterIcon
}
else {
marker.icon = self.getCustomTitleItem(userData: userData)
}
marker.map = mapView
if animated
{
CATransaction.begin()
CAAnimation.init().duration = kGMUAnimationDuration
marker.layer.latitude = position.latitude
marker.layer.longitude = position.longitude
CATransaction.commit()
}
return marker
}
func getCustomTitleItem(userData: AnyObject) -> UIImage {
let item = userData as! POIItem
return item.marker.icon!
}
}
class CustomClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: (String(size) as NSString) as String,
inImage: HFAsset.ic_parking_clustering.image,
font: UIFont.init(name: "Montserrat-Medium", size: 12.0)!)
return image
}
private func textToImage(drawText text: String, inImage image: UIImage, font: UIFont) -> UIImage {
var pinCount = text
if Int(text)! > 9999 {
pinCount = "+9999"
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.white
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.backgroundColor: appThemeColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/3
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
pinCount.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if markerPin == marker {
return true
}
if ((marker.userData as? GMUStaticCluster) != nil) { // Cluster Pin tap
UIView.animate(withDuration: 0.5, delay: 0.2, options: [.curveEaseOut],
animations: {
let newCamera = GMSCameraPosition.camera(withTarget: marker.position,
zoom: self.mapView.camera.zoom + 0.8)
let update = GMSCameraUpdate.setCamera(newCamera)
self.mapView.animate(with: update)
}, completion: {
finished in
})
}
if let poiItem = marker.userData as? POIItem { // Cluster Parking Pin tap
let Detail = self.storyboard?.instantiateViewController(withIdentifier: "HFParkingFullDetailsVC")as! HFParkingFullDetailsVC
Detail.parkModel = (poiItem.userData as? AMParkModel)!
self.navigationController?.pushViewController(Detail, animated: true)
}
3:
class HFDashBordVC: UIViewController,GMUClusterManagerDelegate,GMSMapViewDelegate{
private var clusterManager: GMUClusterManager!
var cameraPosition = GMSCameraPosition()
var markerPin = GMSMarker()
var currentLocationCircle = GMSCircle()
var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var zoomLevel: Float = 18.0
@IBOutlet var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupClustering()
}
func setupClustering() {
let iconGenerator = CustomClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = CustomRendererMarkers(mapView: mapView,
clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
}
private func setClusterParkingPin() {
clusterManager.clearItems()
for object in AppUtilites.sharedInstance.safeParkingArray {
let model = object as! AMParkModel
let lat = Double(model.latitude)!
let lng = Double(model.longitude)!
let position = CLLocationCoordinate2DMake(lat, lng)
let marker = GMSMarker(position: position)
marker.icon = HFAsset.ic_p_pin_orange.image
let userData = model
let item = POIItem(position: position, marker: marker, userData: userData)
self.clusterManager.add(item)
self.setCurrentPin(zoomLevel: 14.0)
}
}
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var userData: AnyObject!
@objc var marker: GMSMarker!
init(position: CLLocationCoordinate2D, marker: GMSMarker, userData: AnyObject) {
self.position = position
self.marker = marker
self.userData = userData
}
}
class CustomRendererMarkers: GMUDefaultClusterRenderer {
var mapView:GMSMapView?
let kGMUAnimationDuration: Double = 0.5
override init(mapView: GMSMapView, clusterIconGenerator iconGenerator: GMUClusterIconGenerator) {
super.init(mapView: mapView, clusterIconGenerator: iconGenerator)
}
func markerWithPosition(position: CLLocationCoordinate2D, from: CLLocationCoordinate2D, userData: AnyObject, clusterIcon: UIImage, animated: Bool) -> GMSMarker {
let initialPosition = animated ? from : position
let marker = GMSMarker(position: initialPosition)
marker.userData! = userData
if clusterIcon.cgImage != nil {
marker.icon = clusterIcon
}
else {
marker.icon = self.getCustomTitleItem(userData: userData)
}
marker.map = mapView
if animated
{
CATransaction.begin()
CAAnimation.init().duration = kGMUAnimationDuration
marker.layer.latitude = position.latitude
marker.layer.longitude = position.longitude
CATransaction.commit()
}
return marker
}
func getCustomTitleItem(userData: AnyObject) -> UIImage {
let item = userData as! POIItem
return item.marker.icon!
}
}
class CustomClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: (String(size) as NSString) as String,
inImage: HFAsset.ic_parking_clustering.image,
font: UIFont.init(name: "Montserrat-Medium", size: 12.0)!)
return image
}
private func textToImage(drawText text: String, inImage image: UIImage, font: UIFont) -> UIImage {
var pinCount = text
if Int(text)! > 9999 {
pinCount = "+9999"
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.white
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.backgroundColor: appThemeColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/3
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
pinCount.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if markerPin == marker {
return true
}
if ((marker.userData as? GMUStaticCluster) != nil) { // Cluster Pin tap
UIView.animate(withDuration: 0.5, delay: 0.2, options: [.curveEaseOut],
animations: {
let newCamera = GMSCameraPosition.camera(withTarget: marker.position,
zoom: self.mapView.camera.zoom + 0.8)
let update = GMSCameraUpdate.setCamera(newCamera)
self.mapView.animate(with: update)
}, completion: {
finished in
})
}
if let poiItem = marker.userData as? POIItem { // Cluster Parking Pin tap
let Detail = self.storyboard?.instantiateViewController(withIdentifier: "HFParkingFullDetailsVC")as! HFParkingFullDetailsVC
Detail.parkModel = (poiItem.userData as? AMParkModel)!
self.navigationController?.pushViewController(Detail, animated: true)
}
4:
class HFDashBordVC: UIViewController,GMUClusterManagerDelegate,GMSMapViewDelegate{
private var clusterManager: GMUClusterManager!
var cameraPosition = GMSCameraPosition()
var markerPin = GMSMarker()
var currentLocationCircle = GMSCircle()
var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var zoomLevel: Float = 18.0
@IBOutlet var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupClustering()
}
func setupClustering() {
let iconGenerator = CustomClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = CustomRendererMarkers(mapView: mapView,
clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
}
private func setClusterParkingPin() {
clusterManager.clearItems()
for object in AppUtilites.sharedInstance.safeParkingArray {
let model = object as! AMParkModel
let lat = Double(model.latitude)!
let lng = Double(model.longitude)!
let position = CLLocationCoordinate2DMake(lat, lng)
let marker = GMSMarker(position: position)
marker.icon = HFAsset.ic_p_pin_orange.image
let userData = model
let item = POIItem(position: position, marker: marker, userData: userData)
self.clusterManager.add(item)
self.setCurrentPin(zoomLevel: 14.0)
}
}
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var userData: AnyObject!
@objc var marker: GMSMarker!
init(position: CLLocationCoordinate2D, marker: GMSMarker, userData: AnyObject) {
self.position = position
self.marker = marker
self.userData = userData
}
}
class CustomRendererMarkers: GMUDefaultClusterRenderer {
var mapView:GMSMapView?
let kGMUAnimationDuration: Double = 0.5
override init(mapView: GMSMapView, clusterIconGenerator iconGenerator: GMUClusterIconGenerator) {
super.init(mapView: mapView, clusterIconGenerator: iconGenerator)
}
func markerWithPosition(position: CLLocationCoordinate2D, from: CLLocationCoordinate2D, userData: AnyObject, clusterIcon: UIImage, animated: Bool) -> GMSMarker {
let initialPosition = animated ? from : position
let marker = GMSMarker(position: initialPosition)
marker.userData! = userData
if clusterIcon.cgImage != nil {
marker.icon = clusterIcon
}
else {
marker.icon = self.getCustomTitleItem(userData: userData)
}
marker.map = mapView
if animated
{
CATransaction.begin()
CAAnimation.init().duration = kGMUAnimationDuration
marker.layer.latitude = position.latitude
marker.layer.longitude = position.longitude
CATransaction.commit()
}
return marker
}
func getCustomTitleItem(userData: AnyObject) -> UIImage {
let item = userData as! POIItem
return item.marker.icon!
}
}
class CustomClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: (String(size) as NSString) as String,
inImage: HFAsset.ic_parking_clustering.image,
font: UIFont.init(name: "Montserrat-Medium", size: 12.0)!)
return image
}
private func textToImage(drawText text: String, inImage image: UIImage, font: UIFont) -> UIImage {
var pinCount = text
if Int(text)! > 9999 {
pinCount = "+9999"
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.white
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.backgroundColor: appThemeColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/3
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
pinCount.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if markerPin == marker {
return true
}
if ((marker.userData as? GMUStaticCluster) != nil) { // Cluster Pin tap
UIView.animate(withDuration: 0.5, delay: 0.2, options: [.curveEaseOut],
animations: {
let newCamera = GMSCameraPosition.camera(withTarget: marker.position,
zoom: self.mapView.camera.zoom + 0.8)
let update = GMSCameraUpdate.setCamera(newCamera)
self.mapView.animate(with: update)
}, completion: {
finished in
})
}
if let poiItem = marker.userData as? POIItem { // Cluster Parking Pin tap
let Detail = self.storyboard?.instantiateViewController(withIdentifier: "HFParkingFullDetailsVC")as! HFParkingFullDetailsVC
Detail.parkModel = (poiItem.userData as? AMParkModel)!
self.navigationController?.pushViewController(Detail, animated: true)
}
5:
class HFDashBordVC: UIViewController,GMUClusterManagerDelegate,GMSMapViewDelegate{
private var clusterManager: GMUClusterManager!
var cameraPosition = GMSCameraPosition()
var markerPin = GMSMarker()
var currentLocationCircle = GMSCircle()
var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var zoomLevel: Float = 18.0
@IBOutlet var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupClustering()
}
func setupClustering() {
let iconGenerator = CustomClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = CustomRendererMarkers(mapView: mapView,
clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
}
private func setClusterParkingPin() {
clusterManager.clearItems()
for object in AppUtilites.sharedInstance.safeParkingArray {
let model = object as! AMParkModel
let lat = Double(model.latitude)!
let lng = Double(model.longitude)!
let position = CLLocationCoordinate2DMake(lat, lng)
let marker = GMSMarker(position: position)
marker.icon = HFAsset.ic_p_pin_orange.image
let userData = model
let item = POIItem(position: position, marker: marker, userData: userData)
self.clusterManager.add(item)
self.setCurrentPin(zoomLevel: 14.0)
}
}
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var userData: AnyObject!
@objc var marker: GMSMarker!
init(position: CLLocationCoordinate2D, marker: GMSMarker, userData: AnyObject) {
self.position = position
self.marker = marker
self.userData = userData
}
}
class CustomRendererMarkers: GMUDefaultClusterRenderer {
var mapView:GMSMapView?
let kGMUAnimationDuration: Double = 0.5
override init(mapView: GMSMapView, clusterIconGenerator iconGenerator: GMUClusterIconGenerator) {
super.init(mapView: mapView, clusterIconGenerator: iconGenerator)
}
func markerWithPosition(position: CLLocationCoordinate2D, from: CLLocationCoordinate2D, userData: AnyObject, clusterIcon: UIImage, animated: Bool) -> GMSMarker {
let initialPosition = animated ? from : position
let marker = GMSMarker(position: initialPosition)
marker.userData! = userData
if clusterIcon.cgImage != nil {
marker.icon = clusterIcon
}
else {
marker.icon = self.getCustomTitleItem(userData: userData)
}
marker.map = mapView
if animated
{
CATransaction.begin()
CAAnimation.init().duration = kGMUAnimationDuration
marker.layer.latitude = position.latitude
marker.layer.longitude = position.longitude
CATransaction.commit()
}
return marker
}
func getCustomTitleItem(userData: AnyObject) -> UIImage {
let item = userData as! POIItem
return item.marker.icon!
}
}
class CustomClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: (String(size) as NSString) as String,
inImage: HFAsset.ic_parking_clustering.image,
font: UIFont.init(name: "Montserrat-Medium", size: 12.0)!)
return image
}
private func textToImage(drawText text: String, inImage image: UIImage, font: UIFont) -> UIImage {
var pinCount = text
if Int(text)! > 9999 {
pinCount = "+9999"
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.white
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.backgroundColor: appThemeColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/3
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
pinCount.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if markerPin == marker {
return true
}
if ((marker.userData as? GMUStaticCluster) != nil) { // Cluster Pin tap
UIView.animate(withDuration: 0.5, delay: 0.2, options: [.curveEaseOut],
animations: {
let newCamera = GMSCameraPosition.camera(withTarget: marker.position,
zoom: self.mapView.camera.zoom + 0.8)
let update = GMSCameraUpdate.setCamera(newCamera)
self.mapView.animate(with: update)
}, completion: {
finished in
})
}
if let poiItem = marker.userData as? POIItem { // Cluster Parking Pin tap
let Detail = self.storyboard?.instantiateViewController(withIdentifier: "HFParkingFullDetailsVC")as! HFParkingFullDetailsVC
Detail.parkModel = (poiItem.userData as? AMParkModel)!
self.navigationController?.pushViewController(Detail, animated: true)
}
如果您只需要更改图标或颜色,则可以在初始化GmudeFaultClusterCongenerator时添加具有多种颜色/图像的存储桶(或者,如果您只需要一种颜色,则仅添加一个存储桶,如下例所示)。我使用了一个较大的数字(高于集群项目的最大数量),以便所有集群都具有相同的颜色。要使用多种颜色,可以添加多个桶和多种颜色
let iconGenerator = GMUDefaultClusterIconGenerator.init(buckets: [99999], backgroundColors: [UIColor.red])
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: googleMapView, clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: googleMapView, algorithm: algorithm, renderer: renderer)
clusterManager.setDelegate(self, mapDelegate: self)
要使用图像作为群集背景,您可以为存储桶提供一组背景图像:
let iconGenerator = GMUDefaultClusterIconGenerator.init(buckets: [99999], backgroundImages: [UIImage(named: "YOUR_IMAGE_HERE")!])
你需要展示你的尝试。我喜欢你的解决方案,它适用于Swift 3,但现在在Swift 4中,你得到了一个“隐式Objective-C入口点,在声明中添加显式'@objc'以在Swift 4中发出Objective-C入口点”。你们找到另一个解决方法了吗?在poitem类中,只需在“var marker”前面添加@objc,我就编辑了这个解决方案。很抱歉回复太晚。谢谢您的回复。谢谢,它很有效!!!由于某种原因,唯一不起作用的是,当我点击集群时,它崩溃了,而不是放大。过时了,现在检查一下