Add TranscendenceStar and TranscendenceFragment
`TranscendenceStar` is a new star capable of displaying `TranscendenceFragment`s depending on the `GridCharacter` stage
This commit is contained in:
parent
d618d44429
commit
9c757c2c5b
4 changed files with 314 additions and 0 deletions
83
components/TranscendenceFragment/index.scss
Normal file
83
components/TranscendenceFragment/index.scss
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
.Fragment {
|
||||
$degrees: 72deg;
|
||||
|
||||
$origWidth: 29px;
|
||||
$origHeight: 54px;
|
||||
|
||||
$scaledWidth: 12px;
|
||||
$scaledHeight: calc(($scaledWidth / $origWidth) * $origHeight);
|
||||
|
||||
$scale: 1.2;
|
||||
|
||||
@include hidpiImage(
|
||||
'/icons/transcendence/interactive/interactive-piece',
|
||||
png,
|
||||
$scaledWidth,
|
||||
$scaledHeight
|
||||
);
|
||||
|
||||
position: absolute;
|
||||
z-index: 32;
|
||||
|
||||
aspect-ratio: 29 / 54;
|
||||
height: $scaledHeight;
|
||||
width: $scaledWidth;
|
||||
opacity: 0;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.Visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.Stage1 {
|
||||
top: 3px;
|
||||
left: 18px;
|
||||
|
||||
// &:hover {
|
||||
// transform: scale($scale, $scale) translateY(-2px);
|
||||
// }
|
||||
}
|
||||
|
||||
&.Stage2 {
|
||||
top: 10px;
|
||||
left: 27px;
|
||||
transform: rotate($degrees);
|
||||
|
||||
// &:hover {
|
||||
// transform: rotate($degrees) scale($scale, $scale) translateY(-2px);
|
||||
// }
|
||||
}
|
||||
|
||||
&.Stage3 {
|
||||
top: 21px;
|
||||
left: 24px;
|
||||
transform: rotate($degrees * 2);
|
||||
|
||||
// &:hover {
|
||||
// transform: rotate($degrees * 2) scale($scale, $scale) translateY(-1px);
|
||||
// }
|
||||
}
|
||||
|
||||
&.Stage4 {
|
||||
top: 21px;
|
||||
left: 12px;
|
||||
transform: rotate($degrees * 3);
|
||||
|
||||
// &:hover {
|
||||
// transform: rotate($degrees * 3) scale($scale, $scale) translateY(-1px);
|
||||
// }
|
||||
}
|
||||
|
||||
&.Stage5 {
|
||||
top: 10px;
|
||||
left: 8px;
|
||||
transform: rotate($degrees * 4);
|
||||
|
||||
// &:hover {
|
||||
// transform: rotate($degrees * 4) scale($scale, $scale) translateY(-1px);
|
||||
// }
|
||||
}
|
||||
}
|
||||
49
components/TranscendenceFragment/index.tsx
Normal file
49
components/TranscendenceFragment/index.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
interface Props {
|
||||
stage: number
|
||||
interactive: boolean
|
||||
visible: boolean
|
||||
onClick?: (index: number) => void
|
||||
onHover?: (index: number) => void
|
||||
}
|
||||
|
||||
const TranscendenceFragment = ({
|
||||
interactive,
|
||||
stage,
|
||||
visible,
|
||||
onClick,
|
||||
onHover,
|
||||
}: Props) => {
|
||||
const classes = classnames({
|
||||
Fragment: true,
|
||||
Visible: visible,
|
||||
Stage1: stage === 1,
|
||||
Stage2: stage === 2,
|
||||
Stage3: stage === 3,
|
||||
Stage4: stage === 4,
|
||||
Stage5: stage === 5,
|
||||
})
|
||||
|
||||
function handleClick() {
|
||||
if (interactive && onClick) onClick(stage)
|
||||
}
|
||||
|
||||
function handleHover() {
|
||||
if (interactive && onHover) onHover(stage)
|
||||
}
|
||||
|
||||
return (
|
||||
<i className={classes} onClick={handleClick} onMouseOver={handleHover} />
|
||||
)
|
||||
}
|
||||
|
||||
TranscendenceFragment.defaultProps = {
|
||||
interactive: false,
|
||||
visible: false,
|
||||
}
|
||||
|
||||
export default TranscendenceFragment
|
||||
79
components/TranscendenceStar/index.scss
Normal file
79
components/TranscendenceStar/index.scss
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
.TranscendenceStar {
|
||||
position: relative;
|
||||
|
||||
&.Immutable {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.Figure {
|
||||
$size: 18px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 54px 54px;
|
||||
display: block;
|
||||
height: $size;
|
||||
width: $size;
|
||||
|
||||
&.Interactive.Base {
|
||||
$size: $unit-6x;
|
||||
|
||||
@include hidpiImage(
|
||||
'/icons/transcendence/interactive/interactive-base',
|
||||
png,
|
||||
$size,
|
||||
$size
|
||||
);
|
||||
|
||||
height: $size;
|
||||
width: $size;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
&.Stage1 {
|
||||
background-image: url('/icons/transcendence/1/step-1@3x.png');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/icons/transcendence/1/step-1-hover@3x.png');
|
||||
}
|
||||
}
|
||||
|
||||
&.Stage2 {
|
||||
background-image: url('/icons/transcendence/2/step-2@3x.png');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/icons/transcendence/2/step-2-hover@3x.png');
|
||||
}
|
||||
}
|
||||
|
||||
&.Stage3 {
|
||||
background-image: url('/icons/transcendence/3/step-3@3x.png');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/icons/transcendence/3/step-3-hover@3x.png');
|
||||
}
|
||||
}
|
||||
|
||||
&.Stage4 {
|
||||
background-image: url('/icons/transcendence/4/step-4@3x.png');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/icons/transcendence/4/step-4-hover@3x.png');
|
||||
}
|
||||
}
|
||||
|
||||
&.Stage5 {
|
||||
background-image: url('/icons/transcendence/5/step-5@3x.png');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/icons/transcendence/5/step-5-hover@3x.png');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
components/TranscendenceStar/index.tsx
Normal file
103
components/TranscendenceStar/index.tsx
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import './index.scss'
|
||||
import TranscendenceFragment from '~components/TranscendenceFragment'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
stage: number
|
||||
editable: boolean
|
||||
interactive: boolean
|
||||
onClick?: () => void
|
||||
onFragmentClick?: (newStage: number) => void
|
||||
onFragmentHover?: (newStage: number) => void
|
||||
}
|
||||
|
||||
const NUM_FRAGMENTS = 5
|
||||
|
||||
const TranscendenceStar = ({
|
||||
className,
|
||||
interactive,
|
||||
stage,
|
||||
editable,
|
||||
onClick,
|
||||
onFragmentClick,
|
||||
onFragmentHover,
|
||||
}: Props) => {
|
||||
const [visibleStage, setVisibleStage] = useState(0)
|
||||
const [currentStage, setCurrentStage] = useState(0)
|
||||
|
||||
// Classes
|
||||
const starClasses = classnames({
|
||||
TranscendenceStar: true,
|
||||
Immutable: !editable,
|
||||
})
|
||||
|
||||
const baseImageClasses = classnames(className, {
|
||||
Figure: true,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
setVisibleStage(stage)
|
||||
setCurrentStage(stage)
|
||||
}, [stage])
|
||||
|
||||
function handleClick() {
|
||||
if (onClick) {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
|
||||
function handleFragmentClick(index: number) {
|
||||
let newStage = index
|
||||
if (index === currentStage) newStage = 0
|
||||
|
||||
setVisibleStage(newStage)
|
||||
setCurrentStage(newStage)
|
||||
if (onFragmentClick) onFragmentClick(newStage)
|
||||
}
|
||||
|
||||
function handleFragmentHover(index: number) {
|
||||
setVisibleStage(index)
|
||||
if (onFragmentHover) onFragmentHover(index)
|
||||
}
|
||||
|
||||
function handleMouseLeave() {
|
||||
setVisibleStage(currentStage)
|
||||
if (onFragmentHover) onFragmentHover(currentStage)
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
className={starClasses}
|
||||
onClick={interactive ? handleClick : () => {}}
|
||||
onMouseLeave={interactive ? handleMouseLeave : () => {}}
|
||||
>
|
||||
<div className="Fragments">
|
||||
{[...Array(NUM_FRAGMENTS)].map((e, i) => {
|
||||
const loopStage = i + 1
|
||||
return (
|
||||
<TranscendenceFragment
|
||||
key={`fragment_${loopStage}`}
|
||||
stage={loopStage}
|
||||
visible={loopStage <= visibleStage}
|
||||
interactive={interactive}
|
||||
onClick={interactive ? handleFragmentClick : () => {}}
|
||||
onHover={interactive ? handleFragmentHover : () => {}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<i className={baseImageClasses} />
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
TranscendenceStar.defaultProps = {
|
||||
stage: 0,
|
||||
editable: false,
|
||||
interactive: false,
|
||||
}
|
||||
|
||||
export default TranscendenceStar
|
||||
Loading…
Reference in a new issue