How to rotate?
This can be implemented by using rotation3DEffect
To make it simple, let’s begin with the empty square. As you can see from the above GIF, rotation3DEffect
make a view rotate around x, y, z axis. You can check details in the official document.
So what we have to do first is making our view to rotate around y-axis like real Pantone color sets. In addition, to make our view act more naturally, we should think about other options like anchor
and perspective
.
anchor
should be placed in the position where the central axis is desired and perspective
is used to adjust perspective literally. I set anchor
to UnitPoint(x: -2, y: -1.5)
because people are used to the top-down view. Okay. Now it seems the only thing we should do is just replacing Rectangle
to a card shape.
However, before we jump into it, there is an unsolved problem we should deal with. That is, because of the feature of ForEach
, zIndex
of cards at the back is higher than card at the front, and so the card at the front is blocked by them. We will look into this issue in more detail at next part. In conclusion, this requires adjusting the zIndex
of each card.
Deal with zIndex
Simply put, this problem can be solved when the front card has a larger zIndex
than the back card. For this, I came up with some concepts: relativeIndex
and zIndexPreset
. relativeIndex
is the index of cards newly calculated based on 0 degrees, that is, the rightmost part of carousel. In other words, It can be said I created kind of new angular coordinate system. Anyway, the code is below.
zIndexPreset
is an array which has decreasing numbers. For example, a zIndexPreset
of length 5 will be an array like [5, 4, 3, 2, 1]
. Of course, actual element in there will be little bit different because zIndex
has to have its input as Double
between 0 and 1. I will use zIndexPreset
to define the zIndex
of each card in the way like zIndexPreset[relativeIndex]
.
However, if relativeIndex
is used without any correction, the relativeIndex
of the card in front of 0 degrees becomes larger than the cards behind, which means they will be blocked by the back card again. To prevent this, I created a variable called correctdRelativeIndex
.
Actually, before doing this, we have to do some math figuring out which card is located in the 0 degree based on the current angle.
Yeah, it’s quite complicated. I tried my best, but I believe there would be easier and better solution. If you have any better ideas, It would be appreciated if you let me know...
Add some details
If you add offset
you can make your card pop out.
chipShapes[index]
.offset(y: currentCard == index ? 100 : 0)
Basic things are all done. You can now add some design elements like ‘card case’, ‘shadow’ to your liking. I added spanning RGB color and using VStack
to stack them up.
Actually, the color codes written on the chips are ‘RGB’ code, not the ‘Pantone’ code. Except for that, it works really fine anyway.🤣
You can get full codes from my Github repo