响应式图像_使用响应图像.js实现真正的响应图像

响应式图像

Responsive web design is something you hear a lot about these days. The moment I really started to get into responsive design was a few months ago when I started to realise that 'responsive' is not just about scaling your websites to the size of your visitors screen but much more than that.

响应式网页设计是您最近听到的很多东西。 我真正开始涉足响应式设计的那一刻是几个月前,当时我开始意识到“响应式”不仅仅是将网站扩展到访问者屏幕的大小,还远远不止于此。

Truly responsive web design is about completely adjusting your website to the visitor's device. It does not just include scaling, but just as important is reducing the data you transfer to visitors who are on a slower connection like 3G or even EDGE.

真正响应快速的网页设计是关于完全根据访问者的设备调整您的网站。 它不仅包括扩展,还重要的是减少传输给访问速度较慢的访客(如3G甚至EDGE)的数据。

图像替换 (Image Replacement)

One of the most data consuming elements on a website are the images. To reduce the data they give to our website we can replace them with more suitable images for the device our visitor is using.

网站上最消耗数据的元素之一是图像。 为了减少他们提供给我们网站的数据,我们可以为访问者使用的设备用更合适的图像替换它们。

This is something which is natively done using the HTML5 <picture> element W3C is developing. The element is not supported in any browsers yet and until it is we'll need either a back-end or a javascript solution to get this done.

这是使用W3C正在开发HTML5 <picture>元素完成的。 到目前为止,所有浏览器均不支持该元素,直到实现该元素为止,我们将需要后端或JavaScript解决方案。

插入? (Plugin?)

There are a number of plugins for this already out there. However, when I searched for one I didn't really find one that suited my needs. Most of them required some kind of additional javascript to be imported next to the plugin and the HTML markup they use seemed a bit dirty and unorganized to me. I got the idea that there might be a cleaner solution possible.

已经有许多用于此的插件。 但是,当我搜索一个时,并没有真正找到适合自己需求的。 他们中的大多数人都需要在插件旁边导入某种其他的javascript,他们使用HTML标记对我来说似乎有点脏乱且杂乱无章。 我想到可能会有更清洁的解决方案。

响应图像.js (responsive-images.js)

This is when I came up with the idea for responsive-images.js. Which is a simple and lightweight javascript plugin(1kb) for responsive image replacement. It uses a clean HTML markup and does not require any additional javascript in order to work.

这是我想到响应图像.js的想法。 这是一个简单轻巧的javascript插件(1kb),用于响应图像替换。 它使用干净HTML标记,并且不需要任何其他JavaScript即可正常工作。

用法 (Usage)

<img alt='kitten!' data-src-base='demo/images/' data-src='<480:smallest.jpg                                                                            ,<768:small.jpg,
                                                          <960:medium.jpg, 
                                                          >960:big.jpg' />

<noscript><img alt='kitten!' src='demo/images/medium.jpg' /></noscript>


That's an example of what the HTML looks like. Pretty clean right?

这是HTML外观的一个示例。 很干净吧?

Using the markup above the browser loads demo/images/smallest.jpg if the size of the viewport is below(or equal to) 480 pixels, demo/images/small.jpg if the size of the viewport is above 480 pixels and below 768 pixels, demo/images/medium.jpg if the size of the viewport is above 768 pixels and below 960 pixels and demo/images/big.jpg if the size of the viewport is above 960 pixels.

如果视口的尺寸小于(或等于)480像素,则使用浏览器上方的标记加载demo / images / smallest.jpg;如果视口的尺寸大于480像素且小于768,则demo / images / small.jpg像素,如果视口的大小大于768像素且小于960像素,则为demo / images / medium.jpg;如果视口的大小大于960像素,则为demo / images / big.jpg。

视网膜? (Retina?)

But what if my visitor is using a retina device?

但是,如果我的访客正在使用视网膜设备怎么办?

<img alt='kitten!' data-src-base='demo/images/' data-src='<480:retina/smallest.jpg                                                                      ,<768:small.jpg,
                                                          <960:medium.jpg, 
                                                          >960:big.jpg' 

                                                data-src2x='<480:retina/smallest.jpg                                                                     ,<768:retina/small.jpg,
                                                            <960:retina/medium.jpg, 
                                                            >960:retina/big.jpg'/>


Tadaa! Using the data-src2x attribute it is possible to specify the images the script should use in case the device has a retina display.

多田 使用data-src2x属性,可以指定脚本在设备具有视网膜显示屏的情况下应使用的图像。

Something that bothered me about this markup though, is that all of the image paths are defined twice. I usually would just save my retina images in a seperate subfolder like demo/images/retina. So to make the markup a bit cleaner there is also the option to only change the data-src-base path for retina devices using the data-src-base2x attribute.

不过,令我感到困扰的是,所有图像路径都定义了两次。 我通常只会将视网膜图像保存在一个单独的子文件夹中,例如demo/images/retina 。 因此,为了使标记更整洁,还可以选择使用data-src-base2x属性仅更改视网膜设备的data-src-base路径。

