javascript - tome - imagen de fondo ocupe todo el div css
Cómo escalar para que el contenedor también crezca y ocupe espacio (6)
Editar: lo arrepentí, quise decir actualizar el contenedor
Puedes, agrega un contenedor. Almacene el tamaño inicial de este contenedor. Ahora cuando se escala en el elemento interno, actualice el ancho / alto del contenedor a la misma proporción.
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>
Así que tengo un contenedor que quiero escalar hacia arriba y hacia abajo (acercar y alejar) pero también tiene su forma expandida / reducida para ocupar espacio en lugar de simplemente superponer otras cosas.
Actualizar
Hay una imagen con divs absolute
que se colocan en coordenadas, deben conservar sus posiciones relativas cuando se aumenta y disminuye el tamaño (de ahí por qué estoy usando la escala).
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>
Preferiría no tener bibliotecas de terceros (al lado de jQuery) pero podría considerar.
La mejor idea es usar el porcentaje dinámico ( %
) de altura, ancho y posición para cada elemento secundario.
Simplemente dividimos todos los valores de píxel con ancho o alto según sea necesario y en JS simplemente cambiamos el ancho del contenedor principal y observamos la magia;)
Encuentre el código a continuación, agregue los comentarios apropiados cuando los valores hayan cambiado.
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>
PD para mostrar el marcador como una casilla, establecemos su ancho como el relleno superior (que cuando se establece como un porcentaje es relativo al ancho principal) para que siempre se muestre como un cuadrado. ;)
Esto, en mi opinión, es mucho más manejable ya que no tiene que procesar cada elemento en JS.
Las transiciones de scale
CSS3 funcionan así. Desafortunadamente, el escalado se superpondrá a otros elementos a medida que saca el contenido del contenedor del flujo mediante la creación de un nuevo contexto de apilamiento (esencialmente colocando todos sus contenidos posicionados en relación con el contenedor); consulte la descripción del documento pertinente:
Si la propiedad tiene un valor diferente a ninguno, se creará un contexto de apilamiento.
Fuente: MDN
Vea una demostración a continuación, escalando todos los elementos por fuerza bruta:
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>
Lo probé con el ancho y alto, creo que funcionará de la manera que desee, agregue una animación pequeña y puede usarla.
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>
Si su caso de uso es tan simple como su ejemplo, creo que puede estar complicando demasiado las cosas. Si necesita elementos de su hijo para mantener su posición relativa con el padre, solo necesita definir sus ubicaciones usando unidades relativas en lugar de unidades absolutas y dejar que el motor de renderizado de CSS haga su trabajo.
Aquí he establecido el ancho del elemento principal (en lugar de la escala), hago que la imagen ajuste el tamaño automáticamente en el contenedor para establecer su altura, y he usado porcentajes en lugar de píxeles.
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>
Usaría otros atributos además de la escala, que a diferencia de la escala afectan el flujo. Podrías cambiar la altura, el ancho, el margen, el relleno, el tamaño de letra, etc. del div.
Editar: si realmente quieres usar la escala para cambiar el tamaño de todo dentro del elemento de una manera uniforme, podrías tener un elemento externo del que cambias el ancho y la altura, y un elemento interno que cambias de escala para que coincida con el exterior elementos ancho y alto. El elemento externo afectará el flujo del contenido. Pero realmente no creo que sea deseable, ya que de todos modos no se verá tan bien si solo amplías todos los iconos y texto eventuales dentro del contenedor, probablemente quieras mantener muchos elementos dentro del contenedor con el mismo tamaño independientemente del tamaño del contenedor.