对象拟合:得到结果尺寸

时间:2016-05-16 14:47:22

标签: javascript jquery css css3

使用新的CSS功能object-fit时,如何访问浏览器通过JavaScript选择的结果维度?

因此,我们假设foo.jpg为100x200像素。浏览器页面/视口宽400像素,高300像素。然后给出这个CSS代码:

img.foo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 25% 0;
}

浏览器现在将图像显示在最顶部,正确的纵横比从左侧延伸到第二个四分之一的底部。这会产生这些图像尺寸:

  • 宽度:150px
  • 身高:300px
  • left:62.5px
  • 右:212.5px

那么JavaScript调用(jQuery允许)会给我那些我手动计算过的数字吗? (注意:JavaScript不知道CSS信息本身,因为用户可以覆盖它们,甚至添加min-width等内容

要使用代码,我创建了一个小提琴:https://jsfiddle.net/sydeo244/

3 个答案:

答案 0 :(得分:3)

感谢@bfred,我没有必要制作初始方法。

这是他的扩展(并重写)版本,它也会计算object-position值。



function getRenderedSize(contains, cWidth, cHeight, width, height, pos){
  var oRatio = width / height,
      cRatio = cWidth / cHeight;
  return function() {
    if (contains ? (oRatio > cRatio) : (oRatio < cRatio)) {
      this.width = cWidth;
      this.height = cWidth / oRatio;
    } else {
      this.width = cHeight * oRatio;
      this.height = cHeight;
    }      
    this.left = (cWidth - this.width)*(pos/100);
    this.right = this.width + this.left;
    return this;
  }.call({});
}

function getImgSizeInfo(img) {
  var pos = window.getComputedStyle(img).getPropertyValue('object-position').split(' ');
  return getRenderedSize(true,
                         img.width,
                         img.height,
                         img.naturalWidth,
                         img.naturalHeight,
                         parseInt(pos[0]));
}

document.querySelector('#foo').addEventListener('load', function(e) {
  console.log(getImgSizeInfo(e.target));
});
&#13;
#container {
  width: 400px;
  height: 300px;
  border: 1px solid blue;
}

#foo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 25% 0;
}
&#13;
<div id="container">
  <img id="foo" src="http://dummyimage.com/100x200/000/fff.jpg"/>
</div>
&#13;
&#13;
&#13;

旁注

看来object-position可以有两个以上的值,当你需要调整(或添加)哪个参数返回左侧位置值

答案 1 :(得分:1)

有一个名为intrinsic-scale的npm包会为您计算,但它不支持相当于object-positionhttps://www.npmjs.com/package/intrinsic-scale

这是整个代码:

// adapted from: https://www.npmjs.com/package/intrinsic-scale
function getObjectFitSize(contains /* true = contain, false = cover */, containerWidth, containerHeight, width, height){
    var doRatio = width / height;
    var cRatio = containerWidth / containerHeight;
    var targetWidth = 0;
    var targetHeight = 0;
    var test = contains ? (doRatio > cRatio) : (doRatio < cRatio);

    if (test) {
        targetWidth = containerWidth;
        targetHeight = targetWidth / doRatio;
    } else {
        targetHeight = containerHeight;
        targetWidth = targetHeight * doRatio;
    }

    return {
        width: targetWidth,
        height: targetHeight,
        x: (containerWidth - targetWidth) / 2,
        y: (containerHeight - targetHeight) / 2
    };
}

用法是:

getObjectFitSize(true, img.width, img.height, img.naturalWidth, img.naturalHeight);

答案 2 :(得分:1)

这是一个更全面的算法,经过测试,以确定图像在屏幕上的显示方式。

