Skip to content

Instantly share code, notes, and snippets.

@johnnewman
Last active January 13, 2020 21:18
Show Gist options
  • Save johnnewman/d69b5c28c9f8d0895f9bb5e36eb1baeb to your computer and use it in GitHub Desktop.
Save johnnewman/d69b5c28c9f8d0895f9bb5e36eb1baeb to your computer and use it in GitHub Desktop.
Code exhibiting a sorting issue with MGLSymbolStyleLayer
//
// IconSortViewController.swift
// IconOrdering
//
// Created by John Newman on 11/18/19.
// Copyright © 2019 Roadtrippers. All rights reserved.
//
import UIKit
import Mapbox
class IconSortViewController: UIViewController {
private var map: MGLMapView?
override func viewDidLoad() {
super.viewDidLoad()
let map = MGLMapView(frame: view.bounds)
map.delegate = self
map.debugMask = MGLMapDebugMaskOptions(rawValue: MGLMapDebugMaskOptions.collisionBoxesMask.rawValue)
map.setCenter(CLLocationCoordinate2D(latitude: 38.1399, longitude: -112.1284), zoomLevel: 13, animated: false)
view.addSubview(map)
self.map = map
}
private func testShape() -> MGLShapeCollectionFeature {
// Trying to draw the red icon on top.
let redSort = 0.99999898
let blueSort = 0.99999896
if redSort > blueSort {
print("red sort > blue sort")
}
let featureDict: [String: Any] = ["type": "FeatureCollection",
"features": [["type":"Feature",
"geometry": ["type":"Point",
"coordinates":[-112.1284,38.1399]],
"properties":["text":"Red",
"icon":"red_circle",
"sort":redSort]],
["type":"Feature",
"geometry": ["type":"Point",
"coordinates":[-112.1274,38.1399]],
"properties":["text":"Blue",
"icon":"blue_circle",
"sort":blueSort]]]]
let data = try! JSONSerialization.data(withJSONObject: featureDict, options: [])
let shape = try! MGLShape(data: data, encoding: String.Encoding.utf8.rawValue) as! MGLShapeCollectionFeature
return shape
}
private func drawShapes() {
let source = MGLShapeSource(identifier: "my-source", shape: testShape(), options: nil)
let layer = MGLSymbolStyleLayer(identifier: "my-layer", source: source)
layer.iconAllowsOverlap = NSExpression(forConstantValue: false) // Flipping to true fixes the issue.
layer.textAllowsOverlap = NSExpression(forConstantValue: false)
layer.textOptional = NSExpression(forConstantValue: true)
layer.text = NSExpression(forKeyPath: "text")
layer.iconImageName = NSExpression(forKeyPath: "icon")
layer.textOffset = NSExpression(forConstantValue: NSValue(cgVector: CGVector.init(dx: 2, dy: 0)))
layer.symbolSortKey = symbolSortKeyExpression()
map!.style!.addSource(source)
map!.style!.addLayer(layer)
}
// When using floats, reversing the order doesn't change the outcome.
private func symbolSortKeyExpression() -> NSExpression {
return NSExpression(forKeyPath: "sort")
// return NSExpression(forFunction: "multiply:by:", arguments: [NSExpression(forKeyPath: "sort"), NSExpression(forConstantValue: -1)])
}
}
extension IconSortViewController : MGLMapViewDelegate {
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
let iconRect = CGRect(x: 0, y: 0, width: 30, height: 30)
let renderer = UIGraphicsImageRenderer(size: iconRect.size)
let red = renderer.image { (context) in
UIColor.white.setFill()
context.cgContext.fillEllipse(in: iconRect)
UIColor.red.setFill()
context.cgContext.fillEllipse(in: iconRect.insetBy(dx: 2, dy: 2))
}
let blue = renderer.image { (context) in
UIColor.white.setFill()
context.cgContext.fillEllipse(in: iconRect)
UIColor.blue.setFill()
context.cgContext.fillEllipse(in: iconRect.insetBy(dx: 2, dy: 2))
}
style.setImage(red, forName: "red_circle")
style.setImage(blue, forName: "blue_circle")
drawShapes()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment