Comments (18)
MKCoordinateRegion is not defined in this package but rather in MapKit - so you will need to put import MapKit
at the top of the file to use MapKit-defined APIs. We might want to change this in the future though, since it would make sense to simply re-export the MapKit interface as well.
from map.
Thank you for the quick reply. It would be good to update the example code given in REEDME as this does not show importing Mapkit.
Kind regards, ahartman, belgium
from map.
Dear Paul,
I am struggling with two things and I am not very good in reading code to find how to use it:
- I want to draw 3 concentric circles with different radiuses and colours from the center of the map but I cannot adapt the overlay example code to work. Can you help a bit here?
- I also wanted to use MapZoomControl to enable zooming on my Mac; however, I get an error: "Cannot find 'MapZoomControl' in scope" in the code below:
var body: some View {
Map(coordinateRegion: $region,
annotationItems: mainModel.mapElementLines,
annotationContent: {
mapLocation in
MapPin(coordinate: mapLocation.coordinate!, tint: mapLocation.color)}
)
.mapKey(1)
.overlay(alignment: .topLeading) {
MapZoomControl(key: 1)
}
}
Any ideas?
Kind regards, ahartman, belgium
from map.
Hey, sorry for responding so late.
- If they should only be on top of the map regardless of coordinates, please simply use SwiftUI's overlay functionality.
For coordinate-fixed circles, you may want to use the following example:
struct MapOverlayCircle: Identifiable {
let id = UUID()
let center: CLLocationCoordinate2D
let radius: CLLocationDistance
let strokeColor: Color
}
struct MyMapView: View {
@State private var overlays = [
MapOverlayCircle(...),
MapOverlayCircle(...),
]
@State private var region = MKCoordinateRegion()
var body: some View {
Map(
coordinateRegion: $region,
overlayItems: overlays
) { overlay in
MapCircle(center: overlay.center, radius: overlay.radius, strokeColor: overlay.strokeColor)
}
}
}
This example will draw two circles on the map (the initializers would need to be filled instead of the ellipsis (...) of course).
For more customization, you might want to have a deeper look into MapCircle initializers.
- MapZoomControl is only available on Mac - maybe you try to build the app for an iOS target and then it fails?
For these cases, please make sure that MapZoomControl is only referenced in macOS code, for example using the following precompiler directives:
Map(
coordinateRegion: $region,
annotationItems: mainModel.mapElementLines
) { mapLocation in
MapPin(coordinate: mapLocation.coordinate!, tint: mapLocation.color)}
)
.mapKey(1)
if os(macOS)
.overlay(alignment: .topLeading) {
MapZoomControl(key: 1)
}
#endif
from map.
Paul,
Better a later answer than no answer, thank you for getting back to me.
I got your overlay example to work. However, I have no idea how to combine annotations AND circles on one map.
The code below of course displays two maps and I want to pins and the circles the same map.
The MapZoomControl is not visible with your code.
import SwiftUI
import MapKit
import Map
struct PatientsPinsCirclesView: View {
static var home = CLLocationCoordinate2D(latitude: 51.35988, longitude: 4.48369)
@EnvironmentObject var model: MainModel
@State private var region = MKCoordinateRegion(
center: home,
span: MKCoordinateSpan(latitudeDelta: 0.6, longitudeDelta: 0.6)
)
@State private var overlays = [
MapOverlayCircle(center: home, radius: 5000.0, strokeColor: .blue),
MapOverlayCircle(center: home, radius: 10000.0, strokeColor: .green),
MapOverlayCircle(center: home, radius: 15000.0, strokeColor: .red)
]
var body: some View {
VStack {
Map(coordinateRegion: $region,
annotationItems: model.mapPins,
annotationContent: {
mapPin in
MapPin(coordinate: mapPin.coordinate, tint: mapPin.color)
}
)
Map(coordinateRegion: $region,
overlayItems: overlays) {
overlay in
MapCircle(center: overlay.center, radius: overlay.radius, strokeColor: UIColor(overlay.strokeColor))
}
.mapKey(1)
#if os(macOS)
.overlay(alignment: .topLeading) {
MapZoomControl(key: 1)
}
#endif
}
}
}
struct PatientsPinsCirclesView_Previews: PreviewProvider {
static var previews: some View {
PatientsPinsCirclesView()
}
}
struct MapOverlayCircle: Identifiable {
let id = UUID()
let center: CLLocationCoordinate2D
let radius: CLLocationDistance
let strokeColor: Color
}
from map.
You can provide overlays and annotations in the same initializer of a map
var body: some View {
Map(
coordinateRegion: $region,
annotationItems: model.mapPins,
annotationContent: { mapPin in
MapPin(coordinate: mapPin.coordinate, tint: mapPin.color)
},
overlayItems: overlays,
overlayContent: { overlay in
MapCircle(center: overlay.center, radius: overlay.radius, strokeColor: UIColor(overlay.strokeColor))
}
)
.mapKey(1)
#if os(macOS)
.overlay(alignment: .topLeading) {
MapZoomControl(key: 1)
}
#endif
}
Does that work for you? 😊
from map.
Paul,
Yes, that works. I tried the same thing but got weird errors. By comparing yours with mine, I found one single stupid typo!
As for the MapZoomControl, I develop for Mac Catalyst, and I presume Catalyst does not qualify as MacOS. That is a pity but I can zoom with double-click and alt-double-click.
Thanks for now and I follow you for updates in your package, good work.
I would be very interested in a solution for clustering annotations; the examples that I find, are old and I cannot came these work.
Regards, André Hartman
from map.
There is unfortunately no such functionality from MapKit, you can however show the current zoom status by setting the informationVisbility
to include MapInformationVisbility.scale
- you can do this for example like this:
var body: some View {
Map(
coordinateRegion: $region,
informationVisibility: .default.union(.scale), // You can also try other values such as `.all` to show all kinds of information
annotationItems: model.mapPins,
annotationContent: { mapPin in
MapPin(coordinate: mapPin.coordinate, tint: mapPin.color)
},
overlayItems: overlays,
overlayContent: { overlay in
MapCircle(center: overlay.center, radius: overlay.radius, strokeColor: UIColor(overlay.strokeColor))
}
)
.mapKey(1)
#if os(macOS)
.overlay(alignment: .topLeading) {
MapZoomControl(key: 1)
}
#endif
}
Edit: Ah, I just noticed, that there should actually be support for macCatalyst - I will have a look into this - thank you for bringing it up!
from map.
Paul,
According to Apple documentation, there is something like Annotation Declustering, but it very dense for me.
Look at:
https://developer.apple.com/documentation/mapkit/mkannotationview/decluttering_a_map_with_mapkit_annotation_clustering
There are examples on Internet as well, but they are old and I can't transform these to SwiftUI.
Regards, André Hartman
from map.
#32 should make MapZoomControl and MapPitchControl available for macCatalyst - have you found anything else that doesn't seem to be available for macCatalyst but actually should be?
from map.
Yes, annotation clustering should be available, I agree, I just haven't found the time nor great ideas to implement it yet. If you happen to have an idea or suggestion, feel free to open another issue or pull request 😊
from map.
According to Apple documentation, there is something like Annotation Declustering, but it very dense for me. Look at: https://developer.apple.com/documentation/mapkit/mkannotationview/decluttering_a_map_with_mapkit_annotation_clustering
Thank you for that link - unfortunately, I cannot implement this right now, but I will try to find some time in the coming weeks.
from map.
Paul,
Please find my code below as as a screen image of the result.
My wife has a psychology practice and the map shows where patients come from in distance from the practice.
import Map
import MapKit
import SwiftUI
struct PatientsPinsView: View {
@EnvironmentObject var model: MainModel
var body: some View {
ZStack {
doMapView()
doLegend()
}
.navigationBarTitleDisplayMode(.inline)
.statusBar(hidden: true)
}
}
struct doMapView: View {
@EnvironmentObject var model: MainModel
static var home = CLLocationCoordinate2D(latitude: 51.35988, longitude: 4.48369)
@State var region = MKCoordinateRegion(
center: home,
latitudinalMeters: 40000.0, longitudinalMeters: 40000.0
)
var body: some View {
VStack {
Map(
coordinateRegion: $region,
annotationItems: model.mapPins,
annotationContent: { element in
MapPin(coordinate: element.coordinate, tint: element.color)
},
overlayItems: getCircles(),
overlayContent: { element in
MapCircle(
center: element.center,
radius: element.radius,
lineWidth: 3,
strokeColor: UIColor(element.strokeColor)
)
}
)
}
}
func getCircles() -> [MapOverlayCircle] {
return [
MapOverlayCircle(center: doMapView.home, radius: 5000.0, strokeColor: .blue),
MapOverlayCircle(center: doMapView.home, radius: 10000.0, strokeColor: .green),
MapOverlayCircle(center: doMapView.home, radius: 15000.0, strokeColor: .red)
]
}
}
struct doLegend: View {
@EnvironmentObject var model: MainModel
let columns = [GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80))]
var body: some View {
VStack {
HStack {
Spacer()
LazyVGrid(columns: columns) {
Text("Afstand")
.underline()
Text("Aantal")
.underline()
Text("Procent")
.underline()
ForEach(model.mapLegend, id: \.self) { legend in
Text(legend.distance)
Text(legend.count)
Text(legend.percentage)
}
}
.border(.black)
.background(Color.white.opacity(0.7))
.padding([.trailing], 50)
.padding([.top], 20)
.frame(maxWidth: 240)
}
Spacer()
}
}
}
struct MapOverlayCircle: Identifiable {
let id = UUID()
let center: CLLocationCoordinate2D
let radius: CLLocationDistance
let strokeColor: Color
}
struct PatientsPinsView_Previews: PreviewProvider {
static var previews: some View {
PatientsPinsView()
}
}
I also have an earlier version the the map window with MapKit and UIViewRepresentable.
In that window I add the markers not in a closure but in a single statement as an array. It is however the next statement that is important; that statement scales the map automatically so that all makers are displayed.
view.addAnnotations(model.mapMarkers)
view.showAnnotations(view.annotations, animated: true)
The image below shows the result and you can observe a marker in 'Arendonk' on the right hand side that is not in the previous image because that has a fixed scale.
Is there a way to do that automatic scaling in your package as well?
Regards, André Hartman
from map.
Sure, okay, I have a couple (small) remarks:
-
Please make sure to have the circles wrapped in
@State
- otherwise the overlays will be regenerated all the times, since the uuids will change. -
There is no such functionality to call this show-method - but you could write a method to center the map accordingly.
Let me give you a helper method that might be of help:
extension MKCoordinateRegion {
convenience init(containing coordinates: [CLLocationCoordinate2D], multiplyingSpanBy spanFactor: Double = 1) {
guard let minLatitude = coordinates.map(\.latitude).min(),
let maxLatitude = coordinates.map(\.latitude).max(),
let minLongitude = coordinates.map(\.longitude).min(),
let maxLongitude = coordinates.map(\.longitude).max() else {
self.init()
return
}
let latitudeDelta = (maxLatitude - minLatitude) * spanFactor // The spanFactor allows you to show a bit more than only the coordinates, e.g. put in `1.5` to see a bit more map than you would actually need to fit the coordinates
let longitudeDelta = (maxLongitude - minLongitude) * spanFactor
self.init(
center: CLLocationCoordinate2D(
latitude: minLatitude + (latitudeDelta / 2),
longitude: minLongitude + (longitudeDelta / 2)
),
span: MKCoordinateSpan(
latitudeDelta: latitudeDelta,
longitudeDelta: longitudeDelta
)
)
}
}
Warning: This will only work, if the coordinates are not close to the Pacific (which I assume is the case here). An issue would arise, if you had one coordinate in California and one in Japan for example, since the average of their longitudes would be somewhere in Europe, which makes no sense. You would need to use trigonometric functions then to compute the average, which I skipped here.
You can then set your region in an onAppear
/ task
modifier, like this:
@State private var region = MKCoordinateRegion()
var body: some View {
Map(...)
.task { region = MKCoordinateRegion(containing: model.mapPins.map(\.coordinate), multiplyingSpanBy: 1.5) }
}
If you need to have this rescaling on every change of the mapPins property, you can use the onChange
view modifier instead. If you wrap that assignment of region
in a withAnimation
, you should also get an animation.
from map.
Paul,
Thank you for the Helper, that works.
I moved the helper code to my logic and added a centerPin to check correct working
However, I see 2 weird things in the map.
- I use 4 objects, mapPins for the window with Map, mapMarkers for a window with MapKit, mapRegion and mapLegend. You would think both windows would draw the same mapRegion the same but that is not true. it looks like the MapKit window applies padding outside the MKCoordinateregion.
- Setting the spanFactor above 1.0 did not work correctly, it shifts the map to the left. I corrected your calculation and it is now OK.
Your calculation:
let latitudeDelta = (maxLatitude - minLatitude) * spanFactor
let longitudeDelta = (maxLongitude - minLongitude) * spanFactor
self.init(
center: CLLocationCoordinate2D(
latitude: minLatitude + (latitudeDelta / 2),
longitude: minLongitude + (longitudeDelta / 2)
),
span: MKCoordinateSpan(
latitudeDelta: latitudeDelta,
longitudeDelta: longitudeDelta
)
)
My correction:
let spanFactor = 1.25
let latitudeDelta = (maxLatitude - minLatitude) * spanFactor
let longitudeDelta = (maxLongitude - minLongitude) * spanFactor
let localRegion = MKCoordinateRegion(
center: CLLocationCoordinate2D(
latitude: minLatitude + (maxLatitude - minLatitude)/2.0,
longitude: minLongitude + (maxLongitude - minLongitude)/2.0
),
span: MKCoordinateSpan(
latitudeDelta: latitudeDelta,
longitudeDelta: longitudeDelta
)
)
Image 1 is the Map window with spanFactor at 1.0.
Image 2 is the MapKit window with spanFactor at 1.0. please observe that it shows a little more.
Image 3 is the Map window with spanFactor at 1.25. The extra room is completely on the right hand side of the map.
Image 4 is the Map window with spanFactor at 1.25 and the corrected calculation.
Regards, André Hartman
from map.
Paul,
Please find my code. below:
Map window:
import Map
import MapKit
import SwiftUI
struct PatientsPinsView: View {
var body: some View {
ZStack {
doMapView()
doLegend()
}
.navigationBarTitleDisplayMode(.inline)
.statusBar(hidden: true)
}
}
struct doMapView: View {
@EnvironmentObject var model: MainModel
let home = CLLocationCoordinate2D(latitude: 51.35988, longitude: 4.48369)
var body: some View {
VStack {
Map(
coordinateRegion: $model.mapRegion,
annotationItems: model.mapPins,
annotationContent: { element in
MapPin(coordinate: element.coordinate, tint: element.color)
},
overlayItems: getCircles(),
overlayContent: { element in
MapCircle(
center: element.center,
radius: element.radius,
lineWidth: 3,
strokeColor: UIColor(element.strokeColor)
)
}
)
}
}
func getCircles() -> [MapOverlayCircle] {
return [
MapOverlayCircle(center: model.home, radius: 5000.0, strokeColor: .blue),
MapOverlayCircle(center: model.home, radius: 10000.0, strokeColor: .green),
MapOverlayCircle(center: model.home, radius: 15000.0, strokeColor: .red)
]
}
}
struct doLegend: View {
@EnvironmentObject var model: MainModel
let columns = [GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80))]
var body: some View {
VStack {
HStack {
Spacer()
LazyVGrid(columns: columns) {
Text("Afstand")
.underline()
Text("Aantal")
.underline()
Text("Procent")
.underline()
ForEach(model.mapLegend, id: \.self) { legend in
Text(legend.distance)
Text(legend.count)
Text(legend.percentage)
}
}
.border(.black)
.background(Color.white.opacity(0.7))
.padding([.trailing], 50)
.padding([.top], 20)
.frame(maxWidth: 240)
}
Spacer()
}
}
}
struct MapOverlayCircle: Identifiable {
let id = UUID()
let center: CLLocationCoordinate2D
let radius: CLLocationDistance
let strokeColor: Color
}
struct PatientsPinsView_Previews: PreviewProvider {
static var previews: some View {
PatientsPinsView()
}
}
MapKit window
import MapKit
import SwiftUI
struct PatientsMarkersView: View {
var body: some View {
ZStack {
provideMapView()
}
.navigationBarTitleDisplayMode(.inline)
.statusBar(hidden: true)
}
}
struct provideMapView: UIViewRepresentable {
@EnvironmentObject var model: MainModel
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView(frame: UIScreen.main.bounds)
mapView.delegate = context.coordinator
mapView.setRegion(model.mapRegion, animated: true)
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
for (index, count) in model.mapLegend.enumerated() {
if index < model.mapLegend.endIndex - 1 {
let circle = MKCircle(center: model.home, radius: count.roundedDistance)
view.addOverlay(circle)
}
}
view.addAnnotations(model.mapMarkers)
//view.showAnnotations(view.annotations, animated: true)
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: provideMapView
init(_ parent: provideMapView) {
self.parent = parent
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: nil)
let color = (annotation as! CustomMarker).color
view.pinTintColor = UIColor(color)
return view
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let circleOverlay = overlay as? MKCircle {
let renderer = MKCircleRenderer(overlay: circleOverlay)
renderer.strokeColor = circleColor(radius: circleOverlay.radius)
renderer.lineWidth = 3
return renderer
}
return MKOverlayRenderer()
}
}
}
public func circleColor(radius: Double) -> UIColor {
switch radius {
case circles.circle1.rawValue:
return UIColor(circleColor1)
case circles.circle2.rawValue:
return UIColor(circleColor2)
case circles.circle3.rawValue:
return UIColor(circleColor3)
case circles.circle4.rawValue:
return UIColor(circleColor4)
default:
return UIColor(.black)
}
}
class CustomMarker: NSObject, MKAnnotation {
let coordinate: CLLocationCoordinate2D
let color: Color
init(coordinate: CLLocationCoordinate2D, color: Color) {
self.coordinate = coordinate
self.color = color
super.init()
}
}
MapModel logic
class MapModel {
func doMapView(patients: [String]) -> ([PatientPin], [LegendLine], MKCoordinateRegion, [CustomMarker]) {
let geoPatients: [CNContact] = ContactsModel().geoPatients(patients: patients)
var localPins = getPins(patients: geoPatients)
let localLegend = getLegend(pins: localPins)
let (localRegion, centerPin) = getRegion(pins: localPins)
var localMarkers = getMarkers(pins: localPins)
localPins.append(centerPin)
localMarkers.append(CustomMarker(coordinate: centerPin.coordinate, color: centerPin.color))
return (localPins, localLegend, localRegion, localMarkers)
}
func getPins(patients: [CNContact]) -> [PatientPin] {
let rodeweg = PatientPin(coordinate: .init(latitude: 51.35988, longitude: 4.48369), radius: 0.0, color: .yellow)
let rodewegDistance = CLLocation(latitude: 51.35988, longitude: 4.48369)
var localPins = [PatientPin]()
for patient in patients {
let coordinates = patient.previousFamilyName.components(separatedBy: ":")
let location = CLLocation(latitude: Double(coordinates[0])!, longitude: Double(coordinates[1])!)
let distance = location.distance(from: rodewegDistance)
var roundedDistance = 0.0
circles.allCases.reversed().forEach {
if distance < $0.rawValue {
roundedDistance = $0.rawValue
}
}
let pinColor = Color(circleColor(radius: roundedDistance))
localPins.append(PatientPin(coordinate: .init(latitude: Double(coordinates[0])!, longitude: Double(coordinates[1])!), radius: roundedDistance, color: pinColor))
}
localPins.append(rodeweg)
return localPins
}
func getMarkers(pins: [PatientPin]) -> [CustomMarker] {
var localMarkers = [CustomMarker]()
for pin in pins {
localMarkers.append(CustomMarker(coordinate: pin.coordinate, color: pin.color))
}
return localMarkers
}
func getLegend(pins: [PatientPin]) -> [LegendLine]{
var localLegend = [LegendLine]()
var oldDistance = 0.0
var counterTotal = 0
for (index, circle) in circles.allCases.enumerated() {
let distance = circle.rawValue
let counter = pins.filter { $0.radius == distance }.count
counterTotal += counter
let color = circleColor(radius: distance)
let textDistance = (index == circles.allCases.count - 1) ? "> \(Int(oldDistance/1000)) km" : "< \(Int(distance/1000)) km"
localLegend.append(LegendLine(roundedDistance: distance, distance: textDistance, count: String(counter), percentage: "0%", color: Color(color)))
oldDistance = distance
}
var percent = 0.0
for (index, _) in localLegend.enumerated() {
percent += Double(localLegend[index].count)!/Double(counterTotal)
let roundedPercentage = Int(round(percent * 20)/20 * 100)
localLegend[index].percentage = String("\(roundedPercentage)%")
}
return localLegend
}
func getRegion(pins: [PatientPin]) -> (MKCoordinateRegion, PatientPin) {
let coordinates = pins.map(\.coordinate)
let minLatitude = coordinates.map(\.latitude).min()!
let maxLatitude = coordinates.map(\.latitude).max()!
let minLongitude = coordinates.map(\.longitude).min()!
let maxLongitude = coordinates.map(\.longitude).max()!
let spanFactor = 1.25
let latitudeDelta = (maxLatitude - minLatitude) * spanFactor
let longitudeDelta = (maxLongitude - minLongitude) * spanFactor
let localRegion = MKCoordinateRegion(
center: CLLocationCoordinate2D(
latitude: minLatitude + (maxLatitude - minLatitude)/2.0,
longitude: minLongitude + (maxLongitude - minLongitude)/2.0
),
span: MKCoordinateSpan(
latitudeDelta: latitudeDelta,
longitudeDelta: longitudeDelta
)
)
let centerPin = PatientPin(coordinate: localRegion.center, radius: 0.0, color: .purple)
return (localRegion, centerPin)
}
from map.
Thank you for the correction of the code snippet - yes, there seems to have been an issue, but you seem to have found the cause correctly.
On the other note, you seem to be setting the mapRegion at two different points in time. While the implementation using this library sets the region once the view is actually in the view hierarchy, your custom implementation sets it before the view enters the view hierarchy with a frame of UIScreen.main.bounds
. This means, there is probably some map rescaling involved once the view is no longer that size but is rather resized to the safeArea instead of the full bounds (if there are navigationbars etc involved, it will be even smaller).
In general, I can see that a lot of data is generated while calculating the body
properties of the view rather than beforehand. Especially in the case of getCircles
, but also in the case of your updateUIView
, this will insert/remove annotations and overlays on any change of data, which is often unnecessary and may result in lags and sometimes even crash the app (If this happens too much - this is an issue of MKMapView and not this library).
from map.
Since your original question and hopefully all further questions are solved, I will close this thread. If you happen to have follow-up questions, feel free to reopen / add comments and for unrelated questions feel free to open new issues.
from map.
Related Issues (20)
- Map Annotation selection HOT 1
- ViewMapAnnotation does not allow text HOT 2
- ViewMapAnnotation not updating location HOT 1
- Using current zoom factor in Annotations HOT 1
- ViewMapAnnotation doesn't support clustering HOT 4
- Support with documentation HOT 4
- impossible to have my liste of annotations HOT 1
- Issue with userTrackingMode HOT 8
- User location not showed HOT 6
- Map+Coordinator.swift:256 Modifying state during view update, this will cause undefined behavior.
- onTapGesture not working HOT 23
- watchOS support for overlays? HOT 2
- assertionFailure("Somehow a cluster contains an unknown annotation item.") HOT 8
- Fails to compile for macOS (Apple Silicon) HOT 2
- If an annotation is clustered and then this annotation is removed from the array of annotationItems, it throws error assertionFailure("Somehow a cluster contains an unknown annotation item." HOT 1
- Append a Text after an Image as ViewMapAnnotation not showed HOT 1
- Annotations aren't immobile and move with zoom HOT 4
- Running HOT 1
- can't use Map on VisionOS. error about userTrackingMode HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from map.