Rise, да, Вы правы - с непривычки может казаться трудновыполнимым, но при объяснении со временем всё становится понятно и исполнимо... во всяком случае в материальной версии, но она фактически только на один раз, потому что легко запоминается первоначальное расположение. Ну, я так увидел, если что))
|
Борис К,
В вашем примере надо делать два клика за один ход: 1-ый клик - выбрать активный сегмент, 2-ой клик - выбрать соседний сегмент. А вы описывали это как просто делать клик на соседний. Если вы не можете даже сами правильно объяснить эту игру, то вряд ли сам играющий в этом быстро разберется. Приходится постоянно перекликивать активный сегмент даже если он был тем же самым на прошлом ходе. Это не совсем очевидное поведение было для меня. |
Rise, да, видимо, всё как Вы и описали... виноват!((
Цитата:
Цитата:
|
Rise, Оплошность в смысле, что изначально неправильно на словах объяснил "поведение" кликов для обмена сегментами... должно быть, как я представил в последнем коде на этой страничке (нахожу это решение просто идеальным), но только у меня трудности его объединения с кодом генерации изображения, которое было представлено Aetae и Рони выше:
https://javascript.ru/forum/css-html...tml#post543474 |
Цитата:
Соединить эти две части можно, но это будет кривовато смотреться, и на будущее не очень, если захотите что-то поменять. |
Цитата:
Цитата:
Rise, спасибо Вам!!! |
игра пазлы собрать картинку
Борис К,
:-? <!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> td { width: 56px; height: 56px; background-size: cover; background-image: var(--url); } .game.end{ border-collapse: collapse; border-spacing: 0px; } </style> </head> <body> <br> <br> <table class="game"> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </table> <button id="btn">Shuffle</button> <script> function imagedata_to_image(imagedata) { let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); canvas.width = imagedata.width; canvas.height = imagedata.height; ctx.putImageData(imagedata, 0, 0); return canvas.toDataURL(); } // функция перемешивающая массив function shuffle(array) { let i = array.length; while (i--) { let j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } const x = 150; // ширина одного const y = 150; // высота одного const w = 2; // сколько в ряду // картинки, должны быть на том же домене или иметь Access-Control-Allow-Origin const images = [ "https://loremflickr.com/150/150/girl?random=1", "https://loremflickr.com/150/150/dog?random=2", "https://loremflickr.com/150/150/red?random=3", "https://loremflickr.com/150/150/kitten?random=4" ]; const h = Math.ceil(images.length / w); // сколько в столбце const canvas = Object.assign(document.createElement('canvas'), { width: w * x, height: h * y }); document.body.prepend(canvas); const ctx = canvas.getContext('2d'), arrSrc = [], tb = document.querySelector('.game'), cells = Array.from(tb.querySelectorAll('td')); let win, temp = []; function endGame() { tb.classList.add('end'); } function exch(event) { if (win) return; let td = event.target.closest('.game td'); if (td) { let cellIndex = td.cellIndex; let rowIndex = td.closest("tr").rowIndex; if (temp.length) { let x = Math.abs(cellIndex - temp[1]); let y = Math.abs(rowIndex - temp[2]); if ((x == 0 && y == 1) || (x == 1 && y == 0) || td === temp[0]) { let url = td.style.getPropertyValue('--url'); td.style.setProperty('--url', temp[0].style.getPropertyValue('--url')); temp[0].style.setProperty('--url', url); temp = []; } } else { temp = [td, cellIndex, rowIndex]; } win = cells.every(({ style }, i) => { let url = style.getPropertyValue('--url'); style.setProperty('--url', arrSrc[i]); let patern = style.getPropertyValue('--url'); style.setProperty('--url', url); return url === patern }); if (win) endGame(); } } tb.addEventListener("click", exch); const createImg = () => Promise.all( shuffle(images).map((src, i) => new Promise( (onload, onerror) => Object.assign(new Image(), { crossOrigin: 'anonymous', src, onerror, onload }) ).then(({ target }) => { const hPos = Math.floor(i / w); const wPos = i - (hPos * w); ctx.drawImage( target, wPos * x, hPos * y, x, y ) })) ).then(() => { const wh = w * x / tb.rows.length; arrSrc.length = 0; win = false; temp = []; tb.classList.remove('end'); for (let i = 0; i < tb.rows.length; i++) { for (let j = 0; j < tb.rows[i].cells.length; j++) { let imagedata = ctx.getImageData(wh * j, wh * i, wh, wh); let url = imagedata_to_image(imagedata); arrSrc.push(`url(${url})`); } } shuffle(arrSrc.slice(0)).forEach((url, i) => cells[i].style.setProperty('--url', url)) }); btn.addEventListener('click', createImg); createImg() </script> </body> </html> |
Рони - javascript-атлант,
Сразу видно, что талант, Гений мысли и труда, Кладезь знаний и ума! © |
Борис К,
строки 24 - 58 можно менять, 2 х 2, 3 х 3, 4 х 4, и т.д., да и код, с миру по нитке, больше сборная солянка, чем деликатес. :) :thanks: |
Цитата:
Цитата:
Цитата:
Рони, огромная благодарность Вам!!! :thanks: |
Рони, изучая код длинными зимними ночами, заметил в нём ваши последние "модификации"... Спасибо! :thanks:
Но вот ещё мучает вопрос по познавательным мотивам: как сделать, чтобы в коде присутствовал вне самого скрипта элемент <canvas id="canvas"></canvas> (в руководствах он присутствует)? Видимо, дополнительно к <canvas id="canvas"></canvas> ещё какие-то строки необходимо изменить в самом скрипте, но я самостоятельно в таком вопросе опять не справляюсь... |
Цитата:
const canvas = Object.assign(document.createElement('canvas'), { width: w * x, height: h * y }); document.body.prepend(canvas); будет const canvas = Object.assign(document.getElementById('canvas'), { width: w * x, height: h * y }); |
Рони, я был близок к решению... просто не догадался одновременно изменить две основные строки!((
Большое спасибо, профессор Рони! :thanks: |
Рони, здравствуйте!)))
Назрел вопрос по следующему фрагменту (строки 84-87): Цитата:
|
Если клиент не знает адреса изображения он не сможет его запросить.
Так что либо предзаполненный список, либо сервер который пройдётся по папке и отдаст клиенту составленный список. |
Aetae, только не кидайте в меня тапками!)
Требуется, чтобы изображения рандомно загружались из папки "images", как в примере ниже: const images = [ "https://xyz.ru/images/", "https://xyz.ru/images/", "https://xyz.ru/images/", "https://xyz.ru/images/" ]; |
Борис К,
имена сделайте по порядку, и число укажите. |
Цитата:
Цитата:
|
Борис К,
максимум сколько? |
предположим всего картинок 44.)))
<!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> td { width: 56px; height: 56px; background-size: cover; background-image: var(--url); } .game.end { border-collapse: collapse; border-spacing: 0px; } </style> </head> <body> <br> <br> <table class="game"> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </table> <button id="btn">Shuffle</button> <script> function imagedata_to_image(imagedata) { let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); canvas.width = imagedata.width; canvas.height = imagedata.height; ctx.putImageData(imagedata, 0, 0); return canvas.toDataURL(); } const x = 150; // ширина одного const y = 150; // высота одного const w = 2; // сколько в ряду // картинки, должны быть на том же домене или иметь Access-Control-Allow-Origin function makeRand(num) { let usedNumbers = []; function f() { if (usedNumbers.length == num) usedNumbers = []; let i = Math.floor(Math.random() * num) + 1; return usedNumbers.includes(i) ? f() : (usedNumbers.push(i), i) } return f; } let totalImg = 44; let key = makeRand(totalImg); let length = 4; let images = length => Array.from({ length }, _ => `https://loremflickr.com/150/150/girl?random=${key()}`); /*let images = length => Array.from({ length }, _ => `https://xyz.ru/images/${('' + key()).padStart(2, "0")}.jpg`);*/ const h = Math.ceil(length / w); // сколько в столбце const canvas = Object.assign(document.createElement('canvas'), { width: w * x, height: h * y }); document.body.prepend(canvas); const ctx = canvas.getContext('2d'), arrSrc = [], tb = document.querySelector('.game'), cells = Array.from(tb.querySelectorAll('td')); let win, temp = []; function endGame() { tb.classList.add('end'); } function exch(event) { if (win) return; let td = event.target.closest('.game td'); if (td) { let cellIndex = td.cellIndex; let rowIndex = td.closest("tr").rowIndex; if (temp.length) { let x = Math.abs(cellIndex - temp[1]); let y = Math.abs(rowIndex - temp[2]); if ((x == 0 && y == 1) || (x == 1 && y == 0) || td === temp[0]) { let url = td.style.getPropertyValue('--url'); td.style.setProperty('--url', temp[0].style.getPropertyValue('--url')); temp[0].style.setProperty('--url', url); temp = []; } } else { temp = [td, cellIndex, rowIndex]; } win = cells.every(({ style }, i) => { let url = style.getPropertyValue('--url'); style.setProperty('--url', arrSrc[i]); let patern = style.getPropertyValue('--url'); style.setProperty('--url', url); return url === patern }); if (win) endGame(); } } tb.addEventListener("click", exch); const createImg = () => Promise.all( images(length).map((src, i) => new Promise( (onload, onerror) => Object.assign(new Image(), { crossOrigin: 'anonymous', src, onerror, onload }) ).then(({ target }) => { const hPos = Math.floor(i / w); const wPos = i - (hPos * w); ctx.drawImage( target, wPos * x, hPos * y, x, y ) })) ).then(() => { const wh = w * x / tb.rows.length; arrSrc.length = 0; win = false; temp = []; tb.classList.remove('end'); for (let i = 0; i < tb.rows.length; i++) { for (let j = 0; j < tb.rows[i].cells.length; j++) { let imagedata = ctx.getImageData(wh * j, wh * i, wh, wh); let url = imagedata_to_image(imagedata); arrSrc.push(`url(${url})`); } } arrSrc.slice(0).sort(_ => Math.random() - .5).forEach((url, i) => cells[i].style.setProperty('--url', url)) }); btn.addEventListener('click', createImg); createImg() </script> </body> </html> |
Борис К,
убрать строки 91 - 93, раскомментировать 95 - 97. |
Рони, круто... очень круто!!!
:thanks: :thanks: :thanks: |
Рони, чисто теоретический вопрос по познавательным мотивам: например, генерировать новое динамическое изображение на основе gif'ок пока недоступно средствами JS?)
|
Борис К,
не могу подсказать. |
Видимо, дело за будущим JS!)
Рони, ещё раз великодушно благодарю за оказанную помощь! :thanks: |
Рони, здравствуйте! :))
Не могу самостоятельно справится со следующим вопросом с использованием стилей: как в последнем варианте кода сделать так, чтобы элемент, на который кликнуто, оставался выделенным с помощью стиля: <style type="text/css"> .active { opacity: .4; } </style> :help: |
игра собери картинку
Борис К,
<!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> td { width: 56px; height: 56px; background-size: cover; background-image: var(--url); } .game.end { border-collapse: collapse; border-spacing: 0px; } .active { opacity: .4; } </style> </head> <body> <br> <br> <table class="game"> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </table> <button id="btn">Shuffle</button> <script> function imagedata_to_image(imagedata) { let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); canvas.width = imagedata.width; canvas.height = imagedata.height; ctx.putImageData(imagedata, 0, 0); return canvas.toDataURL(); } const x = 150; // ширина одного const y = 150; // высота одного const w = 2; // сколько в ряду // картинки, должны быть на том же домене или иметь Access-Control-Allow-Origin function makeRand(num) { let usedNumbers = []; function f() { if (usedNumbers.length == num) usedNumbers = []; let i = Math.floor(Math.random() * num) + 1; return usedNumbers.includes(i) ? f() : (usedNumbers.push(i), i) } return f; } let totalImg = 44; let key = makeRand(totalImg); let length = 4; let images = length => Array.from({ length }, _ => `https://loremflickr.com/150/150/girl?random=${key()}`); /*let images = length => Array.from({ length }, _ => `https://xyz.ru/images/${('' + key()).padStart(2, "0")}.jpg`);*/ const h = Math.ceil(length / w); // сколько в столбце const canvas = Object.assign(document.createElement('canvas'), { width: w * x, height: h * y }); document.body.prepend(canvas); const ctx = canvas.getContext('2d'), arrSrc = [], tb = document.querySelector('.game'), cells = Array.from(tb.querySelectorAll('td')); let win, temp = []; function endGame() { tb.classList.add('end'); } function exch(event) { if (win) return; let td = event.target.closest('.game td'); if (td) { let cellIndex = td.cellIndex; let rowIndex = td.closest("tr").rowIndex; if (temp.length) { let x = Math.abs(cellIndex - temp[1]); let y = Math.abs(rowIndex - temp[2]); if ((x == 0 && y == 1) || (x == 1 && y == 0) || td === temp[0]) { let url = td.style.getPropertyValue('--url'); td.style.setProperty('--url', temp[0].style.getPropertyValue('--url')); temp[0].style.setProperty('--url', url); temp[0].classList.remove('active'); temp = []; } } else { temp = [td, cellIndex, rowIndex]; td.classList.add('active'); } win = cells.every(({ style }, i) => { let url = style.getPropertyValue('--url'); style.setProperty('--url', arrSrc[i]); let patern = style.getPropertyValue('--url'); style.setProperty('--url', url); return url === patern }); if (win) endGame(); } } tb.addEventListener("click", exch); const createImg = () => Promise.all( images(length).map((src, i) => new Promise( (onload, onerror) => Object.assign(new Image(), { crossOrigin: 'anonymous', src, onerror, onload }) ).then(({ target }) => { const hPos = Math.floor(i / w); const wPos = i - (hPos * w); ctx.drawImage( target, wPos * x, hPos * y, x, y ) })) ).then(() => { const wh = w * x / tb.rows.length; arrSrc.length = 0; win = false; temp = []; tb.classList.remove('end'); for (let i = 0; i < tb.rows.length; i++) { for (let j = 0; j < tb.rows[i].cells.length; j++) { let imagedata = ctx.getImageData(wh * j, wh * i, wh, wh); let url = imagedata_to_image(imagedata); arrSrc.push(`url(${url})`); } } arrSrc.slice(0).sort(_ => Math.random() - .5).forEach((url, i) => cells[i].style.setProperty('--url', url)) }); btn.addEventListener('click', createImg); createImg() </script> </body> </html> |
Точно так сделал, но только в 138 строке вместо td.classList.add('active'); у меня было img.classList.add('active'); ... вот неудача!(((
Рони, моя безграничная благодарность! :thanks: :thanks: :thanks: |
Добрый день, Рони! :)
К сожалению, сам не осилил следующий познавательный вопрос: например, как сделать так, чтобы после завершения всех переходов, изображения вновь перемешались, но без использования кнопки "Shuffle"? Понимаю, что в 149 строку - if (win) endGame(); следует вписать что-то из 189 (btn.addEventListener('click', createImg); - вроде задача не из сложных, но |
Борис К,
if (win) createImg() |
Цитата:
СПАСИБО, Рони! :thanks: P.S. Возможно, Вам пригодится следующий "интересный" факт: экспериментируя с количеством и размерами исходных изображений для canvas, я обнаружил, что размеры таблицы с сегментами заметно уменьшены и сами сегменты неравномерно размещаются в таблице... вот такие дела) |
Здравствуйте, Рони! :)
Экспериментируя с некоторыми вариантами вашего кода, перенёс пути к изображениям из скрипта в стили: <style type="text/css"> [data-id="girl"] { background-image:url(https://loremflickr.com/150/150/girl?random=1); width: 150px; height: 150px; } [data-id="dog"] { background-image:url(https://loremflickr.com/150/150/dog?random=2); width: 150px; height: 150px; } [data-id="boy"] { background-image:url(https://loremflickr.com/150/150/boy?random=3); width: 150px; height: 150px; } [data-id="kitten"] { background-image:url(https://loremflickr.com/150/150/kitten?random=4); width: 150px; height: 150px; } </style> Но не могу понять, как изменить следующие строки скрипта, чтобы в нём указать отсылку к изображениям в стилях: const images = [ "https://loremflickr.com/150/150/girl?random=1", "https://loremflickr.com/150/150/dog?random=2", "https://loremflickr.com/150/150/boy?random=3", "https://loremflickr.com/150/150/kitten?random=4" ]; :help: |
Борис К,
пас, умных мыслей, как это сделать, нет. |
Борис К,
тебе понадобится вытащить ссылки из таблицы стилей кури начиная отсюда: https://developer.mozilla.org/en-US/...nt/styleSheets |
Alexandroppolus, благодарю за подсказку!)
P.S. Пока такое высшая математика(( |
Борис К,
это весьма и весьма далеко от высшей математики. 0) открой консоль разработчика на странице своего приложения, лучше в Хроме 1) введи строку document.styleSheets , нажми энтер. 2) тебе вывалится здоровенный объект, и раскрывая ветви дерева, ты увидишь всю правду о таблицах стилей в твоем документе. Остается только с помощью js забрать из этого объекта всё нужное. |
Цитата:
Цитата:
|
Цитата:
https://developer.mozilla.org/en-US/...nt/styleSheets https://developer.mozilla.org/en-US/.../CSSStyleSheet https://developer.mozilla.org/en-US/...eb/API/CSSRule https://developer.mozilla.org/en-US/...I/CSSStyleRule и связанными темами. CSSom немного посложнеее, чем Dom на мой взгляд. + некоторые неточности по сравнению с тем, что реально есть в браузере. |
Voraa, спасибо за ссылки!))
/Но только не ругайтесь за следующий вопрос)/ Вообще возможно ли сделать так, чтобы в массиве обсуждаемого кода, например, вместо одного из изображений ("https://loremflickr.com/150/150/girl?random=1") был красный квадрат, созданный из следующего стиля: background-color: #ff0000; width: 150px; height: 150px;? P.S. У меня есть опасения, что я мог быть ранее неправильно понят.(( |
Многое чего можно сделать. Весь вопрос в сложности.
Зачем для каждого квадрата в css указывать width и height? Разве они могут отличаться? Достаточно создать одно правило для всех квадратов (через класс и атрибут) и там указать ширину и высоту [data-id] { width: 150px; height: 150px; } [data-id="girl"] { background-image:url(https://loremflickr.com/150/150/girl?random=1); } [data-id="dog"] { background-image:url(https://loremflickr.com/150/150/dog?random=2); } [data-id="boy"] { background-image:url(https://loremflickr.com/150/150/boy?random=3); } [data-id="kitten"] { background-image:url(https://loremflickr.com/150/150/kitten?random=4); } |
Часовой пояс GMT +3, время: 23:11. |