如何使用 JavaScript 获取 CSS 背景图片的尺寸?

43

是否可以使用JavaScript获取CSS引用的背景图片的实际大小(以像素为单位的宽度和高度)?

7个回答

62

是的,我会这样做...

window.onload = function () {
  var imageSrc = document
    .getElementById('hello')
    .style.backgroundImage.replace(/url\((['"])?(.*?)\1\)/gi, '$2')
    .split(',')[0];

  // I just broke it up on newlines for readability

  var image = new Image();
  image.src = imageSrc;

  image.onload = function () {
    var width = image.width,
      height = image.height;
    alert('width =' + width + ', height = ' + height);
  };
};

一些注释...

  • 我们需要移除JavaScript返回的url()部分,以获取正确的图像源。我们需要在元素具有多个背景图片的情况下进行,拆分。
  • 我们创建一个新的Image对象并将其src设置为新图像。
  • 然后我们可以读取宽度和高度。

使用jQuery可能会减少很多麻烦。


这段代码无法处理数据URL,因为它使用了split函数。我已经删除了split函数,因为我只使用了单个背景,但是如果需要检查data:的存在,则需要使用额外的if语句。 - Timmerz
@Timmerz 抱歉,我打开了几个标签页,并且在回复时没有处于正确的上下文中。 - alex
1
document.getElementById('hello').attributes.src.value 对我有效。 - Zachary Ryan Smith
1
@ZacharyRyanSmith 我刚试了一下加上背景图片,发现 src 属性在 attributes 中没有定义。你确定这是一个背景图片,而不是普通的 img 元素吗? - alex
1
你应该在 image.onload 处理程序中设置宽度和高度;如果你不这样做,当你的互联网连接较慢或图像很大时,宽度/高度可能为0。 - thdoan
显示剩余13条评论

14

无法在回答下发表评论,所以这里是包括background-size的jQuery版本(发布此版本是因为此问题是谷歌搜索中的第一个问题,可能对其他人有用):

无法在答案下发表评论,因此这里提供了包含 background-size 的jQuery版本(发布此版本是因为此问题是谷歌搜索中的第一个问题,可能对其他人有用):

<code>function getBackgroundSize(selector, callback) {
  var img = new Image(),
      // here we will place image's width and height
      width, height,
      // here we get the size of the background and split it to array
      backgroundSize = $(selector).css('background-size').split(' ');

  // checking if width was set to pixel value
  if (/px/.test(backgroundSize[0])) width = parseInt(backgroundSize[0]);
  // checking if width was set to percent value
  if (/%/.test(backgroundSize[0])) width = $(selector).parent().width() * (parseInt(backgroundSize[0]) / 100);
  // checking if height was set to pixel value
  if (/px/.test(backgroundSize[1])) height = parseInt(backgroundSize[1]);
  // checking if height was set to percent value
  if (/%/.test(backgroundSize[1])) height = $(selector).parent().height() * (parseInt(backgroundSize[0]) / 100);

  img.onload = function () {
    // check if width was set earlier, if not then set it now
    if (typeof width == 'undefined') width = this.width;
    // do the same with height
    if (typeof height == 'undefined') height = this.height;
    // call the callback
    callback({ width: width, height: height });
  }
  // extract image source from css using one, simple regex
  // src should be set AFTER onload handler
  img.src = $(selector).css('background-image').replace(/url\(['"]*(.*?)['"]*\)/g, '$1');
}
</code>

或作为jQuery插件:

<code>(function ($) {
// for better performance, define regexes once, before the code
var pxRegex = /px/, percentRegex = /%/, urlRegex = /url\(['"]*(.*?)['"]*\)/g;
$.fn.getBackgroundSize = function (callback) {
  var img = new Image(), width, height, backgroundSize = this.css('background-size').split(' ');

  if (pxRegex.test(backgroundSize[0])) width = parseInt(backgroundSize[0]);
  if (percentRegex.test(backgroundSize[0])) width = this.parent().width() * (parseInt(backgroundSize[0]) / 100);
  if (pxRegex.test(backgroundSize[1])) height = parseInt(backgroundSize[1]);
  if (percentRegex.test(backgroundSize[1])) height = this.parent().height() * (parseInt(backgroundSize[0]) / 100);
  // additional performance boost, if width and height was set just call the callback and return
  if ((typeof width != 'undefined') && (typeof height != 'undefined')) {
    callback({ width: width, height: height });
    return this;
  }
  img.onload = function () {
    if (typeof width == 'undefined') width = this.width;
    if (typeof height == 'undefined') height = this.height;
    callback({ width: width, height: height });
  }
  img.src = this.css('background-image').replace(urlRegex, '$1');
  return this;
}
})(jQuery);
</code>

1
糟糕!抱歉,它提供的是 未缩放的 图像尺寸。但我仍然喜欢它! - emrys57
1
那个正则表达式可能存在潜在的错误。这是正确的正则表达式: urlRegex = /url\(['"]*(.*?)['"]*\)/g - neochief
你能否解释一下如何使用它?或者给出一个例子,无论是函数还是插件。谢谢。 - jevgenij
@JonLennartAasenden 兄弟,我添加了一个 jQuery 版本,原因在答案开头已经说明了。如果你想发泄对 jQuery 的仇恨,请到别处去,这里没有人需要狂热者。 - klh
@ItagakiFumihiko 九年了,竟然没有人注意到一个错别字 :D 随意使用编辑功能进行修正,这样你就能获得发现它的荣誉。不幸的是,我已经不记得为什么需要 .parent(),因为这没有任何意义。 - klh
显示剩余6条评论

11
var actualImage = new Image();
actualImage.src = $('YOUR SELECTOR HERE').css('background-image').replace(/"/g,"").replace(/url\(|\)$/ig, "");

actualImage.onload = function() {
    width = this.width;
    height = this.height;
}

12
如果背景图片被缩放,而您想获取缩放后的宽度和高度值,该怎么办? - prismspecs

5
var dimension, image;

image = new Image();
image.src = {url/data}
image.onload = function() {
    dimension = {
        width: image.naturalWidth,
        height: image.naturalHeight
    };
    console.log(dimension); // Actual image dimension
};

1
尽管这个问题和答案很老,但这对我很有用。我还编辑了答案以修复语法问题,并在设置image.src变量时使用了Killah的有用正则表达式。 - AuRise
使用' naturalWidth '和' naturalHeight '就像一件轻而易举的事情一样。 - Mau

2

以下是使用jQuery的示例:

var actualImage = new Image();
actualImage.src = $('YOUR SELECTOR HERE').css('background-image').replace(/"/g,"").replace(/url\(|\)$/ig, "");

actualImage.width // The actual image width
actualImage.height // The actual image height

感谢Alex提供的正则表达式技巧。

1
除了在Chrome浏览器上无法正常工作外。火狐浏览器似乎可以加载图像,但Chrome不能。因此actualImage的宽度和高度属性始终为0。 - magiconair

0

这里是klh帖子中代码的修正版本。 我在他的评论区指出了一些小错误,并被告知请编辑它。 于是我就这么做了。 然而,审核者Jan WilamowskiDave拒绝了它。

"这个编辑意图是为了回复帖子的作者,作为编辑并没有任何意义。它应该被写成一个评论或答案。"

显然他们没有看到评论区。

我别无选择,只能将修订后的代码作为新答案编写。

function getBackgroundSize(selector, callback) {
  var img = new Image(),
      // here we will place image's width and height
      width, height,
      // here we get the size of the background and split it to array
      backgroundSize = $(selector).css('background-size').split(' ');

  // checking if width was set to pixel value
  if (/px/.test(backgroundSize[0])) width = parseInt(backgroundSize[0]);
  // checking if width was set to percent value
  if (/%/.test(backgroundSize[0])) width = $(selector).width() * (parseInt(backgroundSize[0]) / 100);
  // checking if height was set to pixel value
  if (/px/.test(backgroundSize[1])) height = parseInt(backgroundSize[1]);
  // checking if height was set to percent value
  if (/%/.test(backgroundSize[1])) height = $(selector).height() * (parseInt(backgroundSize[1]) / 100);

  img.onload = function () {
    // check if width was set earlier, if not then set it now
    if (typeof width == 'undefined') width = this.width;
    // do the same with height
    if (typeof height == 'undefined') height = this.height;
    // call the callback
    callback({ width: width, height: height });
  }
  // extract image source from css using one, simple regex
  // src should be set AFTER onload handler
  img.src = $(selector).css('background-image').replace(/url\(['"]*(.*?)['"]*\)/g, '$1');
}

JQuery

(function ($) {
// for better performance, define regexes once, before the code
var pxRegex = /px/, percentRegex = /%/, urlRegex = /url\(['"]*(.*?)['"]*\)/g;
$.fn.getBackgroundSize = function (callback) {
  var img = new Image(), width, height, backgroundSize = this.css('background-size').split(' ');

  if (pxRegex.test(backgroundSize[0])) width = parseInt(backgroundSize[0]);
  if (percentRegex.test(backgroundSize[0])) width = this.width() * (parseInt(backgroundSize[0]) / 100);
  if (pxRegex.test(backgroundSize[1])) height = parseInt(backgroundSize[1]);
  if (percentRegex.test(backgroundSize[1])) height = this.height() * (parseInt(backgroundSize[1]) / 100);
  // additional performance boost, if width and height was set just call the callback and return
  if ((typeof width != 'undefined') && (typeof height != 'undefined')) {
    callback({ width: width, height: height });
    return this;
  }
  img.onload = function () {
    if (typeof width == 'undefined') width = this.width;
    if (typeof height == 'undefined') height = this.height;
    callback({ width: width, height: height });
  }
  img.src = this.css('background-image').replace(urlRegex, '$1');
  return this;
}
})(jQuery);

0
如果你正在使用React,你可以创建一个自定义Hook:
import { useEffect, useState, useCallback, useRef } from 'react'

const urlRgx = /url\((['"])?(.+?)\1\)/
const getImagePromise = src =>
  new Promise(resolve => {
    const img = new Image()

    img.onload = () =>
      resolve({
        src,
        width: img.naturalWidth,
        height: img.naturalHeight
      })
    img.src = src
  })
const useBackgroundImageSize = (asCallbackFlagOrUrls = false) => {
  const ref = useRef()
  const [images, setImages] = useState(null)
  const callback = useCallback(async () => {
    if (Array.isArray(asCallbackFlagOrUrls)) {
      const imgPromises = asCallbackFlagOrUrls.map(getImagePromise)
      const imgs = await Promise.all(imgPromises)

      if (ref?.current) {
        setImages(imgs)
      }
    }

    if (typeof asCallbackFlagOrUrls === 'string') {
      const image = await getImagePromise(asCallbackFlagOrUrls)

      if (ref?.current) {
        setImages(image)
      }
    }

    if (typeof asCallbackFlagOrUrls === 'boolean') {
      if (ref.current) {
        const matches = window
          .getComputedStyle(ref.current)
          .backgroundImage.match(new RegExp(urlRgx, 'g'))

        if (Array.isArray(matches)) {
          const imgPromises = matches.map(match =>
            getImagePromise(match.replace(new RegExp(urlRgx), '$2'))
          )
          const imgs = await Promise.all(imgPromises)

          if (ref?.current) {
            setImages(imgs.length > 1 ? imgs : imgs[0])
          }
        }
      }
    }
  }, [ref, asCallbackFlagOrUrls])

  useEffect(() => {
    if (asCallbackFlagOrUrls !== true) {
      callback()
    }
  }, [asCallbackFlagOrUrls, callback])

  return asCallbackFlagOrUrls === true ? [ref, images, callback] : [ref, images]
}

export { useBackgroundImageSize }

然后像这样使用:

const App = () => {
  const [ref, image] = useBackgroundImageSize()

  console.log(image) // { width, height, src }

  return <div ref={ref} image={image} />
}

您还可以安装background-image-size-hook并将其用作依赖项。有关更多使用详细信息,请参见README


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