Веблет для вашего досуга. Простой сайт для игры в Пазл
Простой код html. Кидаете в любой текстовый редактор, сохраняете в формате html. Запускаете, выбираете любую картинку и играете. Работает со смартфона
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пазл</title>
<style>
body {
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
background: linear-gradient(135deg, #e0eafc, #cfdef3);
font-family: 'Segoe UI', Arial, sans-serif;
min-height: 100vh;
}
#controls {
background: rgba(255, 255, 255, 0.9);
padding: 15px;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 10px;
max-width: 320px;
width: 100%;
margin-bottom: 20px;
}
#imageInput, #difficulty, button {
padding: 10px;
border: none;
border-radius: 8px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
}
#imageInput {
background: #f5f5f5;
}
#imageInput:hover {
background: #e0e0e0;
}
#difficulty {
background: #fff;
appearance: none;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
}
button {
background: #6b7280;
color: white;
}
button:hover {
background: #4b5563;
}
#imagePreview {
max-width: 100%;
height: auto;
border-radius: 8px;
margin-top: 10px;
display: none;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
#gameContainer {
position: relative;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
}
.puzzle-piece {
position: absolute;
border: 1px solid rgba(255, 255, 255, 0.2);
box-sizing: border-box;
cursor: move;
user-select: none;
touch-action: none;
transition: transform 0.2s ease;
}
.puzzle-piece:hover {
transform: scale(1.02);
}
.puzzle-piece.movable {
z-index: 10;
}
.puzzle-piece.fixed {
z-index: 1;
}
#winMessage {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(255, 255, 255, 0.95);
padding: 20px 40px;
border-radius: 12px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
text-align: center;
font-size: 20px;
color: #333;
z-index: 100; /* Устанавливаем высокий z-index */
}
#winMessage button {
margin-top: 15px;
background: #10b981;
}
#winMessage button:hover {
background: #059669;
}
</style>
</head>
<body>
<div id="controls">
<input type="file" id="imageInput" accept="image/*">
<select id="difficulty">
<option value="3">Легко (3x3)</option>
<option value="4">Средне (4x4)</option>
<option value="5">Сложно (5x5)</option>
</select>
<button onclick="startGame()">Начать</button>
<img id="imagePreview">
</div>
<div id="gameContainer"></div>
<div id="winMessage">
<p>Пазл собран! Поздравляем!</p>
<button onclick="resetGame()">Сыграть снова</button>
</div>
<script>
let img = new Image();
let pieces = [];
let gridSize;
let pieceWidth, pieceHeight;
let container = document.getElementById('gameContainer');
let winMessage = document.getElementById('winMessage');
document.getElementById('imageInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(event) {
img.src = event.target.result;
img.onload = function() {
document.getElementById('imagePreview').src = img.src;
document.getElementById('imagePreview').style.display = 'block';
}
}
reader.readAsDataURL(file);
}
});
function startGame() {
if (!img.src) {
alert('Загрузите изображение!');
return;
}
gridSize = parseInt(document.getElementById('difficulty').value);
container.innerHTML = '';
winMessage.style.display = 'none';
const maxWidth = Math.min(window.innerWidth * 0.9, img.width);
const maxHeight = Math.min(window.innerHeight * 0.7, img.height);
const aspectRatio = img.width / img.height;
let width = maxWidth;
let height = width / aspectRatio;
if (height > maxHeight) {
height = maxHeight;
width = height * aspectRatio;
}
container.style.width = width + 'px';
container.style.height = height + 'px';
pieceWidth = width / gridSize;
pieceHeight = height / gridSize;
createPuzzlePieces();
shufflePieces();
}
function createPuzzlePieces() {
pieces = [];
for (let y = 0; y < gridSize; y++) {
for (let x = 0; x < gridSize; x++) {
const piece = document.createElement('div');
piece.className = 'puzzle-piece movable';
piece.style.width = pieceWidth + 'px';
piece.style.height = pieceHeight + 'px';
piece.style.backgroundImage = `url(${img.src})`;
piece.style.backgroundSize = `${container.offsetWidth}px ${container.offsetHeight}px`;
piece.style.backgroundPosition = `${-x * pieceWidth}px ${-y * pieceHeight}px`;
piece.dataset.correctX = x;
piece.dataset.correctY = y;
makeDraggable(piece);
container.appendChild(piece);
pieces.push(piece);
}
}
}
function shufflePieces() {
pieces.forEach(piece => {
const randomX = Math.random() * (container.offsetWidth - pieceWidth);
const randomY = Math.random() * (container.offsetHeight - pieceHeight);
piece.style.left = randomX + 'px';
piece.style.top = randomY + 'px';
});
}
function makeDraggable(element) {
let posX = 0, posY = 0, startX = 0, startY = 0;
element.onmousedown = dragMouseDown;
element.ontouchstart = dragTouchStart;
function dragMouseDown(e) {
e.preventDefault();
startX = e.clientX;
startY = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function dragTouchStart(e) {
e.preventDefault();
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
document.ontouchend = closeDragElement;
document.ontouchmove = elementDragTouch;
}
function elementDrag(e) {
e.preventDefault();
posX = startX - e.clientX;
posY = startY - e.clientY;
startX = e.clientX;
startY = e.clientY;
moveElement();
}
function elementDragTouch(e) {
posX = startX - e.touches[0].clientX;
posY = startY - e.touches[0].clientY;
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
moveElement();
}
function moveElement() {
element.style.top = Math.max(0, Math.min(element.offsetTop - posY, container.offsetHeight - pieceHeight)) + 'px';
element.style.left = Math.max(0, Math.min(element.offsetLeft - posX, container.offsetWidth - pieceWidth)) + 'px';
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
document.ontouchend = null;
document.ontouchmove = null;
checkSnap(element);
checkWin();
}
}
function checkSnap(piece) {
const correctX = piece.dataset.correctX * pieceWidth;
const correctY = piece.dataset.correctY * pieceHeight;
const currentX = parseFloat(piece.style.left);
const currentY = parseFloat(piece.style.top);
if (Math.abs(currentX - correctX) < 20 && Math.abs(currentY - correctY) < 20) {
piece.style.left = correctX + 'px';
piece.style.top = correctY + 'px';
piece.style.cursor = 'default';
piece.onmousedown = null;
piece.ontouchstart = null;
piece.classList.remove('movable');
piece.classList.add('fixed');
}
}
function checkWin() {
const allPiecesCorrect = pieces.every(piece =>
Math.abs(parseFloat(piece.style.left) - (piece.dataset.correctX * pieceWidth)) < 1 &&
Math.abs(parseFloat(piece.style.top) - (piece.dataset.correctY * pieceHeight)) < 1
);
if (allPiecesCorrect) {
winMessage.style.display = 'block';
}
}
function resetGame() {
winMessage.style.display = 'none';
startGame();
}
window.onresize = () => {
if (pieces.length > 0) startGame();
};
</script>
</body>
</html>
6 комментариев