Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Добавление background-X (https://javascript.ru/forum/dom-window/74684-dobavlenie-background-x.html)

madeas 31.07.2018 15:59

Добавление background-X
 
Всем привет.
Ребята, помогите составить скрипт.
Нужно при помощи инпутов задать блоку background-image и другие свойства.
Т.е., при вводе ссылки в 1 поле, в блоке #back появляется картинка, которая корректируется при помощи полей, расположенных ниже.
Как правильно составить скрипт? Думал сделать выведение через value, но не уверен, что получится. Знаний js пока не хватает.
Набросал разметку в песочнице https://jsfiddle.net/Lbqfp9g7/

Dilettante_Pro 31.07.2018 16:46

Для начала - только 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>

Nexus 31.07.2018 17:00

<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>

madeas 31.07.2018 17:33

Nexus,
Спасибо. Вообще я предполагал сделать так же, как предложил Dilettante_Pro, но мне кажется, так получилось бы более громоздко.
Dilettante_Pro, спасибо. Я был на верном пути)

j0hnik 31.07.2018 19:12

<!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>

madeas 01.08.2018 12:31

j0hnik,
а можно сделать поля независимыми? Сейчас, когда выбираешь пункты, они не активируются до нажатия на background-size. Т.е. чтобы другие изменения заработали, придется стирать size и писать еще раз.

Dilettante_Pro 01.08.2018 13:01

madeas,
У меня пример j0hnik прекрасно работает в Chrome - изменения срабатывают сразу по любому параметру - и совсем не работает в IE.
Стрелочные функции поддерживают не все браузеры

madeas 01.08.2018 13:50

Dilettante_Pro,
тогда хз, в хромиуме приходится обновлять значение других полей, чтобы сработали repeat'ы. Сами по себе они не меняются почему-то.

madeas 01.08.2018 14:18

Dilettante_Pro,
похоже это особенность браузера, эх... в фоксе и правда норм работает.

Dilettante_Pro 01.08.2018 14:20

Цитата:

Сообщение от madeas
в хромиуме приходится обновлять значение других полей

Именно в примере j0hnik пост 5 здесь в теме через Посмотреть?
Вообще Chrome поддерживает стрелочные функции с версии 45.0
У меня 67.0.3396.99


Часовой пояс GMT +3, время: 18:07.