Experimental football field rendered with CSS 3D transforms and using Velocity JS to handle animation.
Created
October 31, 2020 07:30
-
-
Save SH20RAJ/f60c277d4a6e7f2dc1db0a2490f5a317 to your computer and use it in GitHub Desktop.
CSS 3D Football Field
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
<main> | |
<div class="static"> | |
<h1 class="js-heading">FOOTBALL LEAGUE</h1> | |
<p class="js-subheading">Experimental team line-up and football field using CSS 3D transforms.<br><span style="font-size: 11px">Currently buggy in Chrome, will fix soon :)</span></p> | |
<div class="js-switcher switcher"> | |
<a href="#" class="js-switch disabled switch-btn">HOME</a><a href="#" class="js-switch switch-btn">AWAY</a> | |
</div> | |
</div> | |
<div class="js-stage stage texture"> | |
<div class="js-world world"> | |
<div class="team js-team"> | |
<!-- Team cards / icons goes here --> | |
</div> | |
<div class="terrain js-terrain"> | |
<div class="field field--alt"></div> | |
<div class="field ground"> | |
<div class="field__texture field__texture--gradient"></div> | |
<div class="field__texture field__texture--gradient-b"></div> | |
<div class="field__texture field__texture--grass"></div> | |
<div class="field__line field__line--goal"></div> | |
<div class="field__line field__line--goal field__line--goal--far"></div> | |
<div class="field__line field__line--outline"></div> | |
<div class="field__line field__line--penalty"></div> | |
<div class="field__line field__line--penalty-arc"></div> | |
<div class="field__line field__line--penalty-arc field__line--penalty-arc--far"></div> | |
<div class="field__line field__line--mid"></div> | |
<div class="field__line field__line--circle"></div> | |
<div class="field__line field__line--penalty field__line--penalty--far"></div> | |
</div> | |
<div class="field__side field__side--front"></div> | |
<div class="field__side field__side--left"></div> | |
<div class="field__side field__side--right"></div> | |
<div class="field__side field__side--back"></div> | |
</div> | |
</div> | |
<div class="loading js-loading">PLEASE WAIT...</div> | |
</div> | |
</main> |
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
ASSET_URL = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/215059/' | |
$stage = null | |
$world = null | |
$terrain = null | |
$team = null | |
$teamListHome = null | |
$players = null | |
$playersHome = null # Subset of $players | |
$playersAway = null # Subset of $players | |
$switchBtn = null | |
$loadBtn = null | |
$closeBtn = null | |
$heading = null | |
$subHeading = null | |
$loading = null | |
$switcher = null | |
data = | |
players: | |
home: [ | |
{ name: 'Pizarro', asset: 'bm-pizarro.jpg', origin: 'Peru', height: '1.84m', shirt: '14', pos: 'Forward', dob: '36', goals: 1, games: 16, x: 110, y: -190 } | |
{ name: 'Robben', asset: 'bm-robben.png', origin: 'Holland', height: '1.80m', shirt: '10', pos: 'Forward', dob: '32', goals: 19, games: 30, x: -110, y: -190 } | |
{ name: 'Rilbery', asset: 'bm-rilbery.jpg', origin: 'France', height: '1.70m', shirt: '7', pos: 'Midfield', dob: '32', goals: 9, games: 22, x: 150, y: 50 } | |
{ name: 'Schweinsteiger', asset: 'bm-schweinsteiger.jpg', origin: 'Germany', height: '1.87m', shirt: '24', pos: 'Forward', dob: '31', goals: 21, games: 3, x: 0, y: 100 } | |
{ name: 'Martinez', asset: 'bm-martinez.jpg', origin: 'Spain', height: '1.90m', shirt: '8', pos: 'Midfield', dob: '28', goals: 0, games: 2, x: -150, y: 50 } | |
{ name: 'Alaba', asset: 'bm-alaba.jpg', origin: 'Austria', height: '1.80m', shirt: '27', pos: 'Defence', dob: '24', goals: 5, games: 27, x: -200, y: 180 } | |
{ name: 'Lahm', asset: 'bm-lahm.jpg', origin: 'Germany', height: '1.70', shirt: '21', pos: 'Defence', dob: '32', goals: 2, games: 25, x: 200, y: 180 } | |
{ name: 'Benatia', asset: 'bm-benatia.jpg', origin: 'France', height: '1.87m', shirt: '5', pos: 'Defence', dob: '31', goals: 21, games: 1, x: 100, y: 300 } | |
{ name: 'Dante', asset: 'bm-dante.jpg', origin: 'Brazil', height: '1.87m', shirt: '4', pos: 'Defence', dob: '32', goals: 0, games: 34, x: -100, y: 300 } | |
{ name: 'Neuer', asset: 'bm-neuer.jpg', origin: 'Germany', height: '1.93m', shirt: '1', pos: 'Goalie', dob: '29', goals: 0, games: 48, x: 0, y: 410 } | |
] | |
away: [ | |
{ name: 'Benzema', asset: 'rm-benzema.jpg', origin: 'France', height: '1.87m', shirt: '9', pos: 'Forward', dob: '36', goals: 1, games: 16, x: 110, y: -190 } | |
{ name: 'Bale', asset: 'rm-bale.jpg', origin: 'Wales', height: '1.83m', shirt: '11', pos: 'Midfield', dob: '26', goals: 19, games: 30, x: -110, y: -190 } | |
{ name: 'carvajal', asset: 'rm-carvajal.jpg', origin: 'Spain', height: '1.70m', shirt: '15', pos: 'Defender', dob: '32', goals: 9, games: 22, x: 150, y: 50 } | |
{ name: 'Silva', asset: 'rm-silva.jpg', origin: 'Brazil', height: '1.87m', shirt: '16', pos: 'Forward', dob: '22', goals: 21, games: 3, x: 0, y: 100 } | |
{ name: 'Kroos', asset: 'rm-kroos.jpg', origin: 'Germany', height: '1.82', shirt: '8', pos: 'Midfield', dob: '25', goals: 0, games: 2, x: -150, y: 50 } | |
{ name: 'Modric', asset: 'rm-modric.jpg', origin: 'Croatia', height: '1.74m', shirt: '19', pos: 'Midfield', dob: '30', goals: 5, games: 27, x: -200, y: 180 } | |
{ name: 'Nacho', asset: 'rm-nacho.jpg', origin: 'Germany', height: '1.79', shirt: '18', pos: 'Defence', dob: '25', goals: 2, games: 25, x: 200, y: 180 } | |
{ name: 'Ramos', asset: 'rm-ramos.jpg', origin: 'Spain', height: '1.83m', shirt: '4', pos: 'Defence', dob: '31', goals: 21, games: 1, x: 100, y: 300 } | |
{ name: 'Pepe', asset: 'rm-pepe.jpg', origin: 'Brazil', height: '1.88m', shirt: '3', pos: 'Defence', dob: '32', goals: 0, games: 34, x: -100, y: 300 } | |
{ name: 'Casillas', asset: 'rm-casillas.jpg', origin: 'Spain', height: '1.85m', shirt: '1', pos: 'Goalie', dob: '34', goals: 0, games: 48, x: 0, y: 410 } | |
] | |
state = | |
home: true | |
disabHover: false | |
swapSides: -> | |
if @home then @home = false else @home = true | |
curSide: -> | |
if @home then 'home' else 'away' | |
pos = | |
world: | |
baseX: 0 | |
baseY: 0 | |
baseZ: -200 | |
def: | |
goalie: [0,-50] | |
dom = | |
addPlayers: (side) -> | |
for key, val of data.players[side] | |
val.side= side | |
$el = @addPlayer val | |
$team.append $el | |
$players = $('.js-player') | |
$playersHome = $('.js-player[data-side="home"]') | |
$playersAway = $('.js-player[data-side="away"]') | |
addPlayer: (data) -> | |
$el = $ '<div class="js-player player" data-name="' + data.name + '" data-side="' + data.side + '" data-x="' + data.x + '" data-y="' + data.y + '"></div>' | |
$el.append '<div class="player__label"><span>' + data.name + '</span></div>' | |
$el.append '<div class="player__img"><img src= ' + ASSET_URL + data.asset + '></div>' | |
$el.prepend '<div class="player__card"> </div>' | |
$el.prepend '<div class="player__placeholder"></div>' | |
@populateCard $el.find('.player__card'), data | |
$el | |
preloadImages: (preload) -> | |
promises = [] | |
i = 0 | |
while i < preload.length | |
((url, promise) -> | |
img = new Image | |
img.onload = -> promise.resolve() | |
img.src = url | |
) preload[i], promises[i] = $.Deferred() | |
i++ | |
$.when.apply($, promises).done -> | |
scenes.endLoading() | |
scenes.loadIn(1600) | |
populateCard: ($el, data) -> | |
$el.append '<h3>' + data.name + '</h3>' + | |
'<ul class="player__card__list"><li><span>DOB</span><br/>' + data.dob + ' yr</li><li><span>Height</span><br/>' + data.height + '</li><li><span>Origin</span><br/>' + data.origin + '</li></ul>' + | |
'<ul class="player__card__list player__card__list--last"><li><span>Games</span><br/>' + data.games + '</li><li><span>Goals</span><br/>' + data.goals + '</li></ul>' | |
displayNone: ($el) -> | |
$el.css 'display', 'none' | |
events = | |
attachAll: -> | |
$switchBtn.on 'click', (e) -> | |
e.preventDefault() | |
$el = $(this) | |
return if $el.hasClass 'disabled' | |
scenes.switchSides() | |
$switchBtn.removeClass 'disabled' | |
$el.addClass 'disabled' | |
$loadBtn.on 'click', (e) -> | |
e.preventDefault() | |
scenes.loadIn() | |
$players.on 'click', (e) -> | |
e.preventDefault() | |
$el = $(this) | |
if $('.active').length then return false | |
$el.addClass 'active' | |
scenes.focusPlayer($el) | |
setTimeout ( -> events.attachClose()), 1 | |
attachClose: -> | |
$stage.one 'click', (e) -> | |
e.preventDefault() | |
scenes.unfocusPlayer() | |
scenes = | |
preLoad: -> | |
$teamListHome.velocity { opacity: 0 }, 0 | |
$players.velocity { opacity: 0 }, 0 | |
$loadBtn.velocity { opacity: 0 }, 0 | |
$switcher.velocity { opacity: 0 }, 0 | |
$heading.velocity { opacity: 0 }, 0 | |
$subHeading.velocity { opacity: 0 }, 0 | |
$playersAway.css 'display', 'none' | |
$world.velocity { opacity: 0, translateZ: -200, translateY: -60 }, 0 | |
$('main').velocity { opacity: 1 }, 0 | |
loadIn: (delay = 0) -> | |
$world.velocity { opacity: 1, translateY: 0, translateZ: -200 }, { duration: 1000, delay: delay, easing: 'spring' } | |
anim.fadeInDir($heading, 300, (delay + 600), 0, 30) | |
anim.fadeInDir($subHeading, 300, (delay + 800), 0, 30) | |
anim.fadeInDir($teamListHome, 300, (delay + 800), 0, 30) | |
anim.fadeInDir($switcher, 300, (delay + 900), 0, 30) | |
delay += 1200 | |
delayInc = 30 | |
anim.dropPlayers($playersHome, delay, delayInc) | |
startLoading: -> | |
anim.fadeInDir $loading, 300, 0, 0, -20 | |
images = [] | |
for key, val of data.players.home and data.players.away | |
images.push ASSET_URL + val.asset | |
dom.preloadImages(images) | |
endLoading: -> | |
anim.fadeOutDir $loading, 300, 1000, 0, -20 | |
arrangePlayers: -> | |
$players.each -> | |
$el = $(this) | |
$el.velocity | |
translateX: parseInt $el.attr('data-x') | |
translateZ: parseInt $el.attr('data-y') # Z is the Y axis on the field | |
focusPlayer: ($el) -> | |
data = $el.data() | |
shiftY = data.y | |
if shiftY > 0 then shiftY = (data.y / 2) | |
$('.js-player[data-side="' + state.curSide() + '"]').not('.active').each -> | |
$unfocus = $(this) | |
anim.fadeOutDir $unfocus, 300, 0, 0, 0, 0, null, 0.2 | |
$world.velocity | |
translateX: (pos.world.baseX - data.x) | |
translateY: (pos.world.baseY) | |
translateZ: (pos.world.baseZ - shiftY) # Z is the Y axis on the field | |
, 600 | |
$terrain.velocity | |
opacity: 0.66 | |
, 600 | |
@showPlayerCard $el, 600, 600 | |
unfocusPlayer: -> | |
$el = $('.js-player.active') | |
data = $el.data() | |
anim.fadeInDir $('.js-player[data-side="' + state.curSide() + '"]').not('.active'), 300, 300, 0, 0, 0, null, 0.2 | |
$el.removeClass 'active' | |
$world.velocity | |
translateX: (pos.world.baseX) | |
translateY: (pos.world.baseY) | |
translateZ: (pos.world.baseZ) # Z is the Y axis on the field | |
, 600 | |
$terrain.velocity | |
opacity: 1 | |
, 600 | |
@hidePlayerCard $el, 600, 600 | |
hidePlayerCard: ($el, dur, delay) -> | |
$card = $el.find '.player__card' | |
$image = $el.find '.player__img' | |
$image.velocity | |
translateY: 0 | |
, 300 | |
anim.fadeInDir $el.find '.player__label', 200, delay | |
anim.fadeOutDir $card, 300, 0, 0, -100 | |
showPlayerCard: ($el, dur, delay) -> | |
$card = $el.find '.player__card' | |
$image = $el.find '.player__img' | |
$image.velocity | |
translateY: '-=150px' | |
, 300 | |
anim.fadeOutDir $el.find '.player__label', 200, delay | |
anim.fadeInDir $card, 300, 200, 0, 100 | |
switchSides: -> | |
delay = 0 | |
delayInc = 20 | |
$old = $playersHome | |
$new = $playersAway | |
if !state.home | |
$old = $playersAway | |
$new = $playersHome | |
state.swapSides() | |
$old.each -> | |
$el = $(this) | |
anim.fadeOutDir($el, 200, delay, 0, -60, 0) | |
anim.fadeOutDir($el.find('.player__label'), 200, (delay + 700)) | |
delay += delayInc | |
$terrain.velocity { rotateY: '+=180deg' }, { delay: 150, duration: 1200 } | |
anim.dropPlayers($new, 1500, 30) | |
anim = | |
fadeInDir: ($el, dur, delay, deltaX = 0, deltaY = 0, deltaZ = 0, easing = null, opacity = 0) -> | |
$el.css 'display', 'block' | |
$el.velocity | |
translateX: '-=' + deltaX | |
translateY: '-=' + deltaY | |
translateZ: '-=' + deltaZ | |
, 0 | |
$el.velocity | |
opacity: 1 | |
translateX: '+=' + deltaX | |
translateY: '+=' + deltaY | |
translateZ: '+=' + deltaZ | |
, | |
easing: easing | |
delay: delay | |
duration: dur | |
fadeOutDir: ($el, dur, delay, deltaX = 0, deltaY = 0, deltaZ = 0, easing = null, opacity = 0) -> | |
if !opacity | |
display = 'none' | |
else | |
display = 'block' | |
$el.velocity | |
opacity: opacity | |
translateX: '+=' + deltaX | |
translateY: '+=' + deltaY | |
translateZ: '+=' + deltaZ | |
, | |
easing: easing | |
delay: delay | |
duration: dur | |
.velocity | |
opacity: opacity | |
translateX: '-=' + deltaX | |
translateY: '-=' + deltaY | |
translateZ: '-=' + deltaZ | |
, | |
duration: 0 | |
display: display | |
dropPlayers: ($els, delay, delayInc) -> | |
$els.each -> | |
$el = $(this) | |
$el.css | |
display : 'block' | |
opacity : 0 | |
anim.fadeInDir($el, 800, delay, 0, 50, 0, 'spring') | |
anim.fadeInDir($el.find('.player__label'), 200, (delay + 250)) | |
delay += delayInc | |
init = -> | |
$stage = $('.js-stage') | |
$world = $('.js-world') | |
$switchBtn = $('.js-switch') | |
$loadBtn = $('.js-load') | |
$heading = $('.js-heading') | |
$switcher = $('.js-switcher') | |
$closeBtn = $('.js-close') | |
$subHeading = $('.js-subheading') | |
$terrain = $('.js-terrain') | |
$team = $('.js-team') | |
$teamListHome = $('.js-team-home') | |
$loading = $('.js-loading') | |
dom.addPlayers('home') | |
dom.addPlayers('away') | |
scenes.preLoad() | |
scenes.arrangePlayers() | |
events.attachAll() | |
scenes.startLoading() | |
$(document).ready -> | |
init() |
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 src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.2/velocity.min.js"></script> |
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
// Palette | |
$body-bg-color = #2a437c | |
$body-bg-color-2 = #10203b | |
$colors-text-def = #333 | |
$colors-text-med = #777 | |
$colors-text-lt = #aaa | |
$colors-card-bg1 = #f7f7f7 | |
$colors-card-bg2 = #eeeeee | |
$colors-card-bg3 = #1d2643 | |
$colors-card-txt = #a40028 | |
$field-bg-color = #eeeeee | |
$field-side-color = #f7f7f7 | |
$line-color = rgba(255,255,255,0.5) | |
$texture-field-side = #141d2b | |
// Field dimensions | |
$stage-perspective = 1100px | |
$field-y = 840px | |
$field-x = ($field-y * 0.8) | |
$field-ratio = ($field-x / $field-y) | |
$field-side-y = 8px | |
$field-rot = 90deg | |
$field-buffer = 4% | |
$line-x = 3px | |
$line-circle-x = 25% | |
// Player dimensions | |
$player-x = 65px | |
$card-x = 230px | |
$card-y = 260px | |
// Codepen asset mixin | |
asset(filename='blank.gif') | |
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/215059/' filename) | |
* | |
box-sizing: border-box | |
html, body | |
width: 100% | |
height: 100% | |
font-size: 62.5% | |
padding: 0 | |
margin: 0 | |
.velocity-animating | |
transition: none !important | |
body | |
background-image: -webkit-radial-gradient(ellipse, $body-bg-color 0, $body-bg-color-2 100%) | |
font-family: 'Open Sans', helvetica, arial, sans-serif | |
main | |
opacity: 0 | |
.static | |
position: absolute | |
top: 0 | |
left: 0 | |
width: 100% | |
color: #fff | |
text-align: center | |
padding: 0 | |
z-index: 3 | |
h1 | |
margin: 50px 0 15px | |
font-size: 50px | |
font-weight: 800 | |
text-transform: uppercase | |
line-height: 42px | |
letter-spacing: -3px | |
font-family: montserrat | |
p | |
font-weight: 300 | |
opacity: 0.4 | |
margin: 0 0 20px | |
font-size: 16px | |
color: lighten($body-bg-color, 50%) | |
.loading | |
position: absolute | |
top: 0 | |
right: 0 | |
bottom: 0 | |
left: 0 | |
margin: auto | |
height: 16px | |
line-height: 16px | |
color: #fff | |
font-family: 'montserrat' | |
font-size: 24px | |
font-weight: 900 | |
letter-spacing: -1px | |
text-align: center | |
opacity: 0 | |
.team-list | |
position: absolute | |
left: 40px | |
top: 100px | |
list-style: none | |
display: none | |
li:first-child | |
color: #fff | |
font-weight: bold | |
li | |
font-size: 1.4rem | |
margin: 0 0 10px | |
color: lighten($body-bg-color, 50%) | |
.stage | |
position: absolute | |
width: 100% | |
height: 100% | |
top: 0 | |
perspective-origin: 50% -200px | |
perspective: $stage-perspective | |
z-index: 1 | |
backface-visibility: hidden | |
.world | |
position: absolute | |
top: 130px | |
left: 50% | |
margin-left: -($field-x / 2) | |
width: $field-x | |
height: $field-y | |
transform: translateZ(-($field-y / 4)) | |
transform-style: preserve-3d | |
z-index: 1 | |
backface-visibility: hidden | |
&.flipped | |
transform: translateZ(-($field-y / 4)) rotateY(180deg) | |
&.switched | |
transform: translateZ(250px) rotateY(30deg) translateX(60px) translateY(-200px) | |
.switch-btn | |
display: inline-block | |
padding: 6px 15px | |
border: solid 1px lighten($body-bg-color, 50%) | |
border-radius: 5px | |
text-align: center | |
color: lighten($body-bg-color, 50%) | |
text-decoration: none | |
opacity: 1 | |
font-size: 12px | |
transition: all 0.15s | |
&.disabled | |
background: lighten($body-bg-color, 50%) | |
color: $body-bg-color | |
cursor: default | |
&:hover | |
color: $body-bg-color | |
&:hover | |
color: #fff | |
&:first-child | |
border-radius: 10px 0 0 10px | |
border-right: none | |
&:last-child | |
border-radius: 0 10px 10px 0 | |
.team | |
position: absolute | |
top: 0 | |
left: 0 | |
width: 100% | |
height: 100% | |
transform-style: preserve-3d | |
.terrain | |
position: absolute | |
top: 0 | |
left: 0 | |
width: 100% | |
height: 100% | |
transform-style: inherit | |
.field | |
position: absolute | |
top: 0 | |
left: 0 | |
width: 100% | |
height: 100% | |
background-color: $field-bg-color | |
z-index: 2 | |
transform: rotateX($field-rot) translateZ(0) | |
transform-origin: 50% 50% | |
box-sizing: content-box | |
backface-visibility: hidden | |
.field--alt | |
display: block | |
width: 80% | |
left: 10% | |
transform: rotateX($field-rot) translateZ(-10px) | |
background: black | |
opacity: 0.3 | |
box-shadow: 0 0 40px 30px #000 | |
.field__texture | |
width: 100% | |
height: 100% | |
position: absolute | |
z-index: 3 | |
&.field__texture--gradient | |
background-image: linear-gradient(to top, rgba(0,0,0,0.2), transparent) | |
z-index: 4 | |
.flipped & | |
opacity: 0 | |
&.field__texture--gradient-b | |
opacity: 0 | |
background-image: linear-gradient(to bottom, rgba(0,0,0,0.2), transparent) | |
z-index: 4 | |
.flipped & | |
opacity: 1 | |
.texture & | |
&.field__texture--grass | |
asset('grass2.png') | |
background-repeat: repeat | |
background-size: 75px 75px | |
background-position: -20px -20px | |
.field__side | |
position: absolute | |
top: ($field-y / 2) | |
left: 0 | |
width: 100% | |
height: $field-side-y | |
transform: rotateX($field-rot * 2) translateZ(-($field-y / 2)) | |
transform-origin: 50% 50% | |
background-color: $field-side-color | |
z-index: 9 | |
.texture & | |
background-color: black | |
&:after | |
content: "" | |
top: 0 | |
left: 0 | |
bottom: 0 | |
right: 0 | |
position: absolute | |
opacity: 0.55 | |
asset('mud.png') | |
background-repeat: repeat | |
background-size: 75px 75px | |
background-position: -20px -20px | |
&.field__side--left, | |
&.field__side--right | |
top: 0 | |
left: -($field-side-y) | |
height: 100% | |
width: $field-side-y | |
transform-origin: 100% 50% | |
transform: rotateX($field-rot) rotateY(-90deg) translateZ(0) | |
&.field__side--right | |
left: auto | |
right: 0 | |
&.field__side--back | |
transform: rotateX($field-rot * 2) translateZ(($field-y / 2)) | |
.field__line | |
position: absolute | |
width: 100% | |
height: $line-x | |
z-index: 4 | |
.field__line--goal | |
width: 16% | |
height: 6% | |
border: solid $line-x $line-color | |
border-bottom: none | |
left: 0 | |
right: 0 | |
margin: auto | |
bottom: $field-buffer | |
.field__line--goal--far | |
top: $field-buffer | |
bottom: auto | |
border: solid $line-x $line-color | |
border-top: none | |
.field__line--penalty-arc | |
width: 20% | |
height: 20% | |
overflow: hidden | |
bottom: ($field-buffer + 16%) | |
left: 0 | |
right: 0 | |
margin: auto | |
&:after | |
position: absolute | |
top: 75% | |
width: 100% | |
height: 100% | |
left: 0 | |
content: ' ' | |
display: block | |
border-radius: 50% 50% 0 0 | |
border: solid $line-x $line-color | |
border-bottom: none | |
box-sizing: border-box | |
.field__line--penalty-arc--far | |
bottom: auto | |
top: ($field-buffer + 16%) | |
&:after | |
bottom: 75% | |
top: auto | |
border: solid $line-x $line-color | |
border-top: none | |
border-radius: 0 0 50% 50% | |
.field__line--penalty | |
width: 44% | |
height: 16% | |
border: solid $line-x $line-color | |
border-bottom: none | |
left: 0 | |
right: 0 | |
margin: auto | |
bottom: $field-buffer | |
.field__line--penalty--far | |
top: $field-buffer | |
bottom: auto | |
border: solid $line-x $line-color | |
border-top: none | |
.field__line--outline | |
width: (100% - ($field-buffer * 2)) | |
height: (100% - ($field-buffer * 2)) | |
top: $field-buffer | |
left: $field-buffer | |
border: solid $line-x $line-color | |
.field__line--mid | |
top: 50% | |
width: (100% - ($field-buffer * 2)) | |
left: $field-buffer | |
background-color: $line-color | |
.field__line--circle | |
width: 20% | |
height: 20% | |
top: 0 | |
left: 0 | |
right: 0 | |
bottom: 0 | |
margin: auto | |
border: solid $line-x $line-color | |
border-radius: 50% | |
.debug-btn | |
position: absolute | |
right: 40px | |
top: 40px | |
border: solid 1px #fff | |
border-radius: 10px | |
height: 20px | |
padding: 0 10px | |
color: #fff | |
text-decoration: none | |
line-height: 20px | |
&:hover | |
opacity: 1 | |
background-color: rgba(255, 255, 255, 0.1) | |
&.debug-btn--load | |
top: 80px | |
.player | |
position: absolute | |
height: $player-x + 23px | |
width: $player-x | |
padding-bottom: 23px | |
z-index: 9 | |
left: 50% | |
margin-left: -($player-x / 2) | |
bottom: 50% | |
transform-style: preserve-3d | |
backface-visibility: hidden | |
transition: all 0.2s | |
cursor: pointer | |
.player__placeholder | |
position: absolute | |
opacity: 0 | |
transform: rotateX(90deg) | |
height: 30px | |
width: 30px | |
bottom: -10px | |
left: 0 | |
right: 0 | |
margin: auto | |
border-radius: 50% | |
background-color: rgba(0, 0, 0, 0.2) | |
z-index: 1 | |
&.active | |
.player__placeholder | |
opacity: 1 | |
.player__card | |
position: absolute | |
bottom: 26px | |
left: (($player-x / 2) - ($card-x / 2)) | |
height: $card-y | |
background-color: $colors-card-bg1 | |
opacity: 0 | |
width: $card-x | |
padding: 0 | |
font-size: 18px | |
color: #333 | |
border-radius: 4px | |
z-index: 2 | |
//overflow: hidden | |
&:after | |
position: absolute | |
display: block | |
content: '' | |
height: 1px | |
width: 1px | |
border: solid 10px transparent | |
border-top: solid 10px $colors-card-bg2 | |
bottom: -21px | |
left: 0 | |
right: 0 | |
margin: auto | |
top: auto | |
z-index: 3 | |
i | |
position: absolute | |
top: 0px | |
right: 0px | |
padding: 10px 15px | |
font-size: 24px | |
line-height: 20px | |
color: white | |
opacity: 0.3 | |
cursor: pointer | |
transition: all 0.15s | |
&:hover | |
opacity: 0.6 | |
h3 | |
text-align: center | |
font-weight: normal | |
text-transform: uppercase | |
font-family: montserrat | |
font-size: 19px | |
line-height: 27px | |
color: $colors-text-def | |
color: white | |
padding: 15px 30px 40px | |
margin: 0 0 30px | |
background-color: #eee | |
border-radius: 4px 4px 0 0 | |
background-color: desaturate(darken($body-bg-color, 45%), 10%) | |
span:first-child | |
display: inline-block | |
height: 27px | |
width: 27px | |
border-radius: 50% | |
border: solid 1px #fff | |
line-height: 27px | |
opacity: 0.4 | |
font-size: 18px | |
span:last-child | |
font-size: 14px | |
opacity: 0.4 | |
p | |
color: $colors-text-med | |
font-syle: italic | |
text-align: center | |
.player__card__list | |
padding: 10px 0 | |
font-size: 14px | |
color: $colors-text-med | |
overflow: auto | |
text-align: center | |
li | |
display: inline-block | |
white-space: nowrap | |
text-overflow: ellipsis | |
text-align: center | |
font-size: 15px | |
padding-left: 20px | |
color: $colors-text-def | |
//border-left: solid 1px #ddd | |
span | |
font-size: 12px | |
text-transform: uppercase | |
color: $colors-text-lt | |
&:first-child | |
padding-left: 0 | |
border-left: none | |
.player__card__list--last | |
position: absolute | |
width: 100% | |
bottom: 0 | |
background-color: $colors-card-bg2 | |
margin: 0 | |
padding: 0 | |
border-top: solid 1px #ddd | |
border-radius: 0 0 6px 6px | |
overflow: hidden | |
li | |
width: 50% | |
padding: 10px 0 20px 0 | |
color: $colors-card-txt | |
font-size: 28px | |
line-height: 22px | |
&:last-child | |
border-left: solid 1px #ddd | |
* | |
pointer-events: none | |
.player__img | |
position: absolute | |
top: 0 | |
left: 0 | |
width: $player-x | |
height: $player-x | |
z-index: 4 | |
overflow: hidden | |
border-radius: ($player-x / 2) | |
background-color: #000 | |
border: solid 1px #fff | |
backface-visibility: hidden | |
transition: all 0.2s | |
img | |
width: 100% | |
transition: all 0.2s | |
display: block | |
.player__label | |
position: absolute | |
height: 20px | |
display: inline-block | |
width: auto | |
overflow: visible | |
white-space: nowrap | |
left: -100% | |
right: -100% | |
margin: auto | |
padding: 0 10px | |
line-height: 20px | |
text-align: center | |
border-radius: 10px | |
bottom: 0 | |
opacity: 0 | |
text-transform: upppercase | |
transition: opacity 0.2s | |
z-index: 2 | |
pointer-events: none | |
span | |
background-color: rgba(16, 20, 30, 0.9) | |
color: white | |
font-size: 11px | |
padding: 3px 10px 2px 10px | |
border-radius: 10px | |
text-transform: upppercase | |
&:hover | |
.player__img | |
opacity: 1 | |
.player__label | |
opacity: 1 | |
.texture & | |
background-size: 100% auto | |
// @keyframes spinner | |
// to | |
// transform rotate(360deg) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment