Put cards in square grid and add scaling

pull/18/head
Frode Petterson 2017-01-23 14:12:33 +01:00
parent e60a425f2c
commit 7f800195e2
3 changed files with 119 additions and 39 deletions

20
card.js
View File

@ -17,21 +17,18 @@
var path = H5P.getPath(image.path, id); var path = H5P.getPath(image.path, id);
var width, height, margin, $card; var width, height, margin, $card;
var a = 96;
if (image.width !== undefined && image.height !== undefined) { if (image.width !== undefined && image.height !== undefined) {
if (image.width > image.height) { if (image.width > image.height) {
width = a; width = '100%';
height = image.height * (width / image.width); height = 'auto';
margin = '' + ((a - height) / 2) + 'px 0 0 0';
} }
else { else {
height = a; height = '100%';
width = image.width * (height / image.height); width = 'auto';
margin = '0 0 0 ' + ((a - width) / 2) + 'px';
} }
} }
else { else {
width = height = a; width = height = '100%';
} }
/** /**
@ -81,13 +78,14 @@
*/ */
self.appendTo = function ($container) { self.appendTo = function ($container) {
// TODO: Translate alt attr // TODO: Translate alt attr
$card = $('<li class="h5p-memory-card" role="button" tabindex="1">' + $card = $('<li class="h5p-memory-wrap"><div class="h5p-memory-card" role="button" tabindex="1">' +
'<div class="h5p-front"></div>' + '<div class="h5p-front"></div>' +
'<div class="h5p-back">' + '<div class="h5p-back">' +
'<img src="' + path + '" alt="Memory Card" width="' + width + '" height="' + height + '"' + (margin === undefined ? '' : ' style="margin:' + margin + '"') + '/>' + '<img src="' + path + '" alt="Memory Card" style="width:' + width + ';height:' + height + '"/>' +
'</div>' + '</div>' +
'</li>') '</div></li>')
.appendTo($container) .appendTo($container)
.children('.h5p-memory-card')
.children('.h5p-front') .children('.h5p-front')
.click(function () { .click(function () {
self.flip(); self.flip();

View File

@ -1,17 +1,21 @@
.h5p-memory-game { .h5p-memory-game {
overflow: hidden; overflow: hidden;
} }
html .h5p-memory-game > ul { .h5p-memory-game > ul {
list-style: none; list-style: none !important;
padding: 0; padding: 0.25em 0.5em !important;
margin: 0; /*padding: 0 !important;*/
overflow: hidden; margin: 0 !important;
overflow: hidden !important;
font-size: 16px;
box-sizing: border-box;
-moz-box-sizing: border-box;
} }
.h5p-memory-game .h5p-memory-card, .h5p-memory-game .h5p-memory-card,
.h5p-memory-game .h5p-memory-card .h5p-back, .h5p-memory-game .h5p-memory-card .h5p-back,
.h5p-memory-game .h5p-memory-card .h5p-front { .h5p-memory-game .h5p-memory-card .h5p-front {
width: 100px; width: 6.25em;
height: 100px; height: 6.25em;
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
@ -19,17 +23,24 @@ html .h5p-memory-game > ul {
} }
.h5p-memory-game img { .h5p-memory-game img {
-webkit-user-drag: none; -webkit-user-drag: none;
display: inline-block !important;
margin: auto !important;
vertical-align: middle;
}
.h5p-memory-game .h5p-memory-wrap {
float: left;
text-align: center;
} }
.h5p-memory-game .h5p-memory-card { .h5p-memory-game .h5p-memory-card {
float: left; display: inline-block;
outline: none; outline: none;
position: relative; position: relative;
margin: 1em; margin: 0.75em 0.5em;
padding: 0; padding: 0;
background: transparent; background: transparent;
-webkit-perspective: 400px; -webkit-perspective: 25em;
-moz-perspective: 400px; -moz-perspective: 25em;
perspective: 400px; perspective: 25em;
-webkit-transition: opacity 0.4s, filter 0.4s; -webkit-transition: opacity 0.4s, filter 0.4s;
-moz-transition: opacity 0.4s, filter 0.4s; -moz-transition: opacity 0.4s, filter 0.4s;
transition: opacity 0.4s, filter 0.4s; transition: opacity 0.4s, filter 0.4s;
@ -61,17 +72,16 @@ html .h5p-memory-game > ul {
} }
.h5p-memory-game .h5p-memory-card .h5p-front { .h5p-memory-game .h5p-memory-card .h5p-front {
cursor: pointer; cursor: pointer;
text-align: center;
} }
.h5p-memory-game .h5p-memory-card .h5p-front:hover { .h5p-memory-game .h5p-memory-card .h5p-front:hover {
background: #dfdfdf; background: #dfdfdf;
} }
.h5p-memory-game .h5p-memory-card .h5p-front:before { .h5p-memory-game .h5p-memory-card .h5p-front:before {
position: absolute;
content: "?"; content: "?";
font-size: 60px; font-size: 3.75em;
color: #909090; color: #909090;
line-height: 100px; line-height: 1.67em;
left: 35px;
} }
.h5p-memory-game .h5p-memory-card .h5p-front:after { .h5p-memory-game .h5p-memory-card .h5p-front:after {
content: ""; content: "";
@ -88,6 +98,8 @@ html .h5p-memory-game > ul {
background-image: radial-gradient(ellipse closest-side, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%); background-image: radial-gradient(ellipse closest-side, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%);
} }
.h5p-memory-game .h5p-memory-card .h5p-back { .h5p-memory-game .h5p-memory-card .h5p-back {
line-height: 5.9em;
text-align: center;
background: #f0f0f0; background: #f0f0f0;
-webkit-transform: rotateY(-180deg); -webkit-transform: rotateY(-180deg);
-moz-transform: rotateY(-180deg); -moz-transform: rotateY(-180deg);
@ -163,9 +175,9 @@ html .h5p-memory-game > ul {
left: 50%; left: 50%;
margin-left: -10em; margin-left: -10em;
box-shadow: 0 0 1em #666; box-shadow: 0 0 1em #666;
-webkit-transform: translateZ(24px); -webkit-transform: translateZ(1.5em);
-moz-transform: translateZ(24px); -moz-transform: translateZ(1.5em);
transform: translateZ(24px); transform: translateZ(1.5em);
} }
.h5p-memory-game .h5p-memory-image { .h5p-memory-game .h5p-memory-image {
float: left; float: left;
@ -175,6 +187,9 @@ html .h5p-memory-game > ul {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
border-radius: 4px; border-radius: 4px;
background: #f0f0f0; background: #f0f0f0;
width: 100px; width: 6.25em;
height: 100px; height: 6.25em;
}
.h5p-memory-game .h5p-row-break {
clear: left;
} }

View File

@ -1,5 +1,11 @@
H5P.MemoryGame = (function (EventDispatcher, $) { H5P.MemoryGame = (function (EventDispatcher, $) {
// We don't want to go smaller than 100px per card(including the required margin)
var CARD_MIN_SIZE = 100; // PX
var CARD_STD_SIZE = 116; // PX
var STD_FONT_SIZE = 16; // PX
var LIST_PADDING = 1; // EMs
/** /**
* Memory Game Constructor * Memory Game Constructor
* *
@ -13,7 +19,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
// Initialize event inheritance // Initialize event inheritance
EventDispatcher.call(self); EventDispatcher.call(self);
var flipped, timer, counter, popup, $feedback; var flipped, timer, counter, popup, $feedback, $wrapper, maxWidth, numCols;
var cards = []; var cards = [];
var removed = 0; var removed = 0;
@ -132,7 +138,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
self.attach = function ($container) { self.attach = function ($container) {
this.triggerXAPI('attempted'); this.triggerXAPI('attempted');
// TODO: Only create on first attach! // TODO: Only create on first attach!
$container.addClass('h5p-memory-game').html(''); $wrapper = $container.addClass('h5p-memory-game').html('');
// Add cards to list // Add cards to list
var $list = $('<ul/>'); var $list = $('<ul/>');
@ -172,6 +178,67 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
}); });
} }
}; };
/**
* Will try to scale the game so that it fits within its container.
* Puts the cards into a grid layout to make it as square as possible  
* which improves the playability on multiple devices.
*
* @private
*/
function scaleGameSize() {
// Check how much space we have available
var $list = $wrapper.children('ul');
var newMaxWidth = parseFloat(window.getComputedStyle($list[0]).width);
if (maxWidth === newMaxWidth) {
return; // Same size, no need to recalculate
}
else {
maxWidth = newMaxWidth;
}
// Get the card holders
var $elements = $list.children();
if ($elements.length < 4) {
return; // No need to proceed
}
// Determine the optimal number of columns
var newNumCols = Math.ceil(Math.sqrt($elements.length));
// Do not exceed the max number of columns
var maxCols = Math.floor(maxWidth / CARD_MIN_SIZE);
if (newNumCols > maxCols) {
newNumCols = maxCols;
}
if (numCols !== newNumCols) {
// We need to change layout
numCols = newNumCols;
// Calculate new column size in percentage and round it down (we don't
// want things sticking out…)
var colSize = Math.floor((100 / numCols) * 10000) / 10000;
$elements.css('width', colSize + '%').each(function (i, e) {
if (i === numCols) {
$(e).addClass('h5p-row-break');
}
});
}
// Calculate how much one percentage of the standard/default size is
var onePercentage = ((CARD_STD_SIZE * numCols) + STD_FONT_SIZE) / 100;
var paddingSize = (STD_FONT_SIZE * LIST_PADDING) / onePercentage;
var cardSize = (100 - paddingSize) / numCols;
var fontSize = (((maxWidth * (cardSize / 100)) * STD_FONT_SIZE) / CARD_STD_SIZE);
// We use font size to evenly scale all parts of the cards.
$list.css('font-size', fontSize + 'px');
// due to rounding errors in browsers the margins may vary a bit…
}
self.on('resize', scaleGameSize);
} }
// Extends the event dispatcher // Extends the event dispatcher