Overview of My Submission
Place iOS is r/place canvas clone made with Appwrite and pure SwiftUI.
I decide create this project for Appwrite Hackathon to test me in SwiftUI and use majority appwrite Apis. 😃
I'm a super fan of pixel art and this project fit perfect whit it. 🟩🟨🟪
The rules are simple: You can place a pixel every 30 seconds and the canvas will be updated using realtime.
Manage accounts, database, storage, sessions, realtime, functions and more were super simple with appwrite. 😎
My approach for create the canvas in SwiftUI
class CanvasViewModel: ObservableObject {
@Published var documents: [Doc] = [Doc]()
// MARK: - Properties
let canvasWidth: Int = 256
let canvasHeight: Int = 256
/// Pixel per pixels 👀
/// if canvasPixelFactor is high every pixels looks better (no antialiasing) but the performance in older devices will be compromised... Int(UIScreen.main.scale) + (3-12) works good
let canvasPixelFactor: Int = Int(UIScreen.main.scale) + 3
/// Computed canvas size
var canvasWidthComputed: CGFloat {
return CGFloat(canvasWidth * canvasPixelFactor)
}
var canvasHeightComputed: CGFloat {
return CGFloat(canvasWidth * canvasPixelFactor)
}
.
.
.
}
Fetch pixels from storage and database, then create image
private func createImage(completionHandler: @escaping (UIImage?, String?) -> Void){
guard !documents.isEmpty else { fatalError() }
guard canvasWidth > 0 && canvasHeight > 0 else { fatalError() }
DispatchQueue.global(qos: .utility).async {
let width = self.canvasWidth * self.canvasPixelFactor
let height = self.canvasHeight * self.canvasPixelFactor
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) // premultipliedLast or .none
let bitsPerComponent = 8
let bitsPerPixel = 32
var pixels = [Pixel]()
if self.pixelsArray.isEmpty {
for _ in 0..<width {
for _ in 0..<height {
pixels.append(Pixel(r: 255, g: 255, b: 255, a: 255))
}
}
// Colorize
for doc in self.documents {
let x = doc.x + 1
let y = doc.y + 1
let startXPx = x > 0 ? Int((x-1) * self.canvasPixelFactor) : 1
let endXPx = Int(x * self.canvasPixelFactor)
let startYPx = y > 0 ? Int((y-1) * self.canvasPixelFactor) : 1
let endYPx = Int(y * self.canvasPixelFactor)
for i in startXPx..<endXPx{
for j in startYPx..<endYPx{
let offset: Int = (Int(self.canvasWidthComputed) * j) + i
pixels[offset] = Pixel(hexString: doc.hex)
}
}
}
.
.
.
.
}
Bot
Also taking advantage of appwrite SDK's, i made a Bot in python for create pixel art in the canvas.🤖
The bot converts Sprites (or any image) in a valid image for draw in the canvas, the bot uses secret enviroment variable such we provided previously in colorPixel function, thus, will skip the delay. 😎
Dependencies
Appwrite Apple SDK: For manage, accounts, sessions, database, storage, functions, realtime... ⚡
Drops: For create notifications.
Popovers: For create pop menus.
SwiftyBeaver: For logging.
Submission Category:
Mobile Moguls
Link to Code
Additional Resources / Info
Onboarding
Func fact: In the last page, the third guy has an appwrite t-shirt.
Canvas View
For navigate in the canvas view you can zoom in, zoom out , drag and reset.
Func fact: The allowed colors is my favorite palette when i did pixel art: PICO-8 (only i was made a little change in white color to #FFFFFF)
Authentication
Only members are allowed to place pixels.
Settings
For log out, change zoom factor and information.
Fun fact: Tha app support Dark Mode. 😝🌙
Notifications
I use drops for put cool notifications. 🔔
Videos
App demostration
Bot demostration
Conclusion
This project was super fun to do.
Thanks for read and special thanks to Appwrite community for solves my questions ever. 🙏
Top comments (2)
Nice!
Thanks a lot for your feedback 😄