{"id":2198,"url":"https://github.com/efremidze/Magnetic","last_synced_at":"2025-08-06T15:31:03.300Z","repository":{"id":18470120,"uuid":"84387539","full_name":"efremidze/Magnetic","owner":"efremidze","description":"SpriteKit Floating Bubble Picker (inspired by Apple Music) 🧲","archived":false,"fork":false,"pushed_at":"2024-09-05T07:36:22.000Z","size":85661,"stargazers_count":1559,"open_issues_count":24,"forks_count":134,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-12-05T01:09:21.524Z","etag":null,"topics":["animation","apple","apple-music","bubble","carthage","cocoapods","floating","ios","music","picker","spritekit","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/efremidze.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-09T02:15:43.000Z","updated_at":"2024-11-30T06:30:26.000Z","dependencies_parsed_at":"2024-09-06T12:30:45.167Z","dependency_job_id":null,"html_url":"https://github.com/efremidze/Magnetic","commit_stats":{"total_commits":120,"total_committers":12,"mean_commits":10.0,"dds":0.1166666666666667,"last_synced_commit":"63ac15991741c3cc64f70f640a74b22af0b4bc49"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efremidze%2FMagnetic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efremidze%2FMagnetic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efremidze%2FMagnetic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efremidze%2FMagnetic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/efremidze","download_url":"https://codeload.github.com/efremidze/Magnetic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228915470,"owners_count":17991410,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","apple","apple-music","bubble","carthage","cocoapods","floating","ios","music","picker","spritekit","swift"],"created_at":"2024-01-05T20:16:07.358Z","updated_at":"2025-08-06T15:31:03.288Z","avatar_url":"https://github.com/efremidze.png","language":"Swift","funding_links":[],"categories":["Libs","UI","Swift","UI [🔝](#readme)"],"sub_categories":["UI","Other free courses","Font","Other Testing"],"readme":"# Magnetic\n\n[![CI](https://github.com/efremidze/Magnetic/actions/workflows/ci.yml/badge.svg)](https://github.com/efremidze/Magnetic/actions/workflows/ci.yml)\n[![CocoaPods](https://img.shields.io/cocoapods/v/Magnetic.svg)](https://cocoapods.org/pods/Magnetic)\n[![Carthage](https://img.shields.io/badge/Carthage-compatible-brightgreen.svg)](https://github.com/Carthage/Carthage)\n[![SPM](https://img.shields.io/badge/SPM-compatible-brightgreen.svg)](https://swift.org/package-manager/)\n[![Swift](https://img.shields.io/badge/Swift-5.9+-orange.svg)](https://swift.org)\n[![License](https://img.shields.io/github/license/efremidze/Magnetic.svg)](https://github.com/efremidze/Magnetic/blob/master/LICENSE)\n\n**Magnetic** is a customizable bubble picker like the Apple Music genre selection.\n\n\u003cimg src=\"/Images/demo2.gif\" width=\"250\" /\u003e\n\n```\n$ pod try Magnetic\n```\n\n## Features\n\n- [x] Adding/Removing Nodes\n- [x] Selection/Deselection/Removed Animations\n- [x] Multiple Selection\n- [x] Images\n- [x] Multiline Label\n- [x] [Documentation](https://efremidze.github.io/Magnetic)\n\n## Requirements\n\n- iOS 13.0+ (Magnetic 3.3.x), iOS 9.0+ (Magnetic 3.2.1)\n- Swift 5 (Magnetic 3.x), Swift 4 (Magnetic 2.x), Swift 3 (Magnetic 1.x)\n\n## Usage\n\nA `Magnetic` object is an [SKScene](https://developer.apple.com/reference/spritekit/skscene).\n\nTo display, you present it from an [SKView](https://developer.apple.com/reference/spritekit/skview) object.\n\n```swift\nimport Magnetic\n\nclass ViewController: UIViewController {\n\n    var magnetic: Magnetic?\n    \n    override func loadView() {\n        super.loadView()\n        \n        let magneticView = MagneticView(frame: self.view.bounds)\n        magnetic = magneticView.magnetic\n        self.view.addSubview(magneticView)\n    }\n\n}\n```\n\n#### Properties\n\n```swift\nvar magneticDelegate: MagneticDelegate? // magnetic delegate\nvar allowsMultipleSelection: Bool // controls whether you can select multiple nodes. defaults to true\nvar selectedChildren: [Node] // returns selected chidren\n```\n\n### Nodes\n\nA `Node` object is a SKShapeNode subclass.\n\n#### Interaction\n\n```swift\n// add circular node\nlet node = Node(text: \"Italy\", image: UIImage(named: \"italy\"), color: .red, radius: 30)\nmagnetic.addChild(node)\n\n// add custom node\nlet node = Node(text: \"France\", image: UIImage(named: \"france\"), color: .blue, path: path, marginScale: 1.1)\nmagnetic.addChild(node)\n\n// remove node\nnode.removeFromParent()\n```\n\n#### Properties\n\n```swift\nvar text: String? // node text\nvar image: UIImage? // node image\nvar color: UIColor // node color\n```\n\n#### Animations\n\n```swift\noverride func selectedAnimation() {\n    // override selected animation\n}\n\noverride func deselectedAnimation() {\n    // override deselected animation\n}\n\noverride func removedAnimation(completion: @escaping () -\u003e Void) {\n    // override removed animation\n}\n```\n\n### Delegation\n\nThe `MagneticDelegate` protocol provides a number of functions for observing the current state of nodes.\n\n```swift\nfunc magnetic(_ magnetic: Magnetic, didSelect node: Node) {\n    // handle node selection\n}\n\nfunc magnetic(_ magnetic: Magnetic, didDeselect node: Node) {\n    // handle node deselection\n}\n```\n\n### Customization\n\nSubclass the Node for customization.\n\nFor example, a node with an image by default:\n\n```swift\nclass ImageNode: Node {\n    override var image: UIImage? {\n        didSet {\n            texture = image.map { SKTexture(image: $0) }\n        }\n    }\n    override func selectedAnimation() {}\n    override func deselectedAnimation() {}\n}\n```\n\n## Installation\n\n### CocoaPods\nTo install with [CocoaPods](http://cocoapods.org/), simply add this in your `Podfile`:\n```ruby\nuse_frameworks!\npod \"Magnetic\"\n```\n\n### Carthage\nTo install with [Carthage](https://github.com/Carthage/Carthage), simply add this in your `Cartfile`:\n```ruby\ngithub \"efremidze/Magnetic\"\n```\n\n## Mentions\n\n- [Natasha The Robot's Newsleter 126](https://swiftnews.curated.co/issues/126#start)\n\n## Communication\n\n- If you **found a bug**, open an issue.\n- If you **have a feature request**, open an issue.\n- If you **want to contribute**, submit a pull request.\n\n## Credits\n\nhttps://github.com/igalata/Bubble-Picker\n\n## License\n\nMagnetic is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefremidze%2FMagnetic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fefremidze%2FMagnetic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefremidze%2FMagnetic/lists"}