旋转并缩放图像以“适应”容器div

27

我正在使用 transform 根据图像的 EXIF 数据旋转图像。然后,我想通过将其适应其父级 div 来“全屏”显示它。

问题在于,max-width / max-height 和所有其他尺寸指令“忽略”旋转(这是正常的,根据 transform 规范,元素的变换在流中是“被忽略”的)。

Jsfiddle:http://jsfiddle.net/puddjm4y/2/

div.top {
    position: fixed;
    width: 100%;
    height: 100%;
    border: 1px solid blue;
}
img {
    transform: rotate(90deg);
    max-width: 100%;
    max-height: 100%;
}
<div class="top">
    <img src="http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg">
</div>

有没有一种方法可以实现这个?


没有忽略任何东西,它只是保持了图像的纵横比。在您的示例中,图像被缩放以适应父元素的宽度,然后再旋转90度。图像的高度恰好等于容器的宽度。 - user229044
1
@meagar 是的,我同意。但是我希望它能够按比例缩放,以适应父元素的高度,因为它将被旋转。 - Blacksad
@meagar,这是第一天。 - Blacksad
http://jsfiddle.net/puddjm4y/15/ 这算是工作吗? - Shih-Min Lee
2
@Blacksad 你找到答案了吗?我遇到了完全相同的问题。我无法使图像完全覆盖其父元素,而且任何一侧都没有空白。 - doubleOrt
显示剩余4条评论
9个回答

14

要实现全屏显示,最简单的方法是使用视口单位来指定图片的宽度和高度:

  • 普通图像应该是100vw宽,100vh高
  • 旋转的图像应该是100vh宽,100vw高

可以使用CSS变换将图像移到中间。以下是一个例子,它使用了两个比视口大和小的图像:

body {
  margin: 0;
}
img {
  display: block;
}
img.normal {
  max-width: 100vw;
  max-height: 100vh;
  transform: translatex(calc(50vw - 50%)) translatey(calc(50vh - 50%));
}
img.rotated {
  max-width: 100vh;
  max-height: 100vw;
  transform: translatex(calc(50vw - 50%)) translatey(calc(50vh - 50%)) rotate(90deg);
}
/* demo */
.demo {
  height: 100vh;
  position: relative;
}
.demo:nth-child(odd) {
  background-color: #CCC;
}
.demo:nth-child(even) {
  background-color: #EEE;
}
.demo::after {
  content: attr(title);
  position: absolute;
  left: 0;
  top: 0;
  padding: .25em .5em;
  background-color: rgba(255, 255, 255, .8);
}
<div class="demo" title="Large image, normal"><img class="normal" src="https://istack.dev59.com/2DdPE.webp"></div>
<div class="demo" title="Large image, rotated"><img class="rotated" src="https://istack.dev59.com/2DdPE.webp"></div>
<div class="demo" title="Small image, normal"><img class="normal" src="https://istack.dev59.com/ustNQ.webp"></div>
<div class="demo" title="Small image, rotated"><img class="rotated" src="https://istack.dev59.com/ustNQ.webp"></div>


3
将元素的高度与宽度相等,或者相反,这是一个Javascript的事情,因为它可以检索这些值并将它们设置回去。
在CSS中无法完成这个功能,也不可能通过动态尺寸实现,我们不知道"100%"确切地等于多少,即使我们知道了,我们也不能使用它们,因为没有对它们的引用。
但是,如果你采用固定值,并可以通过媒体查询进行操作,那么为什么不使用变量呢?这样我们就有了值和对它的引用。

:root {
  --width: 100px;
  --height: 140px;
}

div.top {
  position: fixed;
  width: var(--width);
  height: var(--height);
  border: 1px solid blue;
}

img {
  width: var(--width);
  height: var(--height);
  animation: rotate 3s alternate infinite;
}


/* translate values are the difference between the height */
/* and width divided between the X and Y */
/* 100 - 140 = 40 / 2 = 20px each */

