Генерация изображений
Привет, javascript-бродяги!))
Пожалуйста, подскажите, возможна ли в принципе генерация цельных изображений (jpg, gif, png) из нескольких изображений случайным образом средствами Java Script? Спасибо!) |
Да, на canvas. Анимированный гиф правда из коробки незя, но ставлю вчерашний йогурт, что есть нормальная библиотека под это дело.
|
Благодарю, Aetae!
Цитата:
Цитата:
|
Aetae, вот такое нашёл здесь:
Вывести две img в одну img через canvas Вот ещё бы изображения рандомно выстраивались каждый раз... |
Rise, например, изображения До:
<img src="http://placehold.it/150x150/ff0000/ff0000"> <img src="http://placehold.it/150x150/ffff00/ffff00"> <img src="http://placehold.it/150x150/0000ff/0000ff"> <img src="http://placehold.it/150x150/00ff00/00ff00"> Изображение После, как случайная комбинация из представленных выше изображений. |
Цитата:
Борис К, "случайных комбинаций" может быть бесконечное количество: и вдоль и поперёк, и по диагонали, и наложением и через фильтры всякие и т.д. и т.п. Конкретный пример нужен, да с описанием. |
Rise, сорри))
Нет, 2 на 2 (или 3 на 3 при большем количестве разных изображений и т.д.) Например, такой вид: <table> <tr> <td><img src="http://placehold.it/50x50/ff0000/ff0000"></td> <td><img src="http://placehold.it/50x50/ffff00/ffff00"></td> <td><img src="http://placehold.it/50x50/0000ff/0000ff"></td> </tr> <tr> <td><img src="http://placehold.it/50x50/00ff00/00ff00"></td> <td><img src="http://placehold.it/50x50/006600/006600"></td> <td><img src="http://placehold.it/50x50/ddff00/ddff00"></td> </tr> <tr> <td><img src="http://placehold.it/50x50/00ffdd/00ffdd"></td> <td><img src="http://placehold.it/50x50/800000/800000"></td> <td><img src="http://placehold.it/50x50/f09900/f09900"></td> </tr> </table> |
Aetae, каждый раз при загрузке странички должно быть сгенерировано изображение в jpg, gif или png, состоящее из других изображений, которые расположились абсолютно случайным образом, как я представил выше для Rise... извините, если сразу непонятно объясняю((
|
|
Aetae, отличная работа!))
Только сгенерированное изображение почему-то отображается аж три раза... как бы это поправить? |
Цитата:
|
Aetae,
:thanks: |
Цитата:
|
Борис К, поправил shuffle, там был баг - он не трогал последнюю картинку.)
|
Спасибо, Рони!
Цитата:
Цитата:
Цитата:
Цитата:
Видимо, у меня ещё старый браузер... такое может быть? |
Цитата:
Цитата:
Спасибо, Aetae! P.S. Но ещё вопрос родился: возможно ли сделать ещё кнопку перемешивания для генерации нового изображения, чтобы не перезагружать страницу, или это слишком трудоёмко? <button onclick="...">Shuffle</button> Самостоятельно разобраться пока не смог(( |
canvas create img
Борис К,
:-? <!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> </head> <body> <img id="pic"></img> <button id="btn">Shuffle</button> <script> // функция перемешивающая массив 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; } // функция добавляющая картинку на страницу function toImage(canvas, type) { pic.src = canvas.toDataURL(type) } const x = 150; // ширина одного const y = 150; // высота одного const w = 2; // сколько в ряду // картинки, должны быть на том же домене или иметь Access-Control-Allow-Origin const images = [ "https://picsum.photos/seed/aaa/150", "https://picsum.photos/seed/bbb/150", "https://picsum.photos/seed/ccc/150", "https://picsum.photos/seed/ddd/150" ]; const h = Math.ceil(images.length / w); // сколько в столбце const canvas = Object.assign(document.createElement('canvas'), { width: w * x, height: h * y }); const ctx = canvas.getContext('2d'); 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(() => { toImage(canvas, 'image/jpeg'); }); btn.addEventListener('click', createImg); createImg() </script> </body> </html> |
Рони... так ничесна!))
Я не поспеваю за Вами... учица новому! :write: Огромная благодарность Богам Java Script! :victory: |
Aetae, Рони, тока не кидайте в меня
Но возможно ли в принципе сделать так, чтобы в последнем коде на этой страничке 10-я строка (<img id="pic"></img>) была заменена следующей таблицей с отправкой к стилям? <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style type="text/css"> [data-id="1"] { background-image:url(...); width:150px; height:150px; background-position:0px 0px } [data-id="2"] { background-image:url(...); width:150px; height:150px; background-position:150px 300px } [data-id="3"] { background-image:url(...); width:150px; height:150px; background-position:0px 150px } [data-id="4"] { background-image:url(...); width:150px; height:150px; background-position:150px 150px } </style> </head> <body> <table align="center" cellspacing="0" cellpadding="0"> <tr> <td data-id="1"></td> <td data-id="2"></td> </tr> <tr> <td data-id="3"></td> <td data-id="4"></td> </tr> </table> </body> </html> :help: |
Борис К,
вопрос не понимаю, нафига тогда огород с канвас городили, если вернулись к тому что было? |
Рони, на первый взгляд, видимо, может показаться, что затея "огород с канвас" бессмысленна, но дело меняется, если посмотреть на таблицу, например, с большим количеством ячеек, которыми в дальнейшем можно интерактивно манипулировать.
Если это очень сложно реализовать, ну, тогда... В любом случае представленное решение на мой первый вопрос несомненно очень кстати, супер... Спасибо огромное! |
Цитата:
Цитата:
|
Рони, возможно, я слишком туманно изьясняюсь... уж извините!)
Смотрите, например, из 16-ти маленьких исходных изображений можно сгенерировать одно большое, которое отражается в <img id="pic"></img>, что и было уже Вами представлено в конечном результате - просто отлично получилось! Теперь это изображение нужно как-то представить, например, девятью ячейками таблицы, чтобы в дальнейшем можно было их перемещать кликами между собой после рандомной перетасовки до первоначально сгенерированного вида. Очень жаль, если такое невозможно реализовать((( Хотя мне казалось, что средствами Java Script невозможно и картинку сгенерировать из других... и, о, чудо чудесное! :dance: |
Цитата:
Переделал слегка пример Рони Вверху canvas. Внизу таблица с перенесенным в ячейки изображение из канвас <!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> td { width:100px; height:100px; } </style> </head> <body> <br> <br> <table> <tr> <td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td> </tr> <tr> <td></td><td></td><td></td> </tr> </table> <button id="btn">Shuffle</button> <script> // функция перемешивающая массив 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; } // функция добавляющая картинку на страницу function toImage(canvas, type) { pic.src = canvas.toDataURL(type) } const x = 150; // ширина одного const y = 150; // высота одного const w = 2; // сколько в ряду // картинки, должны быть на том же домене или иметь Access-Control-Allow-Origin const images = [ "https://picsum.photos/seed/aaa/150", "https://picsum.photos/seed/bbb/150", "https://picsum.photos/seed/ccc/150", "https://picsum.photos/seed/ddd/150" ]; 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'); 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(() => { // toImage(canvas, 'image/jpeg'); const url = canvas.toDataURL('image/jpeg') let x =0; const tb = document.querySelector ('table') for (let i = 0; i< tb.rows.length; i++) { for (let j = 0; j< tb.rows[i].cells.length; j++) { tb.rows[i].cells[j].style.backgroundImage = `url(${url})`; tb.rows[i].cells[j].style.backgroundPosition = `${-j*100}px ${-i*100}px`; } } }); btn.addEventListener('click', createImg); createImg() </script> </body> </html> |
Цитата:
Цитата:
|
Цитата:
Да нет, всё логично по задумке - выше Voraa вроде правильно понял... Поясню: 1. Из 16 маленьких изображений генерируется одно большое изображение цельным jpg (это уже реализовано - представлено Aetae и модифицировано Рони). 2. Одновременно большое изображение должно разделится, например, на 9 частей-квадратиков (Voraa разделил) и перемешатся . 3. Клики по соседним квадратикам должны их менять местами... и так до результата первоначально сгенерированного большого изображения. Цитата:
|
Voraa, Вы правильно поняли мой вопрос и отлично справились, но немного изменили код в моём примере на этой страничке, а это мне помешает самостоятельно реализовать то, что уже имелось для полного замысла... но тем не менее моя Вам искренняя благодарность!))
Поясню своё полное видение: 1. Из 16 маленьких изображений генерируется одно большое изображение цельным jpg (это уже реализовано - представлено Aetae и модифицировано Рони). 2. Одновременно большое изображение должно разделится, например, на 9 частей-квадратиков (реализовано Вами) и перемешатся (имеется уже готовое решение). 3. Клики по соседним квадратикам должны их менять местами... и так до результата первоначально сгенерированного большого изображения. |
Цитата:
Как из нескольких изображений сделать одно. Как снова разделить это изображение на другое количество частей и вставить их как фон на элементы. Ваше видение вы должны сами реализовывать. |
Цитата:
Цитата:
Цитата:
Цитата:
Voraa, спасибо Вам! |
Rise, это пока не игра... ведь решение мной так и не найдено(((
А так, то был замысел сделать что-нибудь среднее по трудности для умственно отсталого ребенка на компьютере... P.S. Я совсем не программист, просто когда-то немного знакомился с веб-технологиями в качестве хобби, но теперь вижу, что язык JS в составе HTML5 ушёл далеко вперёд... и я глубоко восхищён высокопрофессионализмом людей на этом ресурсе, владеющим современным JS! |
А почему обязательно на компьютере?
Разве "материальные" игры, игрушки, головоломки хуже? Я немного знаю о чем говорю, т.к. моя жена всю жизнь проработала психологом в психиатрической больнице (правда не с детьми). Им необходим не столько компьютер, сколько доступная активность для мозга, моторика для рук, общение... |
Voraa, Вы абсолютно без сомнений правы во всём!
Но просто, как дополнение к основному, на компьютере можно создавать бесконечное количество наглядного материала... да и по правде, мне самому интересно повозиться с кодом, но у меня, к сожалению, очень ограниченный объем знаний((( Порой радуюсь, как дитя малое, что удалось что-нибудь "модифицировать" самостоятельно из чужого... повторюсь, я глубоко восхищён возможностями JS! Но я далеко немолод и нездоров, чтобы достаточно хорошо освоить этот замечательный стремительно развивающийся язык((( Хотя всё же жизнь продолжается и я не теряю надежд на лучшее - вот на неделе скачал современные книги по JS))) Voraa, спасибо Вам за добрые слова! |
Цитата:
только надо добавить это https://javascript.ru/forum/css-html...tml#post543513 |
рони,
Судя по той и этой теме, автор так и не определился окончательно что ему нужно. |
Цитата:
Изображение, которое сначала генерируется, например, из 16 маленьких изображений, автоматически делится на 9 сегментов, которые рандомно перемешиваются, и их необходимо кликами по соседним привести в исходное положение, как на первоначально сгенерированной картинке: ![]() Извините, если невразумительно объясняю(( |
Рони, сначала генерация изображения, как было продемонстрировано Вами в этой теме:
https://javascript.ru/forum/css-html...tml#post543474 Потом раздел на сегменты, как на изображении для Rise выше, затем ваша же реализация перемещения разделённых сегментов в другой моей теме: https://javascript.ru/forum/css-html...tml#post542829 P.S. Предупреждал не кидать в меня тапками!)) |
типа пятнашек
<iframe height="550" style="width: 100%;" scrolling="no" title="Fifteen game" src="https://codepen.io/mohnatus-the-lessful/embed/YzXNYQQ?default-tab=js%2Cresult&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mohnatus-the-lessful/pen/YzXNYQQ"> Fifteen game</a> by FurryCat (<a href="https://codepen.io/mohnatus-the-lessful">@mohnatus-the-lessful</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> |
Rise, все 9 сегментов (разделенные красным на изображении выше) должны быть активны - меняться соседние сегменты между собой при кликах на них.
|
MallSerg, спасибо!))
Только все изображения-элементы должны быть видны (не как в "пятнашках"). |
Rise, вот так оно всё должно выглядеть в конечном результате, но только в этом варианте всё время будет одно и то же изображение собираться, поэтому я изначально в этой теме хотел каждый раз новое изображение генерировать для сборки:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style type="text/css"> [data-id="1"] { background-image:url(https://i.ibb.co/cb6tXTH/canvas-01.jpg); width: 200px; height: 200px; } [data-id="2"] { background-image:url(https://i.ibb.co/r3nXCKj/canvas-02.jpg); width: 200px; height: 200px; } [data-id="3"] { background-image:url(https://i.ibb.co/PFc43HB/canvas-03.jpg); width: 200px; height: 200px; } [data-id="4"] { background-image:url(https://i.ibb.co/r5dVWj7/canvas-04.jpg); width: 200px; height: 200px; } [data-id="5"] { background-image:url(https://i.ibb.co/jGp056d/canvas-05.jpg); width: 200px; height: 200px; } [data-id="6"] { background-image:url(https://i.ibb.co/GRVYX8H/canvas-06.jpg); width: 200px; height: 200px; } [data-id="7"] { background-image:url(https://i.ibb.co/QbR97Fr/canvas-07.jpg); width: 200px; height: 200px; } [data-id="8"] { background-image:url(https://i.ibb.co/StcY4gm/canvas-08.jpg); width: 200px; height: 200px; } [data-id="9"] { background-image:url(https://i.ibb.co/bB70pMR/canvas-09.jpg); width: 200px; height: 200px; } </style> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", function() { let temp = []; let form = document.querySelector(".game"); let tds = Array.from(form.querySelectorAll("[data-id]")); let idEnd = tds.map(({ dataset: { id } }) => id); let win; function exch(event) { if (win) return; let td = event.target.closest("[data-id]"); 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]) { [td.dataset.id, temp[0].dataset.id] = [temp[0].dataset.id, td.dataset.id] temp = []; } } else { temp = [td, cellIndex, rowIndex]; } win = tds.every(({ dataset: { id } }, i) => id === idEnd[i]); if (win) alert("Hello world!"); } } form.addEventListener("click", exch); let color = idEnd.slice(0), len = color.length; color.forEach((_, i) => { let a = Math.trunc(Math.random() * len); [color[i], color[a]] = [color[a], color[i]]; }); tds.forEach(({dataset}, i) => dataset.id = color[i]); }); </script> </head> <body> <form class="game"> <table align="center" cellspacing="0" cellpadding="0"> <tr> <td data-id="1"></td> <td data-id="2"></td> <td data-id="3"></td> </tr> <tr> <td data-id="4"></td> <td data-id="5"></td> <td data-id="6"></td> </tr> <tr> <td data-id="7"></td> <td data-id="8"></td> <td data-id="9"></td> </tr> </table> </form> </body> </html> |
Часовой пояс GMT +3, время: 07:58. |