Затухание в фоновом изображении после загрузки (без jquery) при использовании медиа-запросов для замены изображений для разных размеров экрана
Я читал всю ночь и, похоже, не мог прийти к какому-то конкретному ответу на то, что лучший способ сделать это. Эти две вещи, которые, как я знаю, работают, - это
Для замирания изображения при загрузке:
Используйте обертку изображений и тег <img>
следующим образом:
<div class="imageWrapper">
<img src="img.jpg" alt="" onload="imageLoaded(this)">
</div>
и css выглядит как
.imageWrapper {
opacity: 0
}
.loaded {
opacity: 1
}
а затем в файле js что-то вроде
var imageLoaded = (img) => {
var imgWrapper = img.parentNode;
imgWrapper.className += ' loaded';
}
Для загрузки другого изображения на основе размера экрана
@media screen only and (min-device-width: 0) and (max-device-width: 450px) {
.backgroundImage {
background: url('small_background_image.jpg');
}
}
@media screen only and (min-device-width: 451px) and (max-device-width: 1024px) {
.backgroundImage {
background: url('medium_background_image.jpg');
}
}
@media screen only and (min-device-width: 1025px) {
.backgroundImage {
background: url('large_background_image.jpg');
}
}
Моя проблема
Я могу делать обе эти вещи по отдельности (затухание в изображении при загрузке, изменение фонового изображения, когда браузер обнаруживает меньший размер экрана), но я не могу найти решение, которое включает и. Мне нужно иметь возможность указывать другое изображение для разных размеров экрана, а также иметь возможность обнаруживать, когда загружается это изображение и исчезать.
Есть ли хороший способ сделать это?
Мое решение:
В результате я использовал вариант guest271314 для загрузки правильных изображений. Это работает со всей последней версией каждого браузера и очень легко реализуется.
Во-первых, у меня есть встроенный script, расположенный прямо под моим открывающим тегом <body>
, так что, если мой браузер медленно загружает мой js файл, он может в любое время загрузить изображения.
<body>
<script>
function imageLoaded(img) {
if ((" " + img.className + " ").indexOf(" "+'loaded'+" ") > -1 ) {
return true;
} else {
img.className += ' loaded';
}
}
</script>
а затем у меня есть тег <picture>
, например:
<picture class="backgroundContainer">
<source srcset="img-1024.jpg" media="(min-width: 0px) and (max-width:1024px)">
<source srcset="img-1920.jpg" media="(min-width: 1025px) and (max-width: 1920px)">
<source srcset="img-2560.jpg" media="(min-width: 1921px)">
<img class="backgroundImage" onload="imageLoaded(this)" src="img-1920.jpg" alt="">
</picture>
и мой sass выглядит так:
@keyframes fadeIn
0%
opacity: 0
100%
opacity: 1
.backgroundContainer
width: 100%
height: 100%
.backgroundImage
opacity: 0
.loaded
opacity: 1
animation: fadeIn 3s
И это позволяет браузеру (независимо от скорости) ждать, пока изображение с правильным размером будет загружено, а затем затушевывает его поверх 3s
, с надежным возвратом, используя тег <img>
для старых браузеров.
Ответы
Ответ 1
изменить # 2: обновленную скрипту прогресса: https://jsfiddle.net/c5hy0g8r/11
Проблема по-прежнему заключается в том, что при медленных сетевых условиях использование css Свойство content будет по-прежнему загружаться в куски, как обычно делают изображения. обычный метод onload = "imageLoaded (this)" не будет работать на img или изображение, содержимое которого генерируется css-содержимым: url ('img.jpg') свойство.
Вы можете использовать элемент <picture>
, имеющий один или несколько элементов <source>
с атрибутом srcset
, установленным для источника изображения, который должен отображаться в <img>
, когда соответствующий media
, установленный в действительный список медиа-запросов, соответствует среде.
В onload
событии элемента <img>
установите родительский элемент opacity
в 0
; используйте requestAnimationFrame()
для анимации opacity
элемента от 0
до 1
.
<!DOCTYPE html>
<html>
<head>
<style>
.imageWrapper {
opacity: 0;
}
</style>
</head>
<body>
<picture class="imageWrapper">
<source srcset="http://lorempixel.com/50/50/technics" media="(min-width: 0px) and (max-width:150px)">
<source srcset="http://lorempixel.com/50/50/city" media="(min-width: 151px) and (max-width: 300px)">
<source srcset="http://lorempixel.com/50/50/nature" media="(min-width: 301px) and (max-width:450px)">
<source srcset="http://lorempixel.com/50/50/sports" media="(min-width: 451px) and (max-width:600px)">
<source srcset="http://lorempixel.com/50/50/animals" media="(min-width: 601px)">
<img width="50px" height="50px" onload="imageLoaded(this)" src="null" alt="">
</picture>
<figcaption></figcaption>
<script>
const num = 1/60;
var fx = null;
var caption = document.querySelector("figcaption");
var imageLoaded = (img) => {
caption.innerHTML = "";
cancelAnimationFrame(fx);
var n = 0;
var imgWrapper = img.parentNode;
imgWrapper.style.opacity = 0;
fx = requestAnimationFrame(function animate() {
console.log(n);
if (n < 1) {
n += num;
imgWrapper.style.opacity = n;
fx = requestAnimationFrame(animate);
} else {
caption.innerHTML = img.currentSrc.slice(img.currentSrc.lastIndexOf("/") + 1);
console.log("complete");
}
})
}
</script>
</body>
</html>
plnkr http://plnkr.co/edit/RWSc6J3kUUJPUZsrpagi?p=preview
Ответ 2
В основном я должен уметь исчезать в background-image
, когда он загружает или может изменить тег <img>
src, прежде чем он загрузит в зависимости от размера экрана, или сделать что-то, что включает в себя как эти вещи, используя метод, о котором я не знаю.
Вы можете использовать свойство css
content
со значением, установленным в функцию url()
, имеющей URL-адрес изображения для отображения или изменить отображаемый источник изображения; css
animation
, @keyframes
исчезает в background-image
при загрузке исходного изображения.
HTML
<picture class="backgroundImage"></picture>
CSS
.backgroundImage {
opacity: 0; /* set `opacity` to `0` */
width: 50px;
width: 50px;
content: url(http://lorempixel.com/50/50/technics); /* set intial image */
animation-name: fadein;
animation-iteration-count: 1;
animation-duration: 2500ms;
animation-fill-mode: both;
}
@keyframes fadein {
to {
opacity: 1; /* fade in image */
}
}
/* set media queries */
@media screen only and (min-device-width: 0) and (max-device-width: 450px) {
.backgroundImage {
opacity: 0; /* set `opacity` to `0` */
content: url(http://lorempixel.com/50/50/cats); /* set image */
animation-name: first;
}
@keyframes first {
to {
opacity: 1; /* fade in image */
}
}
}
@media screen only and (min-device-width: 451px) and (max-device-width: 1024px) {
.backgroundImage {
opacity: 0; /* set `opacity` to `0` */
content: url(http://lorempixel.com/50/50/city); /* set image */
animation-name: second;
}
@keyframes second {
to {
opacity: 1; /* fade in image */
}
}
}
@media screen only and (min-device-width: 1025px) {
.backgroundImage {
opacity: 0; /* set `opacity` to `0` */
content: url(http://lorempixel.com/50/50/sports); /* set image */
animation-name: third;
}
@keyframes third {
to {
opacity: 1; /* fade in image */
}
}
}
jsfiddle https://jsfiddle.net/yayd5Lma/3
Ответ 3
Вы должны использовать анимацию css3 для этой цели.
@-webkit-keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
@keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
.fadeIn {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
Ответ 4
Я бы просто загрузил все изображения в свою разметку и назначил классы для медиа-запросов:
<div class="imageWrapper">
<img class="small" src="img_small.jpg" onload="imageLoaded(this)">
<img class="med" src="img_med.jpg" onload="imageLoaded(this)">
<img class="large" src="img_large.jpg" onload="imageLoaded(this)">
</div>
Затем используйте ваши медиа-запросы, чтобы скрыть их по мере необходимости:
@media screen only and (min-device-width: 0) and (max-device-width: 450px) {
.imageWrapper .large, .imageWrapper .medium { display: none; }
}
@media screen only and (min-device-width: 451px) and (max-device-width: 1024px) {
.imageWrapper .large, .imageWrapper .small { display: none; }
}
@media screen only and (min-device-width: 1025px) {
.imageWrapper .small, .imageWrapper .medium { display: none; }
}