diff --git a/index.html b/index.html index f8ad90e4aecbbef5982e9399db1e15885ca03c37..8e86f47cff27d0c8acf2cf51772cb0d9cbd7d9a5 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@ - + diff --git a/js/html_actuator.js b/js/html_actuator.js index 189208732df26b134f69359e2dec87cf2c1029e8..374a9ee9dd7ad966fe3f516806be9045e1774db7 100644 --- a/js/html_actuator.js +++ b/js/html_actuator.js @@ -46,25 +46,27 @@ HTMLActuator.prototype.clearContainer = function (container) { HTMLActuator.prototype.addTile = function (tile) { var self = this; - var element = document.createElement("div"); + var wrapper = document.createElement("div"); + var inner = document.createElement("div"); var position = tile.previousPosition || { x: tile.x, y: tile.y }; positionClass = this.positionClass(position); // We can't use classlist because it somehow glitches when replacing classes var classes = ["tile", "tile-" + tile.value, positionClass]; - this.applyClasses(element, classes); + this.applyClasses(wrapper, classes); - element.textContent = tile.value; + inner.classList.add("tile-inner"); + inner.textContent = tile.value; if (tile.previousPosition) { // Make sure that the tile gets rendered in the previous position first window.requestAnimationFrame(function () { classes[2] = self.positionClass({ x: tile.x, y: tile.y }); - self.applyClasses(element, classes); // Update the position + self.applyClasses(wrapper, classes); // Update the position }); } else if (tile.mergedFrom) { classes.push("tile-merged"); - this.applyClasses(element, classes); + this.applyClasses(wrapper, classes); // Render the tiles that merged tile.mergedFrom.forEach(function (merged) { @@ -72,11 +74,14 @@ HTMLActuator.prototype.addTile = function (tile) { }); } else { classes.push("tile-new"); - this.applyClasses(element, classes); + this.applyClasses(wrapper, classes); } + // Add the inner part of the tile to the wrapper + wrapper.appendChild(inner); + // Put the tile on the board - this.tileContainer.appendChild(element); + this.tileContainer.appendChild(wrapper); }; HTMLActuator.prototype.applyClasses = function (element, classes) { diff --git a/style/helpers.scss b/style/helpers.scss index 7d0a61d339971a6c2df14885e2967026213bb88f..d6fdd6c859631abe8e5a1a5f08b2faa35f5e28e4 100644 --- a/style/helpers.scss +++ b/style/helpers.scss @@ -24,11 +24,31 @@ @mixin transition($args...) { -webkit-transition: $args; -moz-transition: $args; + transition: $args; } @mixin transition-property($args...) { -webkit-transition-property: $args; -moz-transition-property: $args; + transition-property: $args; +} + +@mixin animation($args...) { + -webkit-animation: $args; + -moz-animation: $args; + animation: $args; +} + +@mixin animation-fill-mode($args...) { + -webkit-animation-fill-mode: $args; + -moz-animation-fill-mode: $args; + animation: $args; +} + +@mixin transform($args...) { + -webkit-transform: $args; + -moz-transform: $args; + transform: $args; } // Keyframe animations @@ -44,16 +64,6 @@ } } -@mixin animation($str) { - -webkit-animation: #{$str}; - -moz-animation: #{$str}; -} - -@mixin animation-fill-mode($str) { - -webkit-animation-fill-mode: #{$str}; - -moz-animation-fill-mode: #{$str}; -} - // Media queries @mixin smaller($width) { @media screen and (max-width: $width) { diff --git a/style/main.css b/style/main.css index 6dbbaed348a727e0c1d7cbcbaa8c7fcf3c793a2a..073cbefa658b391eed42465a37817661927e8380 100644 --- a/style/main.css +++ b/style/main.css @@ -87,8 +87,10 @@ h1.title { z-index: 100; -webkit-animation: move-up 600ms ease-in; -moz-animation: move-up 600ms ease-in; + animation: move-up 600ms ease-in; -webkit-animation-fill-mode: both; - -moz-animation-fill-mode: both; } + -moz-animation-fill-mode: both; + animation: both; } .score-container:after { content: "Score"; } @@ -168,8 +170,10 @@ hr { text-align: center; -webkit-animation: fade-in 800ms ease 1200ms; -moz-animation: fade-in 800ms ease 1200ms; + animation: fade-in 800ms ease 1200ms; -webkit-animation-fill-mode: both; - -moz-animation-fill-mode: both; } + -moz-animation-fill-mode: both; + animation: both; } .game-container .game-message p { font-size: 60px; font-weight: bold; @@ -226,229 +230,252 @@ hr { position: absolute; z-index: 2; } -.tile { - width: 106.25px; - height: 106.25px; +.tile, .tile .tile-inner { + width: 107px; + height: 107px; line-height: 116.25px; } - .tile.tile-position-1-1 { - position: absolute; - left: 0px; - top: 0px; } - .tile.tile-position-1-2 { - position: absolute; - left: 0px; - top: 121px; } - .tile.tile-position-1-3 { - position: absolute; - left: 0px; - top: 243px; } - .tile.tile-position-1-4 { - position: absolute; - left: 0px; - top: 364px; } - .tile.tile-position-2-1 { - position: absolute; - left: 121px; - top: 0px; } - .tile.tile-position-2-2 { - position: absolute; - left: 121px; - top: 121px; } - .tile.tile-position-2-3 { - position: absolute; - left: 121px; - top: 243px; } - .tile.tile-position-2-4 { - position: absolute; - left: 121px; - top: 364px; } - .tile.tile-position-3-1 { - position: absolute; - left: 243px; - top: 0px; } - .tile.tile-position-3-2 { - position: absolute; - left: 243px; - top: 121px; } - .tile.tile-position-3-3 { - position: absolute; - left: 243px; - top: 243px; } - .tile.tile-position-3-4 { - position: absolute; - left: 243px; - top: 364px; } - .tile.tile-position-4-1 { - position: absolute; - left: 364px; - top: 0px; } - .tile.tile-position-4-2 { - position: absolute; - left: 364px; - top: 121px; } - .tile.tile-position-4-3 { - position: absolute; - left: 364px; - top: 243px; } - .tile.tile-position-4-4 { - position: absolute; - left: 364px; - top: 364px; } +.tile.tile-position-1-1 { + -webkit-transform: translate(0px, 0px); + -moz-transform: translate(0px, 0px); + transform: translate(0px, 0px); } +.tile.tile-position-1-2 { + -webkit-transform: translate(0px, 121px); + -moz-transform: translate(0px, 121px); + transform: translate(0px, 121px); } +.tile.tile-position-1-3 { + -webkit-transform: translate(0px, 242px); + -moz-transform: translate(0px, 242px); + transform: translate(0px, 242px); } +.tile.tile-position-1-4 { + -webkit-transform: translate(0px, 363px); + -moz-transform: translate(0px, 363px); + transform: translate(0px, 363px); } +.tile.tile-position-2-1 { + -webkit-transform: translate(121px, 0px); + -moz-transform: translate(121px, 0px); + transform: translate(121px, 0px); } +.tile.tile-position-2-2 { + -webkit-transform: translate(121px, 121px); + -moz-transform: translate(121px, 121px); + transform: translate(121px, 121px); } +.tile.tile-position-2-3 { + -webkit-transform: translate(121px, 242px); + -moz-transform: translate(121px, 242px); + transform: translate(121px, 242px); } +.tile.tile-position-2-4 { + -webkit-transform: translate(121px, 363px); + -moz-transform: translate(121px, 363px); + transform: translate(121px, 363px); } +.tile.tile-position-3-1 { + -webkit-transform: translate(242px, 0px); + -moz-transform: translate(242px, 0px); + transform: translate(242px, 0px); } +.tile.tile-position-3-2 { + -webkit-transform: translate(242px, 121px); + -moz-transform: translate(242px, 121px); + transform: translate(242px, 121px); } +.tile.tile-position-3-3 { + -webkit-transform: translate(242px, 242px); + -moz-transform: translate(242px, 242px); + transform: translate(242px, 242px); } +.tile.tile-position-3-4 { + -webkit-transform: translate(242px, 363px); + -moz-transform: translate(242px, 363px); + transform: translate(242px, 363px); } +.tile.tile-position-4-1 { + -webkit-transform: translate(363px, 0px); + -moz-transform: translate(363px, 0px); + transform: translate(363px, 0px); } +.tile.tile-position-4-2 { + -webkit-transform: translate(363px, 121px); + -moz-transform: translate(363px, 121px); + transform: translate(363px, 121px); } +.tile.tile-position-4-3 { + -webkit-transform: translate(363px, 242px); + -moz-transform: translate(363px, 242px); + transform: translate(363px, 242px); } +.tile.tile-position-4-4 { + -webkit-transform: translate(363px, 363px); + -moz-transform: translate(363px, 363px); + transform: translate(363px, 363px); } .tile { - border-radius: 3px; - background: #eee4da; - text-align: center; - font-weight: bold; - z-index: 10; - font-size: 55px; + position: absolute; -webkit-transition: 100ms ease-in-out; -moz-transition: 100ms ease-in-out; - -webkit-transition-property: top, left; - -moz-transition-property: top, left; } - .tile.tile-2 { + transition: 100ms ease-in-out; + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + transition-property: transform; } + .tile .tile-inner { + border-radius: 3px; + background: #eee4da; + text-align: center; + font-weight: bold; + z-index: 10; + font-size: 55px; } + .tile.tile-2 .tile-inner { background: #eee4da; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); } - .tile.tile-4 { + .tile.tile-4 .tile-inner { background: #ede0c8; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); } - .tile.tile-8 { + .tile.tile-8 .tile-inner { color: #f9f6f2; background: #f2b179; } - .tile.tile-16 { + .tile.tile-16 .tile-inner { color: #f9f6f2; background: #f59563; } - .tile.tile-32 { + .tile.tile-32 .tile-inner { color: #f9f6f2; background: #f67c5f; } - .tile.tile-64 { + .tile.tile-64 .tile-inner { color: #f9f6f2; background: #f65e3b; } - .tile.tile-128 { + .tile.tile-128 .tile-inner { color: #f9f6f2; background: #edcf72; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.2381), inset 0 0 0 1px rgba(255, 255, 255, 0.14286); font-size: 45px; } @media screen and (max-width: 480px) { - .tile.tile-128 { + .tile.tile-128 .tile-inner { font-size: 25px; } } - .tile.tile-256 { + .tile.tile-256 .tile-inner { color: #f9f6f2; background: #edcc61; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.31746), inset 0 0 0 1px rgba(255, 255, 255, 0.19048); font-size: 45px; } @media screen and (max-width: 480px) { - .tile.tile-256 { + .tile.tile-256 .tile-inner { font-size: 25px; } } - .tile.tile-512 { + .tile.tile-512 .tile-inner { color: #f9f6f2; background: #edc850; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.39683), inset 0 0 0 1px rgba(255, 255, 255, 0.2381); font-size: 45px; } @media screen and (max-width: 480px) { - .tile.tile-512 { + .tile.tile-512 .tile-inner { font-size: 25px; } } - .tile.tile-1024 { + .tile.tile-1024 .tile-inner { color: #f9f6f2; background: #edc53f; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.47619), inset 0 0 0 1px rgba(255, 255, 255, 0.28571); font-size: 35px; } @media screen and (max-width: 480px) { - .tile.tile-1024 { + .tile.tile-1024 .tile-inner { font-size: 15px; } } - .tile.tile-2048 { + .tile.tile-2048 .tile-inner { color: #f9f6f2; background: #edc22e; box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.55556), inset 0 0 0 1px rgba(255, 255, 255, 0.33333); font-size: 35px; } @media screen and (max-width: 480px) { - .tile.tile-2048 { + .tile.tile-2048 .tile-inner { font-size: 15px; } } @-webkit-keyframes appear { 0% { opacity: 0; -webkit-transform: scale(0); - -moz-transform: scale(0); } + -moz-transform: scale(0); + transform: scale(0); } 100% { opacity: 1; -webkit-transform: scale(1); - -moz-transform: scale(1); } } + -moz-transform: scale(1); + transform: scale(1); } } @-moz-keyframes appear { 0% { opacity: 0; -webkit-transform: scale(0); - -moz-transform: scale(0); } + -moz-transform: scale(0); + transform: scale(0); } 100% { opacity: 1; -webkit-transform: scale(1); - -moz-transform: scale(1); } } + -moz-transform: scale(1); + transform: scale(1); } } @keyframes appear { 0% { opacity: 0; -webkit-transform: scale(0); - -moz-transform: scale(0); } + -moz-transform: scale(0); + transform: scale(0); } 100% { opacity: 1; -webkit-transform: scale(1); - -moz-transform: scale(1); } } + -moz-transform: scale(1); + transform: scale(1); } } -.tile-new { +.tile-new .tile-inner { -webkit-animation: appear 200ms ease 100ms; -moz-animation: appear 200ms ease 100ms; - -webkit-animation-fill-mode: both; - -moz-animation-fill-mode: both; } + animation: appear 200ms ease 100ms; + -webkit-animation-fill-mode: backwards; + -moz-animation-fill-mode: backwards; + animation: backwards; } @-webkit-keyframes pop { 0% { -webkit-transform: scale(0); - -moz-transform: scale(0); } + -moz-transform: scale(0); + transform: scale(0); } 50% { -webkit-transform: scale(1.2); - -moz-transform: scale(1.2); } + -moz-transform: scale(1.2); + transform: scale(1.2); } 100% { -webkit-transform: scale(1); - -moz-transform: scale(1); } } + -moz-transform: scale(1); + transform: scale(1); } } @-moz-keyframes pop { 0% { -webkit-transform: scale(0); - -moz-transform: scale(0); } + -moz-transform: scale(0); + transform: scale(0); } 50% { -webkit-transform: scale(1.2); - -moz-transform: scale(1.2); } + -moz-transform: scale(1.2); + transform: scale(1.2); } 100% { -webkit-transform: scale(1); - -moz-transform: scale(1); } } + -moz-transform: scale(1); + transform: scale(1); } } @keyframes pop { 0% { -webkit-transform: scale(0); - -moz-transform: scale(0); } + -moz-transform: scale(0); + transform: scale(0); } 50% { -webkit-transform: scale(1.2); - -moz-transform: scale(1.2); } + -moz-transform: scale(1.2); + transform: scale(1.2); } 100% { -webkit-transform: scale(1); - -moz-transform: scale(1); } } + -moz-transform: scale(1); + transform: scale(1); } } -.tile-merged { +.tile-merged .tile-inner { z-index: 20; -webkit-animation: pop 200ms ease 100ms; -moz-animation: pop 200ms ease 100ms; - -webkit-animation-fill-mode: both; - -moz-animation-fill-mode: both; } + animation: pop 200ms ease 100ms; + -webkit-animation-fill-mode: backwards; + -moz-animation-fill-mode: backwards; + animation: backwards; } .game-intro { margin-bottom: 0; } @@ -514,8 +541,10 @@ hr { text-align: center; -webkit-animation: fade-in 800ms ease 1200ms; -moz-animation: fade-in 800ms ease 1200ms; + animation: fade-in 800ms ease 1200ms; -webkit-animation-fill-mode: both; - -moz-animation-fill-mode: both; } + -moz-animation-fill-mode: both; + animation: both; } .game-container .game-message p { font-size: 60px; font-weight: bold; @@ -572,79 +601,79 @@ hr { position: absolute; z-index: 2; } - .tile { - width: 57.5px; - height: 57.5px; + .tile, .tile .tile-inner { + width: 58px; + height: 58px; line-height: 67.5px; } - .tile.tile-position-1-1 { - position: absolute; - left: 0px; - top: 0px; } - .tile.tile-position-1-2 { - position: absolute; - left: 0px; - top: 68px; } - .tile.tile-position-1-3 { - position: absolute; - left: 0px; - top: 135px; } - .tile.tile-position-1-4 { - position: absolute; - left: 0px; - top: 203px; } - .tile.tile-position-2-1 { - position: absolute; - left: 68px; - top: 0px; } - .tile.tile-position-2-2 { - position: absolute; - left: 68px; - top: 68px; } - .tile.tile-position-2-3 { - position: absolute; - left: 68px; - top: 135px; } - .tile.tile-position-2-4 { - position: absolute; - left: 68px; - top: 203px; } - .tile.tile-position-3-1 { - position: absolute; - left: 135px; - top: 0px; } - .tile.tile-position-3-2 { - position: absolute; - left: 135px; - top: 68px; } - .tile.tile-position-3-3 { - position: absolute; - left: 135px; - top: 135px; } - .tile.tile-position-3-4 { - position: absolute; - left: 135px; - top: 203px; } - .tile.tile-position-4-1 { - position: absolute; - left: 203px; - top: 0px; } - .tile.tile-position-4-2 { - position: absolute; - left: 203px; - top: 68px; } - .tile.tile-position-4-3 { - position: absolute; - left: 203px; - top: 135px; } - .tile.tile-position-4-4 { - position: absolute; - left: 203px; - top: 203px; } + .tile.tile-position-1-1 { + -webkit-transform: translate(0px, 0px); + -moz-transform: translate(0px, 0px); + transform: translate(0px, 0px); } + .tile.tile-position-1-2 { + -webkit-transform: translate(0px, 67px); + -moz-transform: translate(0px, 67px); + transform: translate(0px, 67px); } + .tile.tile-position-1-3 { + -webkit-transform: translate(0px, 135px); + -moz-transform: translate(0px, 135px); + transform: translate(0px, 135px); } + .tile.tile-position-1-4 { + -webkit-transform: translate(0px, 202px); + -moz-transform: translate(0px, 202px); + transform: translate(0px, 202px); } + .tile.tile-position-2-1 { + -webkit-transform: translate(67px, 0px); + -moz-transform: translate(67px, 0px); + transform: translate(67px, 0px); } + .tile.tile-position-2-2 { + -webkit-transform: translate(67px, 67px); + -moz-transform: translate(67px, 67px); + transform: translate(67px, 67px); } + .tile.tile-position-2-3 { + -webkit-transform: translate(67px, 135px); + -moz-transform: translate(67px, 135px); + transform: translate(67px, 135px); } + .tile.tile-position-2-4 { + -webkit-transform: translate(67px, 202px); + -moz-transform: translate(67px, 202px); + transform: translate(67px, 202px); } + .tile.tile-position-3-1 { + -webkit-transform: translate(135px, 0px); + -moz-transform: translate(135px, 0px); + transform: translate(135px, 0px); } + .tile.tile-position-3-2 { + -webkit-transform: translate(135px, 67px); + -moz-transform: translate(135px, 67px); + transform: translate(135px, 67px); } + .tile.tile-position-3-3 { + -webkit-transform: translate(135px, 135px); + -moz-transform: translate(135px, 135px); + transform: translate(135px, 135px); } + .tile.tile-position-3-4 { + -webkit-transform: translate(135px, 202px); + -moz-transform: translate(135px, 202px); + transform: translate(135px, 202px); } + .tile.tile-position-4-1 { + -webkit-transform: translate(202px, 0px); + -moz-transform: translate(202px, 0px); + transform: translate(202px, 0px); } + .tile.tile-position-4-2 { + -webkit-transform: translate(202px, 67px); + -moz-transform: translate(202px, 67px); + transform: translate(202px, 67px); } + .tile.tile-position-4-3 { + -webkit-transform: translate(202px, 135px); + -moz-transform: translate(202px, 135px); + transform: translate(202px, 135px); } + .tile.tile-position-4-4 { + -webkit-transform: translate(202px, 202px); + -moz-transform: translate(202px, 202px); + transform: translate(202px, 202px); } .game-container { margin-top: 20px; } - .tile { + .tile .tile-inner { font-size: 35px; } .game-message p { @@ -710,8 +739,10 @@ hr { pointer-events: none; -webkit-transition: 400ms ease; -moz-transition: 400ms ease; + transition: 400ms ease; -webkit-transition-property: top, opacity; - -moz-transition-property: top, opacity; } + -moz-transition-property: top, opacity; + transition-property: top, opacity; } .btc-donate .address:after { position: absolute; border-top: 10px solid #bbada0; diff --git a/style/main.scss b/style/main.scss index e4915dbb5fb003fb14223489ec503b82953b853e..519365961ff8798f400c366750687bdc5cde897b 100644 --- a/style/main.scss +++ b/style/main.scss @@ -280,17 +280,19 @@ hr { } .tile { - width: $tile-size; - height: $tile-size; - line-height: $tile-size + 10px; + &, .tile-inner { + width: ceil($tile-size); + height: ceil($tile-size); + line-height: $tile-size + 10px; + } // Build position classes @for $x from 1 through $grid-row-cells { @for $y from 1 through $grid-row-cells { &.tile-position-#{$x}-#{$y} { - position: absolute; - left: round(($tile-size + $grid-spacing) * ($x - 1)); - top: round(($tile-size + $grid-spacing) * ($y - 1)); + $xPos: floor(($tile-size + $grid-spacing) * ($x - 1)); + $yPos: floor(($tile-size + $grid-spacing) * ($y - 1)); + @include transform(translate($xPos, $yPos)); } } } @@ -301,17 +303,24 @@ hr { @include game-field; .tile { - border-radius: $tile-border-radius; + position: absolute; // Makes transforms relative to the top-left corner - background: $tile-color; - text-align: center; - font-weight: bold; - z-index: 10; + .tile-inner { + border-radius: $tile-border-radius; - font-size: 55px; + background: $tile-color; + text-align: center; + font-weight: bold; + z-index: 10; + + font-size: 55px; + } + // Movement transition @include transition($transition-speed ease-in-out); - @include transition-property(top, left); + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + transition-property: transform; $base: 2; $exponent: 1; @@ -334,7 +343,7 @@ hr { @while $exponent <= $limit { $power: pow($base, $exponent); - &.tile-#{$power} { + &.tile-#{$power} .tile-inner { // Calculate base background color $gold-percent: ($exponent - 1) / ($limit - 1) * 100; $mixed-background: mix($tile-gold-color, $tile-color, $gold-percent); @@ -387,43 +396,38 @@ hr { @include keyframes(appear) { 0% { opacity: 0; - -webkit-transform: scale(0); - -moz-transform: scale(0); + @include transform(scale(0)); } 100% { opacity: 1; - -webkit-transform: scale(1); - -moz-transform: scale(1); + @include transform(scale(1)); } } -.tile-new { +.tile-new .tile-inner { @include animation(appear 200ms ease $transition-speed); - @include animation-fill-mode(both); + @include animation-fill-mode(backwards); } @include keyframes(pop) { 0% { - -webkit-transform: scale(0); - -moz-transform: scale(0); + @include transform(scale(0)); } 50% { - -webkit-transform: scale(1.2); - -moz-transform: scale(1.2); + @include transform(scale(1.2)); } 100% { - -webkit-transform: scale(1); - -moz-transform: scale(1); + @include transform(scale(1)); } } -.tile-merged { +.tile-merged .tile-inner { z-index: 20; @include animation(pop 200ms ease $transition-speed); - @include animation-fill-mode(both); + @include animation-fill-mode(backwards); } .game-intro { @@ -471,11 +475,6 @@ hr { margin: 0 auto; } - // .scores-container { - // float: left; - // clear: left; - // } - .score-container, .best-container { margin-top: 0; padding: 15px 10px; @@ -494,7 +493,7 @@ hr { } // Rest of the font-size adjustments in the tile class - .tile { + .tile .tile-inner { font-size: 35px; }