<img alt='kitten!' data-src-base='demo/images/' data-src-base2x='demo/images/retina/' data-src='<480:smallest.jpg,
                       <768:small.jpg,
                       <960:medium.jpg, 
                       >960:big.jpg' />


没有src属性? (No src attribute?)

From what I can see, it looks like an <img> tag that requires JavaScript to generate a source, which I'd be a bit uncomfortable with. -- Tech Blogger

据我所知,它看起来像一个<img>标记,需要JavaScript生成一个源,我对此有些不满意。 - 技术博客

Yeah, I'd be a bit nervous about that as well.

是的,我对此也会有点紧张。

Browsers are too quick for us! In order to provide the fastest loading time possible, browsers preload all of the images that they can identify -- Choosing A Responsive Image Solution, Smashing Magazine

浏览器对我们来说太快了! 为了提供尽可能最快的加载时间,浏览器会预加载他们可以识别的所有图像- 选择《自适应图像解决方案》,《粉碎杂志》

The problem is though, as described by Smashing Magazine, that when you set a src attribute the browser will preload the image before any javascript or even CSS is applied. This would make double loading of images unavoidable.

但问题是,如Smashing Magazine所述,当您设置src属性时,浏览器会在应用任何JavaScript甚至CSS之前预加载图像。 这将不可避免地导致图像的两次加载。

I don't see any workaround here yet (thoughts, anyone?). The good part is that the plugin even works in browsers like IE5 and Opera Mobile and that there are no known unsupported browsers yet, which makes it pretty safe to leave out the src attribute.

我在这里还没有找到任何解决方法(想法,有人吗?)。 好消息是该插件甚至可以在IE5和Opera Mobile之类的浏览器中使用,并且还没有未知的不受支持的浏览器,这使得删除src属性非常安全。

幕后花絮 (Behind the scenes)

How the plugin itself works is pretty easy. It loops through all the images on the page and first checks if the image contains a data-src attribute to determine if the image is supposed to be responsive

插件本身的工作方式非常简单。 它循环浏览页面上的所有图像,并首先检查该图像是否包含data-src属性,以确定该图像是否应该响应

if( !image.hasAttribute('data-src') ){
    continue;
} 


Then it splits the data-src attribute at every comma which gives us something like:

然后,它在每个逗号处分割data-src属性,这使我们得到如下结果:

[<480:smallest.jpg, <768:small.jpg, <960:medium.jpg, >960:big.jpg]


It starts looping through the results and splits every result again at the colon

它开始循环遍历结果,并在冒号处再次拆分每个结果

[<768, smallest.jpg]


Now we determine if we are talking about above 768 or below 768 by simply calling an indexOf

现在,我们通过简单地调用indexOf来确定是在768以上还是在768以下

if( query[0].indexOf('<') )


We split the string again at the angle bracket.

我们再次在尖括号处分割字符串。

query[0].split('<') 


Now, before matching the 768 against our visitors viewport we first have to determine if their is any lower breakpoint available.

现在,在将768与访问者视口匹配之前,我们首先必须确定他们是否有可用的较低断点。

if( queriesList[(j -1)] ) 


In this case there is a lower breakpoint set of 480. Like above, we split the string at its square bracket and colon. Now we check if the viewport is between our two values.

在这种情况下,有一个较低的断点集480。像上面一样,我们将字符串拆分为方括号和冒号。 现在,我们检查视口是否在两个值之间。

viewport <= breakpoint && viewport > previous_breakpoint


If this is the case then we simply change the image source to the source that belongs to the 768 breakpoint

如果是这种情况,那么我们只需将图像源更改为属于768断点的源

image.setAttribute('src', newSource); 


At this point the image source is set to demo/images/small.jpg and our visitor is viewing the right image for his/hers device.

此时,图像源已设置为demo/images/small.jpg ,我们的访客正在为其设备查看正确的图像。

浏览器支持 (Browser support)

As soon as the plugin was functional I started doing some browser tests. I tested on iOS, android and various desktop browsers. Since I really wanted to see was how far I could raise the bar also older browsers were tested including IE5, Opera 10.6, Safari 4, Firefox 3 and Chrome 14. On the phones I tested devices including Android 1.4, iOS 3 and even Opera Mobile.

插件正常运行后,我开始进行一些浏览器测试。 我在iOS,Android和各种桌面浏览器上进行了测试。 因为我真的很想知道我能提高多大的标准,所以还测试了较旧的浏览器,包括IE5,Opera 10.6,Safari 4,Firefox 3和Chrome14。在手机上,我测试了包括Android 1.4,iOS 3甚至Opera Mobile在内的设备。

While doing these tests I ran into a few problems. Two were for IE but one was for our beloved iOS...

在进行这些测试时,我遇到了一些问题。 其中两个用于IE,但一个用于我们钟爱的iOS ...

1.移动视口 (1. Viewports on mobile)

