Closed carson-katri closed 3 years ago
Disregard the snapshot test comment, I realize this won't be possible right now because we can't test TokamakDOM
directly, and this is implemented in TokamakDOM
.
Haven't done much cleanup yet, but did add support for symbols:
Canvas { context, size in
// Draw axes on the canvas.
context.stroke(Rectangle().path(in: .init(x: size.width / 2, y: 0, width: 1, height: size.height)), with: .color(.green))
context.stroke(Rectangle().path(in: .init(x: 0, y: size.height / 2, width: size.width, height: 1)), with: .color(.green))
// Resolve and draw the symbols, looking them up by tag.
guard let aSymbol = context.resolveSymbol(id: "a"),
let bSymbol = context.resolveSymbol(id: "b") else { return }
context.draw(aSymbol, at: .init(x: size.width / 2, y: size.height / 2), anchor: .topLeading)
context.draw(bSymbol, at: .init(x: size.width / 2, y: size.height / 2), anchor: .bottomTrailing)
} symbols: {
Text("A")
.frame(width: 100, height: 100)
.background(Color.red)
.cornerRadius(10)
.tag("a") // Tagged with "a"
Text("B")
.frame(width: 100, height: 100)
.background(Color.blue)
.tag("b") // Tagged with "b"
}
To look up Views by their tag, I added support for _VariadicView
(matching SwiftUI's) which provides access to child views as a RandomAccessCollection
, as well as access to _ViewTraitKey
s. The basic usage in Canvas is like so:
private struct SymbolResolverLayout<ID: Hashable>: _VariadicView.ViewRoot {
let id: ID
func body(children: _VariadicView.Children) -> some View {
ForEach(children) {
if case let .tagged(tag) = $0[TagValueTraitKey<ID>.self],
tag == id
{
$0
}
}
}
}
// Then used like so:
_VariadicView.Tree(SymbolResolverLayout(id: id)) {
_storage.symbols
}
The views are rendered in the canvas using SVG+foreignObject.
Off-topic, but _VariadicView
could be used to solve some issues with Picker
. It can allow for the use of tag(_:)
to specify items alongside ForEach
:
Picker("Choose...", selection: $selection) {
ForEach(items) { Text($0.title) }
Text("Clear").tag(Item.clear)
}
or for re-tagging:
Picker("Choose...", selection: $value) {
ForEach(items) {
Text($0.title)
.tag($0.value)
}
}
Would this be ready for review soon? It would be great to keep the PR relatively small, and then additional features could be implemented in a separate PR, for easier review, and to have separate commits for such features in the main
branch history.
Yes, it can be reviewed now.
This is built on the HTML canvas, and is compatible with the iOS 15
Canvas
view.TimelineView
with an.animation
schedule only runs withCanvas
at the moment with a special implementation usingrequestAnimationFrame
, but could be adjusted to work with other views as well.Here's a demo of confetti using
Canvas
:https://user-images.githubusercontent.com/13581484/133929292-4b98926c-3e0a-468c-ad23-28d8a87e3c77.mov