JavaScript 获取图片的宽度和高度的方法

目录
  1. 1. 1、简陋获取宽高的方法
  2. 2. 2、onload 之后获取
  3. 3. 3、通过complete和onload一起混合使用
  4. 4. 4、循环定时检测获取宽高

快速获取图片的宽高其实就是为了先做好排版布局做好准备,通过快速获取图片宽高的方法比如onload要节省甚多时间,甚至一分钟以上都有可能,并且这种方法适用于主流浏览器和低版本浏览器。

1、简陋获取宽高的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
/* 图片地址 加日期为了避免缓存 get请求 */
let img_url = 'images/front.jpg?'+Date.parse(new Date());

// 创建对象
let img = new Image();

// 创建对象
img.src = img_url;

// 打印数据
console.log('width:'+img.width+', height:'+img.height);
</script>

结果

宽高都是0,因为加载图片是异步的,在图片的相关数据没有加载完之后,宽高都是默认为0,所以可以这么改写。

2、onload 之后获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>

/* 图片地址 加日期为了避免缓存 get请求 */
let img_url = 'images/front.jpg?' + Date.parse(new Date());

// 打印数据
let img = new Image();

// 打印数据
img.src = img_url;

// 加载完成之后执行
img.onload = function () {
// 打印数据
console.log('width:' + img.width + ', height:' + img.height);
};

</script>

结果

这个结果获取到了图片的宽高,因为onload是等图片相关的数据加载完之后才会执行,所以此时可以获取图片的宽高。
但是图片比较大的时候,等待图片数据完全加载之后再获取宽高,很浪费时间。
因此,可以考虑考虑使用缓存,只要浏览器缓存,那么图片几乎不用等待加载即可可以图片宽高。

3、通过complete和onload一起混合使用

为了测试缓存效果,以下的url都不加时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>

// 测试缓存不加时间戳
let img_url = 'images/front.jpg';

// 创建对象
let img = new Image();

// 改变图片的src
img.src = img_url;

// 判断是否有缓存
if (img.complete) {
// 打印数据
console.log('from : complete - width:' + img.width + ', height:' + img.height);
} else {
// 加载完执行
img.onload = function () {
// 打印数据
console.log('from : onload - width:' + img.width + ', height:' + img.height);
}
}

</script>

第一次执行永远都是onload触发

然后,再刷新几次多试缓存触发

从缓存中读取图片的宽高,非常方便,但是我们要解决的是没有缓存而又快速相比onload方式获取方式。
因为,有些图片,虽然没有无安全加载出来但是,已经占据了位置。既然占有位置,那就可以获取到。
所以,第四种方法,循环定时检查图片是否已经占据了位置,若图片的宽或者高有一个大于0就说明图片此时已经占据了位置,此时就可以获取到宽高。

4、循环定时检测获取宽高

为了避免是从缓存中获取,每次请求都加上时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script>

// 避免缓存加上时间戳
let img_url = 'images/front.jpg?' + Date.parse(new Date());

// 创建对象
let img = new Image();

// 改变图片的src
img.src = img_url;

// 循环获取宽高
let set = 0;
function check() {
set = requestAnimationFrame(check);
// 打印数据
console.log('from : check - width:' + img.width + ', height:' + img.height);

}

// 加载完成获取宽高
img.onload = function () {
// 打印数据
console.log('from : onload - width:' + img.width + ', height:' + img.height);

// 取消循环
cancelAnimationFrame(set);
};

check();

</script>

结果

通过测试,我们发现循环检测笔onload快了一些,其实只要在循环函数里面判断只要图片的宽高有一个大于零就表示已经获取到了图片的宽高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<script>

// 记录当前的时间戳
let start_time = new Date().getTime();

// 避免缓存加上时间戳
let img_url = 'images/front.jpg?' + Date.parse(new Date());

// 创建对象
let img = new Image();

// 改变图片的src
img.src = img_url;

// 循环获取宽高
let check = function () {

let diff = new Date().getTime() - start_time;

// 只要宽高有一个大于0就表示服务器已经返回宽高
if (img.width > 0 || img.height > 0) {
// 打印数据
console.log('from : check - width:' + img.width + ', height:' + img.height + " time:" + diff + 'ms');
cancelAnimationFrame(set);
}

};

let set = requestAnimationFrame(check);

// 加载完成获取宽高
img.onload = function () {
let diff = new Date().getTime() - start_time;
// 打印数据
console.log('from : onload - width:' + img.width + ', height:' + img.height + " time:" + diff + 'ms');
};

check();

</script>

结果

很明显可以看出,循环查询,比加载完在获取宽高确实快了一些。