blob: 65f6217a59ddd309bdd696ce8ad3b7ad098e1724 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color: rgb(255, 255, 255);
}
#container {
position: absolute;
left: 510px;
top: 90px;
}
#hud {
position: absolute;
left: 60px;
top: 40px;
font-size: 30px;
}
.image-square {
position: absolute;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0);
transition: 1s;
}
</style>
</head>
<body>
<div id="hud">
<!-- Populated by JavaScript -->
</div>
<div id="container"></div>
<!-- Populated by JavaScript -->
</div>
<script>
var NUMBER_OF_ROWS = 9;
var NUMBER_OF_COLUMNS = 9;
var TOTAL_GRID_WIDTH = 900;
var TOTAL_GRID_HEIGHT = 900;
var PIECE_WIDTH = TOTAL_GRID_WIDTH / NUMBER_OF_COLUMNS;
var PIECE_HEIGHT = TOTAL_GRID_HEIGHT / NUMBER_OF_ROWS;
var NUMBER_OF_PIECES = 70;
var IMAGES = [
{
'palette': [
'rgb(0, 0, 0)',
],
'image': [
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0,
0, 1, 1, 1, 0, 0, 1, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
]
},
{
'palette': [
'rgb(100, 255, 100)',
'rgb(200, 200, 50)',
],
'image': [
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 2, 0, 0, 0, 0,
0, 0, 0, 0, 2, 0, 0, 0, 0,
0, 0, 0, 2, 2, 2, 0, 0, 0,
0, 0, 2, 2, 2, 2, 2, 0, 0,
]
},
{
'palette': [
'rgb(0, 0, 0)',
],
'image': [
0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 1, 0, 1, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 0,
]
},
{
'palette': [
'rgb(50, 50, 50)',
'rgb(100, 100, 255)',
'rgb(200, 200, 50)',
],
'image': [
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 2, 2, 0, 2, 2, 0, 1,
1, 0, 2, 2, 0, 2, 2, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 3, 3, 0, 2, 2, 0, 1,
1, 0, 3, 3, 0, 2, 2, 0, 1,
1, 0, 3, 3, 0, 0, 0, 0, 1,
1, 0, 3, 3, 0, 0, 0, 0, 1,
]
},
{
'palette': [
'rgb(255, 0, 0)',
],
'image': [
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 0, 0, 0, 0, 1, 1,
1, 0, 1, 0, 0, 0, 1, 0, 1,
1, 0, 0, 1, 0, 1, 0, 0, 1,
1, 0, 0, 0, 1, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0,
]
},
{
'palette': [
'rgb(200, 200, 200)',
'rgb(170, 170, 170)',
'rgb(140, 140, 140)',
'rgb(110, 110, 110)',
'rgb(80, 80, 80)',
],
'image': [
1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 0, 0, 0, 0, 0, 0, 0, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3,
0, 0, 0, 0, 0, 0, 0, 0, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5, 5, 5,
]
},
{
'palette': [
'rgb(0, 0, 0)',
'rgb(255, 255, 0)',
],
'image': [
0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 1, 2, 2, 2, 1, 0, 0,
0, 1, 2, 2, 2, 2, 2, 1, 0,
1, 2, 2, 1, 2, 1, 2, 2, 1,
1, 2, 2, 2, 1, 2, 2, 2, 1,
1, 2, 1, 2, 2, 2, 1, 2, 1,
0, 1, 2, 1, 1, 1, 2, 1, 0,
0, 0, 1, 2, 2, 2, 1, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0,
]
},
];
var TRANSITION_MODES = [
{
'name': 'Easing',
'styleParameters': function() {
return {'transition': '1s'}
}
},
{
'name': 'Linear',
'styleParameters': function() {
return {'transition': '1s linear'}
}
},
{
'name': 'Stepped',
'styleParameters': function() {
return {'transition': '1s steps(6)'}
}
},
{
'name': 'Springy',
'styleParameters': function() {
return {'transition':
'cubic-bezier(0.67, 2.26, 0.47, 0.59) transform 1s, ' +
'background-color 1s'}
}
},
{
'name': 'Random-delay easing',
'styleParameters': function() {
return {'transition': '1s ' + Math.random() * 0.5 + 's'}
}
},
{
'name': 'Random-duration easing',
'styleParameters': function() {
return {'transition': (0.6 + Math.random() * 1.0) + 's'}
}
},
]
var pieces = [];
var transition_mode_index = 0;
// This function sets up initial style for each piece.
function setPieceInitialStyle(piece) {
piece.style.width = PIECE_WIDTH + 'px';
piece.style.height = PIECE_HEIGHT + 'px';
}
// This function returns style data for the transform and background-color
// of a piece in its resting position, which depends on its piece index.
function getRestingStyle(pieceIndex, number_of_pieces) {
var kGridCenter = [TOTAL_GRID_WIDTH / 2, TOTAL_GRID_HEIGHT / 2];
var kGridRadius = Math.sqrt(TOTAL_GRID_WIDTH * TOTAL_GRID_WIDTH / 4 +
TOTAL_GRID_HEIGHT * TOTAL_GRID_HEIGHT / 4);
var pieceTheta = 2 * Math.PI * pieceIndex / number_of_pieces;
return {'x': kGridCenter[0] + Math.cos(pieceTheta) * kGridRadius,
'y': kGridCenter[1] + Math.sin(pieceTheta) * kGridRadius,
'rotation': 0,
'scale': 0,
'color': 'rgba(0, 0, 0, 0)',
'transition': '1.0s'};
}
// Functions like getRestingStyle() and getStyleForGridPosition() return
// dictionaries that are not actually CSS styles. This function converts
// them to CSS styles.
function setStyleFromStyleDict(piece, pieceIndex, styleDict) {
piece.style.transform =
'translateX(' + styleDict.x + 'px) translateY(' +
styleDict.y + 'px) rotate(' + styleDict.rotation +
'rad) scale(' + styleDict.scale + ')';
piece.style.transition = styleDict.transition;
piece.style.backgroundColor = styleDict.color;
}
function getStyleForGridPosition(x, y, color) {
var targetStyle = {'x': x * PIECE_WIDTH,
'y': y * PIECE_HEIGHT,
'rotation': 2 * Math.PI * Math.floor(Math.random() * 2),
'scale': 1,
'color': color};
var transition_mode = TRANSITION_MODES[transition_mode_index];
transitionStyleParameters = transition_mode.styleParameters();
for (var attributeName in transitionStyleParameters) {
targetStyle[attributeName] = transitionStyleParameters[attributeName];
}
return targetStyle;
}
function shuffle(array) {
for (var i = 0; i < array.length; ++i) {
var swapIndex = i + Math.floor(Math.random() * array.length - i);
var temp = array[i];
array[i] = array[swapIndex];
array[swapIndex] = temp;
}
}
function refreshImage(image) {
// Prepare an array of piece indices we can use to create our image.
var pieceIndices = new Array(pieces.length);
for (var i = 0; i < pieces.length; ++i) pieceIndices[i] = i;
shuffle(pieceIndices);
var currentPiece = 0;
// Traverse the grid, setting up pieces as we need them.
for (var col = 0; col < NUMBER_OF_COLUMNS; ++col) {
for (var row = 0; row < NUMBER_OF_ROWS; ++row) {
var gridIndex = row * NUMBER_OF_COLUMNS + col;
var gridValue = image.image[gridIndex];
if (gridValue != 0 && currentPiece < pieces.length) {
// Setup a piece for this grid location.
var pieceIndex = pieceIndices[currentPiece++];
var piece = pieces[pieceIndex];
setStyleFromStyleDict(
piece, pieceIndex,
getStyleForGridPosition(col, row, image.palette[gridValue - 1]));
}
}
}
// Set the remaining pieces to their resting style.
for (var i = currentPiece; i < pieces.length; ++i) {
var pieceIndex = pieceIndices[i];
setStyleFromStyleDict(
pieces[pieceIndex], pieceIndex,
getRestingStyle(pieceIndex, pieces.length));
}
}
function onTransitionModeUpdated() {
var transition_mode = TRANSITION_MODES[transition_mode_index];
var hudDiv = document.getElementById('hud');
hudDiv.innerHTML = 'Transition mode: ' + transition_mode.name;
}
window.addEventListener('load', function () {
var containerDiv = document.getElementById('container');
for (var i = 0; i < NUMBER_OF_PIECES; ++i) {
var newDiv = document.createElement('div');
newDiv.className = 'image-square';
pieces.push(newDiv);
setPieceInitialStyle(pieces[i]);
setStyleFromStyleDict(pieces[i], i, getRestingStyle(i, pieces.length));
containerDiv.appendChild(newDiv);
}
pieces = document.getElementsByClassName('image-square');
for (var i = 0; i < pieces.length; ++i) {
setPieceInitialStyle(pieces[i]);
setStyleFromStyleDict(pieces[i], i, getRestingStyle(i, pieces.length));
}
onTransitionModeUpdated();
});
var image_index = -1;
document.addEventListener('keydown', function (e) {
if (e.keyCode == 37) {
// Left arrow key was pressed.
image_index -= 1;
if (image_index < 0) {
image_index = IMAGES.length - 1;
}
refreshImage(IMAGES[image_index]);
} else if (e.keyCode == 39) {
// Right arrow key was pressed.
image_index += 1;
if (image_index >= IMAGES.length) {
image_index = 0;
}
refreshImage(IMAGES[image_index]);
} else if (e.keyCode == 38) {
// Up arrow key was pressed.
transition_mode_index += 1;
if (transition_mode_index >= TRANSITION_MODES.length) {
transition_mode_index = 0;
}
onTransitionModeUpdated();
} else if (e.keyCode == 40) {
// Down arrow key was pressed.
transition_mode_index -= 1;
if (transition_mode_index < 0) {
transition_mode_index = TRANSITION_MODES.length - 1;
}
onTransitionModeUpdated();
}
});
</script>
</body>
</html>