Put cards in square grid and add scaling
parent
e60a425f2c
commit
7f800195e2
20
card.js
20
card.js
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue