Добавление background-X
Всем привет.
Ребята, помогите составить скрипт. Нужно при помощи инпутов задать блоку background-image и другие свойства. Т.е., при вводе ссылки в 1 поле, в блоке #back появляется картинка, которая корректируется при помощи полей, расположенных ниже. Как правильно составить скрипт? Думал сделать выведение через value, но не уверен, что получится. Знаний js пока не хватает. Набросал разметку в песочнице https://jsfiddle.net/Lbqfp9g7/ |
Для начала - только url.
Можно попробовать этот: "https://javascript.ru/cat/list/donkey.gif" <style> * { box-sizing: border-box; padding: 0; margin: 0; } label, ul, p { margin-bottom: 0; } .back_flex ul li { list-style: none; display: inline-block; } .back_flex { display: flex; align-items: center; margin: 15px 0; } .back_flex p { margin-right: 15px; } #backpx { width: 50px; } #back { width: 267px; height: 267px; background-color: rgb(0, 0, 0); display: flex; position: relative; } </style> <div class='container p-3'> <div class='row align-items-center'> <div class='col-lg-6'> <div class='back_flex'> <p>background-image:</p> <ul> <li>url(<input type='text' id=''>);</li> </ul> </div> <div class='back_flex'> <p>background-repeat:</p> <ul> <li><label><input type='radio' name='repeat' id='' checked>no-repeat;</label></li> <li><label><input type='radio' name='repeat' id=''>repeat;</label></li> <li><label><input type='radio' name='repeat' id=''>repeat-x;</label></li> <li><label><input type='radio' name='repeat' id=''>repeat-y;</label></li> </ul> </div> <div class='back_flex'> <p>background-position: </p> <ul> <li>Left <label><input id='backpx' type='number' min='0' max='100' id=''>%</label></li> <li>Top <label><input id='backpx' type='number' min='0' max='100' id=''>%</label></li> </ul> </div> <div class='back_flex'> <p>background-size: </p> <ul> <li><label><input id='backpx' type='number' id=''>px</label></li> <li><label><input type='radio' id='' name='size'>cover</label></li> <li><label><input type='radio' id='' name='size'>repeat</label></li> <li><label><input type='radio' id='' name='size'>no-repeat</label></li> </ul> </div> </div> <div class='col-lg-6'> <div id='back'></div> </div> </div> </div> <script> document.querySelector('input[type=text]').onchange = function() { document.querySelector('#back').style.backgroundImage = 'url(' + this.value + ')'; } </script> |
<div class='container p-3'> <style>* { box-sizing: border-box; padding: 0; margin: 0; } label, ul, p { margin-bottom: 0; } .back_flex ul li { list-style: none; display: inline-block; } .back_flex { display: flex; align-items: center; margin: 15px 0; } .back_flex p { margin-right: 15px; } #backpx { width: 50px; } #back { width: 267px; height: 267px; background-color: rgb(0, 0, 0); display: flex; position: relative; } </style> <div class='row align-items-center'> <div class='col-lg-6'> <div class='back_flex'> <p>background-image:</p> <ul> <li>url(<input type='text' name="backgroundImage">);</li> </ul> </div> <div class='back_flex'> <p>background-repeat:</p> <ul> <li><label><input type='radio' name='backgroundRepeat' value="no-repeat" checked>no-repeat;</label></li> <li><label><input type='radio' name='backgroundRepeat' value="repeat">repeat;</label></li> <li><label><input type='radio' name='backgroundRepeat' value="repeat-x">repeat-x;</label></li> <li><label><input type='radio' name='backgroundRepeat' value="repeat-y">repeat-y;</label></li> </ul> </div> <div class='back_flex'> <p>background-position: </p> <ul> <li><label>Left <input type='text' name="backgroundPositionLeft"></label></li> <li><label>Top <input type='text' name="backgroundPositionTop"></label></li> </ul> </div> <div class='back_flex'> <p>background-size: </p> <ul> <li><label><input type='text' name="backgroundSize"></label></li> <li><label><input type='radio' name="backgroundSize" value='cover'>cover</label></li> <li><label><input type='radio' name="backgroundSize" value='repeat'>repeat</label></li> <li><label><input type='radio' name="backgroundSize" value='no-repeat'>no-repeat</label></li> </ul> </div> </div> <div class='col-lg-6'> <div id='back'></div> </div> </div> </div> <script> (function() { const container = document.getElementById('back'); const inputList = [].slice.call(document.querySelectorAll('input')); const index = inputList.reduce(function(res, item) { if (item.name in res) { if (res[item.name] instanceof Array) res[item.name].push(item); else (res[item.name] = [res[item.name]]).push(item); } else res[item.name] = item; return res; }, {}); inputList.forEach(function(node) { const IS_RADIO = node.type === 'radio'; node.addEventListener(IS_RADIO ? 'change' : 'input', function() { let value; if (this.name.indexOf('backgroundPosition') === 0) { return container.style.backgroundPosition = index.backgroundPositionLeft.value + index.backgroundPositionTop.value; } else if (this.name === 'backgroundSize') { value = index[this.name].filter(function(node) { return node.type === 'text'; }).shift().getAttribute('value'); if (!value || value.trim().length) { value = index[this.name].filter(function(node) { return node.type !== 'text' && node.checked; }); if (!value.length) return; value = value.shift().getAttribute('value'); }; } else if (this.name === 'backgroundImage') value = 'url(' + this.value + ')'; else value = this.value; container.style[this.name] = value; }); }); })() </script> |
Nexus,
Спасибо. Вообще я предполагал сделать так же, как предложил Dilettante_Pro, но мне кажется, так получилось бы более громоздко. Dilettante_Pro, спасибо. Я был на верном пути) |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> * { box-sizing: border-box; padding: 0; margin: 0; } label, ul, p { margin-bottom: 0; } .back_flex ul li { list-style: none; display: inline-block; } .back_flex { display: flex; align-items: center; margin: 15px 0; } .back_flex p { margin-right: 15px; } #backpx { width: 50px; } #back { width: 267px; height: 267px; background-color: rgb(0, 0, 0); display: flex; position: relative; } </style> </head> <body> <div class='container p-3'> <div class='row align-items-center'> <div class='col-lg-6'> <div class='back_flex'> <p>background-image:</p> <ul> <li>url(<input type='text' id='url' value="https://javascript.ru/cat/list/donkey.gif">);</li> </ul> </div> <div class='back_flex'> <p>background-repeat:</p> <ul> <li><label><input type='radio' name='repeat' id='' checked>no-repeat</label></li> <li><label><input type='radio' name='repeat' id=''>repeat</label></li> <li><label><input type='radio' name='repeat' id=''>repeat-x</label></li> <li><label><input type='radio' name='repeat' id=''>repeat-y</label></li> </ul> </div> <div class='back_flex'> <p>background-position: </p> <ul> <li>Left <label><input id='posX' type='number' min='0' max='100' value="0">%</label></li> <li>Top <label><input id='posY' type='number' min='0' max='100' value="0">%</label></li> </ul> </div> <div class='back_flex'> <p>background-size: </p> <ul> <li><label><input type='number' id='size' value="30">px</label></li> <li><label><input type='checkbox' id='size2' name='size'>cover</label></li> </ul> </div> </div> <div class='col-lg-6'> <div id='back'></div> </div> </div> </div> <script> var back = document.querySelector("#back"), x = document.querySelector("#posX"), y = document.querySelector('#posY'), size = document.querySelector('#size'), size2 = document.querySelector('#size2'); (style=()=>{ back.style.background = `url(${document.querySelector("#url").value}) black ${document.querySelector('[name="repeat"]:checked').parentNode.textContent} ${x.value}% ${y.value}%`; back.style.backgroundSize = size2.checked?'cover':size.value+'px'; })(); document.querySelectorAll('input').forEach(el=>el.oninput=style); </script> </body> </html> |
j0hnik,
а можно сделать поля независимыми? Сейчас, когда выбираешь пункты, они не активируются до нажатия на background-size. Т.е. чтобы другие изменения заработали, придется стирать size и писать еще раз. |
madeas,
У меня пример j0hnik прекрасно работает в Chrome - изменения срабатывают сразу по любому параметру - и совсем не работает в IE. Стрелочные функции поддерживают не все браузеры |
Dilettante_Pro,
тогда хз, в хромиуме приходится обновлять значение других полей, чтобы сработали repeat'ы. Сами по себе они не меняются почему-то. |
Dilettante_Pro,
похоже это особенность браузера, эх... в фоксе и правда норм работает. |
Цитата:
Вообще Chrome поддерживает стрелочные функции с версии 45.0 У меня 67.0.3396.99 |
Dilettante_Pro,
в его примере, через "Посмотреть", так же. Не работают репиты и переключение px/cover. Изменения вступают в силу только после изменений позиции (лефт/топ). Cover работает, но тоже барахлит) |
А как такой вариант?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> * { box-sizing: border-box; padding: 0; margin: 0; } label, ul, p { margin-bottom: 0; } .back_flex ul li { list-style: none; display: inline-block; } .back_flex { display: flex; align-items: center; margin: 15px 0; } .back_flex p { margin-right: 15px; } #backpx { width: 50px; } #back { width: 267px; height: 267px; background-color: rgb(0, 0, 0); display: flex; position: relative; } </style> </head> <body> <div class='container p-3'> <div class='row align-items-center'> <div class='col-lg-6'> <div class='back_flex'> <p>background-image:</p> <ul> <li>url(<input type='text' id='url' value="https://javascript.ru/cat/list/donkey.gif">);</li> </ul> </div> <div class='back_flex'> <p>background-repeat:</p> <ul> <li><label><input type='radio' name='repeat' id='' checked>no-repeat</label></li> <li><label><input type='radio' name='repeat' id=''>repeat</label></li> <li><label><input type='radio' name='repeat' id=''>repeat-x</label></li> <li><label><input type='radio' name='repeat' id=''>repeat-y</label></li> </ul> </div> <div class='back_flex'> <p>background-position: </p> <ul> <li>Left <label><input id='posX' type='number' min='0' max='100' value="0">%</label></li> <li>Top <label><input id='posY' type='number' min='0' max='100' value="0">%</label></li> </ul> </div> <div class='back_flex'> <p>background-size: </p> <ul> <li><label><input type='number' id='size' value="30">px</label></li> <li><label><input type='checkbox' id='size2' name='size'>cover</label></li> </ul> </div> </div> <div class='col-lg-6'> <div id='back'></div> </div> </div> </div> <script> var back = document.querySelector("#back"), x = document.querySelector("#posX"), y = document.querySelector('#posY'), size = document.querySelector('#size'), size2 = document.querySelector('#size2'); function style() { back.style.background = `url(${document.querySelector("#url").value}) black ${document.querySelector('[name="repeat"]:checked').parentNode.textContent} ${x.value}% ${y.value}%`; back.style.backgroundSize = size2.checked?'cover':size.value+'px'; }; style(); [].forEach.call(document.querySelectorAll('input'), function(el) { el.onchange=style}); [].forEach.call(document.querySelectorAll('input'), function(el) { el.oninput=style}); </script> </body> </html> |
Dilettante_Pro,
https://my-files.ru/dko70m пришлось на телефон снимать)) |
madeas,
Посмотрел. Очень странно. У меня нормально работает - на все параметры сразу реагирует. Значит, дело не в стрелочных функциях... |
madeas,
Изменил назначение обработчика в пост 12. Посмотрите. |
Dilettante_Pro,
не, ничего не поменялось. Это видимо браузер. Нормально работает лефт/топ и позиция через поле. Радио и чеки нет. Кстати, а как сделать чтобы появилась кнопка "просмотреть" ?) |
madeas, скорее всего событие "input" не срабатывает на радио-баттонах.
Про форматирование на форуме: http://javascript.ru/formatting |
Цитата:
Если только change - не очень динамично работает |
Dilettante_Pro, а почему не так?
[].forEach.call(document.querySelectorAll('input'), function(el) { el.addEventListener(el.type === 'text' ? 'input' : 'change', style); }); |
Nexus,
Методом копипасте, по-быстрому:) - для посмотреть Сначала input поменял на change - не очень понравилось, добавил второй:write: |
Я если честно запутался) Подскажите, как переправить чтобы инпуты срабатывали? п.с. Попробую сделать с просмотром)) Секунду)
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> * { box-sizing: border-box; padding: 0; margin: 0; } ul li { list-style: none; display: inline-block; } .back_style { font-size: 16px; } #back { width: 267px; height: 267px; background-color: rgb(0, 0, 0); display: flex; position: relative; } .d-flex { display: flex; margin-bottom: 1rem; } .space-around { justify-content: space-around; } .flex-column { flex-direction: column; } </style> <body> <div class='d-flex'> <p>background-image:</p> <ul> <li>url(<input type='text' id='bgImage' value="https://javascript.ru/cat/list/donkey.gif">);</li> </ul> </div> <div class='d-flex space-around'> <div class='mr-2'> <h5>background-repeat:</h5> <ul class='d-flex flex-column'> <li><input type='radio' name='repeat' id='norep' checked><label for='norep'>no-repeat</label></li> <li><input type='radio' name='repeat' id='repXY'><label for='repXY'>repeat</label></li> <li><input type='radio' name='repeat' id='repX'><label for='repX'>repeat-x</label></li> <li><input type='radio' name='repeat' id='repY'><label for='repY'>repeat-y</label></li> </ul> </div> <div class='mx-2'> <h5>background-size:</h5> <ul class='d-flex flex-column'> <li><label id='bnoradio'><input type='number' id='sizeIn' value='150' name='size' class='adstl bsize'> px</label></li> <li class='bsckeck'><input type='checkbox' id='sizeOne' name='size'><label for='sizeOne'>cover</label></li> <li class='bsckeck'><input type='checkbox' id='sizeTwo' name='size'><label for='sizeTwo'>contain</label></li> </ul> </div> <div class='ml-2'> <h5>background-position:</h5> <ul class='d-flex flex-column'> <li>Left: <label><input id='posX' type='number' min='0' max='100' value='50' class='adstl bsize'> %</label></li> <li>Top: <label><input id='posY' type='number' min='0' max='100' value='70' class='adstl bsize'> %</label></li> </ul> </div> </div> <div id='back'></div> <script> var back = document.querySelector("#back"), x = document.querySelector("#posX"), y = document.querySelector('#posY'), so = document.querySelector('#sizeOne'), st = document.querySelector('#sizeTwo'), si = document.querySelector('#sizeIn'); (style = () => { back.style.background = `url(${document.querySelector("#bgImage").value}) black ${document.querySelector('[name="repeat"]:checked').parentNode.textContent} ${x.value}% ${y.value}%`; back.style.backgroundSize = so.checked ? 'cover' : st.checked ? 'contain' : si.value + 'px'; })(); document.querySelectorAll('input').forEach(el => el.oninput = style); </script> </body> </head> </html> Получилось)) Я слегка подкорректировал, в принципе и так нормально, но такие тонкости не все поймут, психанут и закроют страничку) |
madeas,
Что-то я в результате не понял, почему у вас раньше не работало? |
Dilettante_Pro,
не работают только радио и чеки. Вернее работают, но после изменений в других полях. Я так понял, что это браузер так себя ведет, хз почему. Так что оставлю пока как есть, может со временем приду к нужному решению. |
madeas,
а смотрели последнюю версию пост 12? Работают радио? Можно также с использованием варианта Nexus |
Dilettante_Pro,
пробовал. это браузер. на телефоне в хроме норм, в других браузерах тоже по разному, но работают. |
Попробуйте вот этот вариант back.style.background
back.style.background = 'url(' + document.querySelector("#bgImage").value+') black '+ document.querySelector('[name="repeat"]:checked').parentNode.textContent +' '+x.value+'% '+y.value+'%'; |
Dilettante_Pro, я так и начал с ', но потом запутался стер и поставил ` они удобней =)
|
j0hnik,
Да я уже всячески с бубнами танцую - у ТС что-то странное... Стоит посмотреть в консоли насчет ошибок и назначения обработчиков ЗЫ: Цитата:
|
Dilettante_Pro,
так это же тоже самое фактически) не помогает. Это всетаки хромиум убонтовский так работает. Жаль что нельзя оставить 2-3 браузера с одинаковой поддержкой, а остальные заблокировать нафиг)) |
Цитата:
Консоль-то что-то говорит? Ошибки? Обработчики на инпуты устанавливаются? Цитата:
|
Цитата:
https://developer.mozilla.org/ru/doc...mplate_strings |
Ребята, подскажите, а как разбить этот бэкграунд на части, чтобы бэкграунд превратился в в бэкграунд-имадже, а другие давали свои параметры?
var back = document.querySelector("#back"), x = document.querySelector("#posX"), y = document.querySelector('#posY'), so = document.querySelector('#sizeOne'), st = document.querySelector('#sizeTwo'), si = document.querySelector('#sizeIn'); (style = () => { back.style.backgroundImage = 'url(' + document.querySelector("#bgImage").value + ') '; back.style.backgroundRepeat = document.querySelector('[name="repeat"]:checked'); back.style.backgroundPosition = + x.value + '% ' + y.value + '%'; back.style.backgroundSize = so.checked ? 'cover' : st.checked ? 'contain' : si.value + 'px'; })(); document.querySelectorAll('input').forEach(el => el.oninput = style); Вроде бы сделал правильно, но не работает. В чем ошибка? |
настроил.
var back = document.querySelector("#back"), x = document.querySelector("#posX"), y = document.querySelector('#posY'), so = document.querySelector('#sizeOne'), st = document.querySelector('#sizeTwo'), si = document.querySelector('#sizeIn'); (style = () => { back.style.backgroundImage = 'url(' + document.querySelector("#bgImage").value + ') '; back.style.backgroundSize = so.checked ? 'cover' : st.checked ? 'contain' : si.value + 'px'; back.style.backgroundRepeat = document.querySelector('[name="repeat"]:checked').parentNode.textContent; back.style.backgroundPosition = y.value + '%' + x.value + '%'; })(); document.querySelectorAll('input').forEach(el => el.oninput = style); |
Часовой пояс GMT +3, время: 03:27. |