var imageComputedStyle = window.getComputedStyle(image);
var imageObjectFit = imageComputedStyle.getPropertyValue("object-fit");
coordinates = {};
var imagePositions = imageComputedStyle.getPropertyValue("object-position").split(" ");
var horizontalPercentage = parseInt(imagePositions[0]) / 100;
var verticalPercentage = parseInt(imagePositions[1]) / 100;
var naturalRatio = image.naturalWidth / image.naturalHeight;
var visibleRatio = image.width / image.height;
if (imageObjectFit === "none")
{
  coordinates.sourceWidth = image.width;
  coordinates.sourceHeight = image.height;
  coordinates.sourceX = (image.naturalWidth - image.width) * horizontalPercentage;
  coordinates.sourceY = (image.naturalHeight - image.height) * verticalPercentage;
  coordinates.destinationWidthPercentage = 1;
  coordinates.destinationHeightPercentage = 1;
  coordinates.destinationXPercentage = 0;
  coordinates.destinationYPercentage = 0;
}
else if (imageObjectFit === "contain" || imageObjectFit === "scale-down")
{
  // TODO: handle the "scale-down" appropriately, once its meaning will be clear
  coordinates.sourceWidth = image.naturalWidth;
  coordinates.sourceHeight = image.naturalHeight;
  coordinates.sourceX = 0;
  coordinates.sourceY = 0;
  if (naturalRatio > visibleRatio)
  {
    coordinates.destinationWidthPercentage = 1;
    coordinates.destinationHeightPercentage = (image.naturalHeight / image.height) / (image.naturalWidth / image.width);
    coordinates.destinationXPercentage = 0;
    coordinates.destinationYPercentage = (1 - coordinates.destinationHeightPercentage) * verticalPercentage;
  }
  else
  {
    coordinates.destinationWidthPercentage = (image.naturalWidth / image.width) / (image.naturalHeight / image.height);
    coordinates.destinationHeightPercentage = 1;
    coordinates.destinationXPercentage = (1 - coordinates.destinationWidthPercentage) * horizontalPercentage;
    coordinates.destinationYPercentage = 0;
  }
}
else if (imageObjectFit === "cover")
{
  if (naturalRatio > visibleRatio)
  {
    coordinates.sourceWidth = image.naturalHeight * visibleRatio;
    coordinates.sourceHeight = image.naturalHeight;
    coordinates.sourceX = (image.naturalWidth - coordinates.sourceWidth) * horizontalPercentage;
    coordinates.sourceY = 0;
  }
  else
  {
    coordinates.sourceWidth = image.naturalWidth;
    coordinates.sourceHeight = image.naturalWidth / visibleRatio;
    coordinates.sourceX = 0;
    coordinates.sourceY = (image.naturalHeight - coordinates.sourceHeight) * verticalPercentage;
  }
  coordinates.destinationWidthPercentage = 1;
  coordinates.destinationHeightPercentage = 1;
  coordinates.destinationXPercentage = 0;
  coordinates.destinationYPercentage = 0;
}
else
{
  if (imageObjectFit !== "fill")
  {
    console.error("unexpected 'object-fit' attribute with value '" + imageObjectFit + "' relative to");
  }
  coordinates.sourceWidth = image.naturalWidth;
  coordinates.sourceHeight = image.naturalHeight;
  coordinates.sourceX = 0;
  coordinates.sourceY = 0;
  coordinates.destinationWidthPercentage = 1;
  coordinates.destinationHeightPercentage = 1;
  coordinates.destinationXPercentage = 0;
  coordinates.destinationYPercentage = 0;
}

其中image是HTML <img>元素而coordinates包含以下属性,因为我们认为sourceFrame是图像定义的矩形(如果它是完全打印的) ,即其自然尺寸,printFrame是实际显示的区域,即printFrame.width = image.widthprintFrame.height = image.height

  • sourceX:应该剪切sourceFrame的左上角水平位置
  • sourceY:应该剪切sourceFrame的左上角的垂直位置,
  • sourceWidth:应切割sourceFrame的水平空间,
  • sourceHeight:应该切割sourceFrame的垂直空间,
  • destinationXPercentage:相对于printFrame宽度,{/ 1}}打印图像的左上角水平位置的百分比
  • printFrame:相对于destinationYPercentage高度,printFrame打印图像的左上角的垂直位置百分比
  • printFrame:相对于destinationWidthPercentage宽度,
  • 打印图像的printFrame宽度的百分比
  • printFrame:相对于destinationHeightPercentage高度,图像打印的printFrame高度的百分比。

抱歉,printFrame案件未得到处理,因为其定义不明确。