@keyframes rotate {
  to {
    transform: rotate(90deg) translate(20px, 20px);
    width: var(--height);
    height: var(--width);
  }
}
<div class="top">
  <img src="http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg">
</div>

再说一遍,这只是一个想法。

你正在使转换部分变得复杂.. 没有必要进行复杂的计算,只需执行以下操作即可 transform: rotate(90deg) translateY(-100%); transform-origin: top left; - Temani Afif
1
哦,是的,这个优化得多了。 - Rainbow

2

我终于找到了解决这个问题所需的答案,也许它能帮助其他人。 我有一个flex父元素,我需要基于EXIF旋转子元素。 我需要使用image-orientation: from-image;

imgBox {
    flex: 1;
    padding: 1rem;
    overflow: hidden;
 }

 .img1 {
     object-fit: cover;
     max-width: 100%;
     image-orientation: from-image;
 }

这帮助我编写了一个解决方案的函数 - 关键是将容器设置为flexbox,并使用JS更改容器的高度以匹配图像在侧向旋转时的宽度。 - anba

2
我会选择像这样的东西(使用视口大小交换最大宽度/高度)

* {
  box-sizing:border-box;
}

html, body {
  margin:0;
}

div.top {
    position: fixed;
    width: 100%;
    height: 100%;
    top:0;
    left:0;
    border: 1px solid blue;
    display:flex;
}
img {
    transform: rotate(90deg);
    max-width: 100vh;
    max-height: 100vw;
    margin:auto;
}
<div class="top">
    <img src="http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg">
</div>


@Rafael 无论如何这都会起作用,我相信 position:fixed; 是用于某种叠加框的。 - Maciej Kwas
@MaciejKwas 你确定吗? - Rafael

1
你可以通过检查容器高度并将图像的maxWidth设置为容器的高度来使用JavaScript实现此操作。
 /**
 * Set max width of a rotated image to container height
 * @param {*} container
 * @param {*} image
 */
function setRotatedImageWidth(container = null, image = null) {
    if (!container || !image) {
        return false; // exit if empty
    }
    var h = container.offsetHeight; // Container height
    var w = image.offsetWidth; // Image width

    // If image width is greater container height
    if (w > h) {
        image.style.maxWidth = h + 'px';
    }
}

var container = document.querySelector('.container');
var image = container.querySelector('img');
setRotatedImageWidth(container, image);

0

如果您可以忽略变换部分,因为这是一个纵横比的问题,没有答案,但将图像显示到父元素的100%是可能的,并且不需要任何媒体查询。 100%相对于父级,对于图像来说,它是纵横比规则尺寸的关键。我们可以拉伸它,但那样并不能达到目的。希望下面的CSS能在某种程度上帮助您。

div.top {
    position: fixed;
    width: 100%;
    height: 100%;
    border: 1px solid blue;
    background-image:url("http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg");
    background-size:cover;
    background-repeat:no-repeat;
    background-position:50%;
}
div.top img {
    /* transform: rotate(90deg); */
    min-width: 100%;
    min-height: 100%;
    visibility:hidden;
}

0
这是一个简略的尝试,需要手动同步宽度/高度。对于愿意使用JS的人来说,应该很容易同步。

div.top {
    border: 1px solid blue;
    box-sizing: border-box;
    width: 100%;
    height: 300px;/* SYNC */
    position: relative;
    overflow: hidden;
}

div.top:before {
  content: "";
  position: absolute;
  width: 300px;/* SYNC */
  height: 100%; 
  transform: rotate(90deg);
  background-image: url(http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg);
  background-size: contain;
  background-repeat: no-repeat;
}
<div class="top"></div>

定位变得尴尬了。不过,我希望有人能从这里分支出去,并想出一个更好的解决方案。


0

-2

关于 exif 部分,你不能使用 CSS 进行操作,因为 CSS 无法读取 exif 数据。

但对于 CSS 部分,你需要使用 transform-origin,而不仅仅是 transform,并且还需要使用宽度为 100% 和高度自适应以保持比例。

这里是一个例子: http://jsfiddle.net/yxqgt2d1/1/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接