feat: styling cards as fan

This commit is contained in:
efim 2023-05-07 18:25:54 +04:00
parent ba58a13e6a
commit 3dab3f66b9
2 changed files with 39 additions and 14 deletions

View File

@ -34,22 +34,32 @@ object OtherPlayers {
val xOffsetStyleSignal = p.map(_._2)
div(
className := "bg-green-200 border-b-2 border-black rounded p-2 m-2 absolute drop-shadow-xl m-3",
// left <-- p.map(tuple => ((1 + tuple._2) * 10000).toString()),
styleAttr <-- p.map(tuple => s"left: ${(0 + tuple._2) * 200}px"),
child.text <-- p.map(_._1.name),
renderHandCardBacks(cardsAmount)
)
}
def dynamicCardStyle(index: Int, totalCards: Int): String = {
val offCenterIndex = 2*index - (totalCards + 1)
val maxOffCenter = (totalCards + 1) / 2
val angle = Math.round((offCenterIndex / maxOffCenter.toDouble) * 20)
val xOffset = (offCenterIndex * 0.3)
s"transform: rotate(${angle}deg) translateX(${xOffset}em) "
}
def renderHandCardBacks(amountSignal: Signal[Int]): Element = {
def renderCard(index: Int): Element =
def renderCard(index: Int, totalCards: Int): Element =
div(
className := "w-8 h-12 rounded bg-green-500 text-yellow m-1 border border-green-700 drop-shadow-md"
className := "w-8 h-12 rounded bg-green-500 text-yellow m-1 border border-green-700 drop-shadow-md",
className := "absolute ",
styleAttr := dynamicCardStyle(index, totalCards),
)
div(
className := "flex flex-row",
children <-- amountSignal.map { amount => (1 to amount).map(renderCard) }
className := "relative h-16 w-20",
children <-- amountSignal.map { amount => (1 to amount).map(renderCard(_, amount)) }
)
}

View File

@ -12,32 +12,47 @@ object OwnHandControls {
def render(roomStateSignal: Signal[RoomStateView]): Element = {
val cardTypesSignal = roomStateSignal.map(myUnselectedCards(_))
div(
className := "flex flex-row justify-center",
children <-- cardTypesSignal.map(_.map(renderCard(_)))
className := " h-1/3 relative",
children <-- cardTypesSignal.map(cards => cards.map(renderCard(_, cards.size))),
)
}
private def renderCard(value: String): Element = {
def dynamicCardStyle(index: Int, totalCards: Int): String = {
val offCenterIndex = 2*index - (totalCards + 1)
val maxOffCenter = (totalCards + 1) / 2
val angle = Math.round((offCenterIndex / maxOffCenter.toDouble) * 15)
val xOffset = offCenterIndex * 1.3
s"$offCenterIndex ${(offCenterIndex.toLong / maxOffCenter.toLong)} transform: rotate(${angle}deg) "
s"transform: rotate(${angle}deg) translateX(${xOffset}em) translateY(-2em)"
}
private def renderCard(cardWithIndex: (String, Int), totalCards: Int): Element = {
val (value, index) = cardWithIndex
val submitVote = Fetch.get(s"/api/vote/$value").text
div(
className := "cursor-pointer w-24 h-48 m-1 rounded-l flex justify-center items-center m-3 text-black bg-gray-50 border-black border-2 drop-shadow-md",
className := "hover:-translate-y-2 hover:scale-[1.02] hover:drop-shadow-xl rounded-lg hover:bg-gray-100 ease-linear duration-200",
className := " hover:z-50 hover:drop-shadow-xl rounded-lg hover:bg-gray-100 ease-linear duration-200",
className := "absolute origin-bottom start-1/2",
styleAttr := dynamicCardStyle(index, totalCards),
onClick.flatMap(_ => submitVote) --> Observer(resp => g.console.info(resp.toString())),
div(
className := "-rotate-45 text-xl",
value
value,
)
)
}
private def myUnselectedCards(state: RoomStateView): List[String] = {
state.round match {
private def myUnselectedCards(state: RoomStateView): List[(String, Int)] = {
val allCards = state.allowedCards
val cards = state.round match {
case RoundStateView.Voting(myCard, _) =>
state.allowedCards.filterNot(value => myCard.contains(value))
allCards.filterNot(value => myCard.contains(value))
case RoundStateView.Viewing(votes) =>
state.allowedCards.filterNot(value => votes.toMap.get(state.me).contains(value))
allCards.filterNot(value => votes.toMap.get(state.me).contains(value))
}
cards.zip(1 to state.allowedCards.size)
}
}