Easy right? Just put document.documentElement.clientWidth in there and you're good. That's what I thought. But it appears to be a bit more complicated than that. Without a proper width=device-width set in your meta tag some mobile devices will return the viewport as being standard size(980px) which would cause the script to return an image suitable for a 980 pixels wide viewport.

容易吧? 只需将document.documentElement.clientWidth放在那里,就可以了。 我也这么想。 但这似乎要复杂得多。 在您的meta标签中未设置适当的width=device-width ,某些移动设备将以标准尺寸(980px)返回视口,这将导致脚本返回适合980像素宽视口的图像。

I haven't been able to find a javascript only solution for this yet and am not sure if there is one. Taking the fact that most responsive websites have width=device-width in their meta tag anyway this is not a huge problem. I would however like to investigate this some more. If you have thoughts about this, let me know!

我还没有找到一个仅适用于javascript的解决方案,并且不确定是否有一个解决方案。 无论如何,考虑到大多数响应式网站的meta标签中都具有width=device-width的事实,这并不是一个大问题。 但是,我想对此进行更多调查。 如果您对此有任何想法,请告诉我!

2. hasAttribute (2. hasAttribute)

To determine if an image has a data-src attribute the scripts makes use of the hasAttribute method. The problem with this however is that IE7 and below do not support this. For them I had to create a workaround.

为了确定图像是否具有data-src属性,脚本使用了hasAttribute方法。 但是,此问题是IE7及以下版本不支持此功能。 对于他们,我不得不创建一个解决方法。

We first check if the hasAttribute method is available

我们首先检查hasAttribute方法是否可用

if( image.hasAttribute )


If it is we use the hasAttribute method

如果是的话,我们使用hasAttribute方法

image.hasAttribute('data-src')


If it is not available we use a workaround

如果不可用,我们使用一种解决方法

typeof image['data-src'] !== undefined


Those are the basics of this all. However, after this I bumped into another problem. I thought: IE7 and below do not support hasAttribute so why not just define the hasAttribute method myself in case it does not exist? A prototype function is out of the question since IE7 and below do not support them either so I created a normal one.

这些就是这一切的基础。 但是,在此之后,我遇到了另一个问题。 我以为:IE7及以下版本不支持hasAttribute所以为什么不自己定义hasAttribute方法呢? 由于IE7及以下版本也不支持原型功能,因此我创建了一个普通的原型功能。

if( !images[0].hasAttribute ){

    function hasAttr(el, attrName){
        return typeof el[attrName] !== undefined ? 1 : 0;
    }

} else {

    function hasAttr(el, attrName){
        return el.hasAttribute(attrName) ? 1 : 0;
    }

}


Do you already see my mistake here? Declared functions are loaded before any of the other code is executed which makes our if statement invalid and results in a Object does not support property or method hasAttribute error. Let's try that again

您在这里已经看到我的错误了吗? 在执行任何其他代码之前,已装入声明的函数,这会使我们的if语句无效,并导致Object does not support property or method hasAttribute错误。 让我们再试一次

if( !images[0].hasAttribute ){

    hasAttr = function(el, attrName){
        return typeof el[attrName] !== undefined ? 1 : 0;
    };

} else {

    hasAttr = function(el, attrName){
        return el.hasAttribute(attrName) ? 1 : 0;
    };

}


Now if we use function expressions, the code will only load when the interpreter reaches that line. Which makes our if statement work.

现在,如果我们使用函数表达式,则仅在解释器到达该行时才加载代码。 这使我们的if语句起作用。

3. addEventListener (3. addEventListener)

Next up is the addEventListener method which is not available available in IE8 and below. They instead use the attachEvent method. Just like for the hasAttribute method I also used a simple workaround here by first checking if the addEventListener method exists.

接下来是addEventListener方法,在IE8及以下版本中不可用。 他们改为使用attachEvent方法。 就像hasAttribute方法一样,我在这里也使用了一种简单的解决方法,首先检查addEventListener方法是否存在。

if( window.addEventListener ){


If so, use it!

如果是这样,请使用它!

window.addEventListener('load', makeImagesResponsive, false);
window.addEventListener('resize', makeImagesResponsive, false);


if not, use the attachEvent method

如果没有,请使用attachEvent方法

window.attachEvent('onload', makeImagesResponsive);
window.attachEvent('onresize', makeImagesResponsive);


你呢? (What about you?)

Make sure to check out the Github page. I'd feel honored if you'd like to fork and contribute and would let me know what you think. I'd love to hear your feedback! ;)

确保检查出Github页面 。 如果您愿意分担并做出贡献,我将感到很荣幸,并让我知道您的想法。 我希望听到您的反馈! ;)

激动吗 (Excited?)

Grab all the devices you can find and check out the demo below for some responsive kittens. :)

拿起您可以找到的所有设备,并查看下面的演示,了解一些响应灵敏的小猫。 :)

翻译自: https://davidwalsh.name/responsive-design

响应式图像

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值