Last active
October 15, 2021 12:59
-
-
Save tlux/88dfd5f84cb587892a3495fef7734f68 to your computer and use it in GitHub Desktop.
Cube component with CSS transitions Svelte + TS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import { createEventDispatcher } from 'svelte'; | |
import { CubeSide } from './CubeSide'; | |
export let view: CubeSide = CubeSide.Front; | |
export let transition: boolean = false; | |
export let transitionDuration: number = 2000; | |
export let backface: boolean = false; | |
export let perspective: string = '1000px'; | |
export let width: string = '100%'; | |
export let height: string = '100%'; | |
let style!: string; | |
$: { | |
style = [ | |
`--cube-width: ${width}`, | |
`--cube-height: ${height}`, | |
`--cube-perspective: ${perspective}`, | |
transition && `--cube-transition-duration: ${transitionDuration}ms`, | |
].filter(Boolean).join(';'); | |
} | |
const dispatch = createEventDispatcher(); | |
function onTransitionEnd() { | |
dispatch('transitionend', { view }); | |
} | |
</script> | |
<div | |
class="cube cube--view-{view}" | |
class:cube--backface={backface} | |
class:cube--transition={transition} | |
{style} | |
> | |
<div class="cube__body" on:transitionend|self={onTransitionEnd}> | |
<div class="cube__side cube__side--front"> | |
<slot name="front" /> | |
</div> | |
<div class="cube__side cube__side--back"> | |
<slot name="back" /> | |
</div> | |
<div class="cube__side cube__side--left"> | |
<slot name="left" /> | |
</div> | |
<div class="cube__side cube__side--right"> | |
<slot name="right" /> | |
</div> | |
<div class="cube__side cube__side--top"> | |
<slot name="top" /> | |
</div> | |
<div class="cube__side cube__side--bottom"> | |
<slot name="bottom" /> | |
</div> | |
</div> | |
</div> | |
<style> | |
.cube { | |
position: relative; | |
width: var(--cube-width); | |
height: var(--cube-height); | |
perspective: var(--cube-perspective); | |
perspective-origin: center; | |
} | |
.cube--view-front { | |
--rotate-x: 0; | |
--rotate-y: 0; | |
} | |
.cube--view-left { | |
--rotate-x: 0; | |
--rotate-y: 90; | |
} | |
.cube--view-right { | |
--rotate-x: 0; | |
--rotate-y: -90; | |
} | |
.cube--view-back { | |
--rotate-x: 0; | |
--rotate-y: 180; | |
} | |
.cube--view-top { | |
--rotate-x: -90; | |
--rotate-y: 0; | |
} | |
.cube--view-bottom { | |
--rotate-x: 90; | |
--rotate-y: 0; | |
} | |
.cube__body { | |
position: relative; | |
width: 100%; | |
height: 100%; | |
transform-style: preserve-3d; | |
transform: rotateY(-90deg) translateX(-50%) rotateY(90deg) | |
rotateY(calc(var(--rotate-y) * 1deg)) | |
rotateX(calc(var(--rotate-x) * 1deg)); | |
} | |
.cube--transition .cube__body { | |
transition-property: transform; | |
transition-duration: var(--cube-transition-duration); | |
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); | |
} | |
.cube__side { | |
position: absolute; | |
inset: 0; | |
backface-visibility: hidden; | |
} | |
.cube--backface .cube__side { | |
backface-visibility: inherit; | |
} | |
.cube__side--front { | |
transform: rotateY(90deg) translateX(-50%) rotateY(-90deg); | |
} | |
.cube__side--back { | |
transform: rotateY(90deg) translateX(50%) rotateY(90deg); | |
} | |
.cube__side--left { | |
transform: rotateY(0deg) translateX(-50%) rotateY(-90deg); | |
} | |
.cube__side--right { | |
transform: rotateY(0deg) translateX(50%) rotateY(90deg); | |
} | |
.cube__side--top { | |
transform: translateY(-50%) rotateX(90deg); | |
} | |
.cube__side--bottom { | |
transform: translateY(50%) rotateX(-90deg); | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export enum CubeSide { | |
Front = 'front', | |
Back = 'back', | |
Left = 'left', | |
Right = 'right', | |
Top = 'top', | |
Bottom = 'bottom' | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment