Подтвердить что ты не робот

Как масштабировать, чтобы контейнер также увеличивался и занимал место

Итак, у меня есть контейнер, который я хочу масштабировать вверх и вниз (увеличение и уменьшение), но также иметь расширенную/сжатую форму, чтобы занимать место, а не просто перекрывать другие вещи.

Update

Есть изображение, в котором есть absolute divs, которые помещаются в координаты, они должны сохранять свои относительные позиции при определении размеров вверх и вниз (следовательно, почему я использую масштаб).

var b = document.getElementById("outer");
var scale = 1;

function increase() {
  scale += 0.1
  b.style.transform = `scale(${scale})`;
}

function decrease() {
  scale -= 0.1
  b.style.transform = `scale(${scale})`;
}
#outer {
  overflow-x: auto position: relative;
  transform-origin: left top;
}

.pointer {
  width: 20px;
  height: 20px;
  background-color: orange;
  position: absolute;
}

#a1 {
  top: 50px;
  left: 150px;
}

#a2 {
  top: 150px;
  left: 50px;
}

#a3 {
  top: 250px;
  left: 550px;
}
<div>
  <button onclick="increase()">Increase</button>
  <button onclick="decrease()">Decrease</button>
</div>
<div id=outer>
  <img src="http://via.placeholder.com/600x350" />
  <div id="a1" class='pointer'>
  </div>
  <div id="a2" class='pointer'>
  </div>
  <div id="a3" class='pointer'>
  </div>
</div>
<div>
  please don't cover me
</div>
4b9b3361

Ответ 1

Переходы CSS3 scale работают так. К сожалению, масштабирование будет перекрывать другие элементы, так как он берет содержимое контейнера из потока, создавая новый контекст стекирования (по существу, помещая все его содержимое в положение относительно контейнера) - см. Соответствующее описание документа:

Если свойство имеет значение, отличное от none, то контекст стекирования будут созданы.

Источник: MDN

См. демонстрацию ниже масштабирования всех элементов с помощью грубой силы:

var b, scale = 1, offset, pointers;

window.onload = function() {
  b = document.getElementById("outer");
  offset = b.getBoundingClientRect();
  pointers = Array.prototype.map.call(b.querySelectorAll('.pointer'), function(e) {
    return {
      el: e,
      offset: e.getBoundingClientRect()
    }
  });
}

function increase() {
  scale += 0.1;
  scaleIt();
}

function decrease() {
  scale -= 0.1;
  scaleIt();
}

function scaleIt() {
  b.style.width = scale * offset.width + 'px';
  b.style.height = scale * offset.height + 'px';
  Array.prototype.forEach.call(pointers, function(e) {
    e.el.style.width = scale * e.offset.width + 'px';
    e.el.style.height = scale * e.offset.height + 'px';
    e.el.style.top = scale * e.offset.top + 'px';
    e.el.style.left = scale * e.offset.left + 'px';
  });
}
#outer {
  /*overflow-x: auto;*/
  position: relative;
  transform-origin: left top;
}
.pointer {
  width: 20px;
  height: 20px;
  background-color: orange;
  position: absolute;
}
#outer > img {
  height: 100%;
}

#a1 {
  top: 50px;
  left: 150px;
}
#a2 {
  top: 150px;
  left: 50px;
}
#a3 {
  top: 250px;
  left: 550px;
}
<div>
    <button onclick="increase()">Increase</button>
    <button onclick="decrease()">Decrease</button>
</div>
<div id=outer>
  <img src="http://via.placeholder.com/600x350" />
  <div id="a1" class='pointer'>
  </div>
  <div id="a2" class='pointer'>
  </div>
  <div id="a3" class='pointer'>
  </div>
</div>
<div>
    please don't cover me
</div>

Ответ 2

Я пробовал его с шириной и высотой, я думаю, что будет работать так же, как вы хотите, добавьте небольшую анимацию, и вы можете ее использовать.

var b = document.getElementById("outer");
var b_width = document.getElementById("outer").offsetWidth;
var b_height = document.getElementById("outer").offsetHeight;

function increase()
{
    b_width += 10
    b_height += 10
    b.style.width = b_width+"px";
    b.style.height = b_height+"px";
}

function decrease()
{
    b_width -= 10
    b_height -= 10
    b.style.width = b_width+"px";
    b.style.height = b_height+"px";
}
#outer {
  background-color: red;
  padding: 1em;
  height: 80px;
  width: 80px;
  transform-origin: left top;
}

#inner {
  background-color: yellow;
  height: 50px;
  width: 100%;
}
<div>
    <button onclick="increase()">Increase</button>
    <button onclick="decrease()">Decrease</button>
</div>
<div id=outer>
  <div id=inner>
  </div>
</div>
<div>
    please don't cover me
</div>

Ответ 3

Редактировать: извините, что он бросил его, я имел в виду обновление контейнера

Вы можете добавить контейнер. Сохраните исходный размер этого контейнера. Теперь, когда вы масштабируете внутренний элемент, обновите контейнер ширина/высота до того же самого отношения.

var a = document.getElementById("outer-wrapper");
var b = document.getElementById("outer");
var scale = 1;
var aWidth = a.offsetWidth;
var aHeight = a.offsetHeight;

