Как масштабировать, чтобы контейнер также увеличивался и занимал место
Итак, у меня есть контейнер, который я хочу масштабировать вверх и вниз (увеличение и уменьшение), но также иметь расширенную/сжатую форму, чтобы занимать место, а не просто перекрывать другие вещи.
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>
Ответы
Ответ 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
Я использовал бы другие атрибуты, кроме масштаба, что в отличие от масштаба влияет на поток. Вы можете изменить высоту, ширину, край, размер, размер шрифта и т.д.
Изменить: если вы действительно хотите использовать масштаб, чтобы изменить размер всего элемента внутри элемента в едином виде, вы можете иметь внешний элемент, который вы изменяете ширину и высоту, и внутренний элемент, который вы изменяете масштаб на соответствуют ширине и высоте внешних элементов. Внешний элемент будет влиять на поток содержимого. Но я не думаю, что это желательно, так как это не будет выглядеть так хорошо, если вы просто увеличите все возможные значки и текст внутри контейнера, вы, вероятно, захотите сохранить много элементов внутри контейнера одинакового размера, независимо от того, размера контейнера.