function increase()
{
    scale += 0.1
    b.style.transform = `scale(${scale})`;
    a.style.width = `${scale * aWidth}px`;
    a.style.height = `${scale * aHeight}px`;
}

function decrease()
{
    scale -= 0.1
    b.style.transform = `scale(${scale})`;
    a.style.width = `${scale * aWidth}px`;
    a.style.height = `${scale * aHeight}px`;
}
#outer {
  position: relative;
  transform-origin: left top;
}

.pointer {
  width: 20px;
  height: 20px;
  background-color: orange;
  position: absolute;
}

#a1 {
  top: 50px;
  left: 150px;
}
#a2 {
  top: 150px;
  left: 50px;
}
#a3 {
  top: 250px;
  left: 550px;
}
<div>
    <button onclick="increase()">Increase</button>
    <button onclick="decrease()">Decrease</button>
</div>
<div id="outer-wrapper">
  <div id="outer">
    <img src="http://via.placeholder.com/600x350" />
    <div id="a1" class='pointer'>
    </div>
    <div id="a2" class='pointer'>
    </div>
    <div id="a3" class='pointer'>
    </div>
  </div>
</div>
<div>
    please don't cover me
</div>

Ответ 4

Если ваш пример использования так же прост, как ваш пример, я думаю, что вы можете слишком усложнять ситуацию. Если вам нужны ваши дочерние элементы для поддержания их относительной позиции для родителя, вам просто нужно определить их местоположения, используя относительные единицы, а не абсолютные единицы, и пусть движок рендеринга CSS сделает свое дело.

Здесь я установил ширину родительского (а не масштаба), автоматически определяю размер изображения, сопоставляя его с контейнером, чтобы установить его высоту, и использовал проценты, а не пиксели.

var b = document.getElementById("outer");
var width = 600;

function increase() {
  width = width * 1.1
  b.style.width = width + 'px';
}

function decrease() {
  width = width / 1.1
  b.style.width = width + 'px';
}
#outer {
  position: relative;
}

#outer img {
    width: 100%;
    height: auto;
}

.pointer {
  width: 3.333%;
  height: 5.714%;
  background-color: orange;
  position: absolute;
}

#a1 {
  top: 8.333%;
  left: 14.285%;
}

#a2 {
  top: 42.857%;
  left: 8.333%;
}

#a3 {
  top: 71.428%;
  left: 91.667%;
}
<div>
  <button onclick="increase()">Increase</button>
  <button onclick="decrease()">Decrease</button>
</div>
<div id=outer>
  <img src="http://via.placeholder.com/600x350" />
  <div id="a1" class='pointer'>
  </div>
  <div id="a2" class='pointer'>
  </div>
  <div id="a3" class='pointer'>
  </div>
</div>
<div>
  please don't cover me
</div>

Ответ 5

Лучше всего использовать динамический процент (%) высоту, ширину и позиции для каждого дочернего элемента.

Мы просто делим все значения пикселей по ширине или высоте по мере необходимости и в JS простое изменение ширины родительского контейнера и наблюдение за магией;)

Пожалуйста, найдите код ниже, добавьте соответствующие комментарии, где значения изменены.

var b = document.getElementById("outer");
var scale = 1;

function increase() {
  scale += 0.1
  // Just change the width of parent
  b.style.width = 600 * scale + "px";
}

function decrease() {
  scale -= 0.1
  // Just change the width of parent
  b.style.width = 600 * scale + "px";
}
#outer {
  overflow-x: auto;
  position: relative;
  transform-origin: left top;
  width: 600px; /* Give div static width for children to position correctly */
}

#outer img {
  width: 100%; /* Set image to stretch full width */
}

.pointer {
  width: 3.33%; /* 20px/600px*100% */
  padding-top: 3.33%;/* Don't use static height */
  background-color: orange;
  position: absolute;
}

#a1 {
  top: 14.28%;/* 50px/350px*100% */
  left: 25%;/* 150px/600px*100% */
}

#a2 {
  top: 42.85%;/* 150px/350px*100% */
  left: 8.33%;/* 50px/600px*100% */
}

#a3 {
  top: 71.42%;/* 250px/350px*100% */
  left: 91.66%; /* 550px/600px*100% */
}
<div>
  <button onclick="increase()">Increase</button>
  <button onclick="decrease()">Decrease</button>
</div>
<div id=outer>
  <img src="http://via.placeholder.com/600x350" />
  <div id="a1" class='pointer'>
  </div>
  <div id="a2" class='pointer'>
  </div>
  <div id="a3" class='pointer'>
  </div>
</div>
<div>
  please don't cover me
</div>

Ответ 6

Я использовал бы другие атрибуты, кроме масштаба, что в отличие от масштаба влияет на поток. Вы можете изменить высоту, ширину, край, размер, размер шрифта и т.д.

Изменить: если вы действительно хотите использовать масштаб, чтобы изменить размер всего элемента внутри элемента в едином виде, вы можете иметь внешний элемент, который вы изменяете ширину и высоту, и внутренний элемент, который вы изменяете масштаб на соответствуют ширине и высоте внешних элементов. Внешний элемент будет влиять на поток содержимого. Но я не думаю, что это желательно, так как это не будет выглядеть так хорошо, если вы просто увеличите все возможные значки и текст внутри контейнера, вы, вероятно, захотите сохранить много элементов внутри контейнера одинакового размера, независимо от того, размера контейнера.