在鼠标悬停时循环 AJAX 请求的图像,在鼠标离开时停止循环
Looping over AJAX requested images on mouseover, stopping the loop on mouseleave
我有一个模型网格,每个模型都包含 link、图像和名称。在 mouseenter 上,我希望每秒用循环中的 AJAX 加载图像列表替换悬停图像的 src 属性。在 mouseleave 上,原始图像应该恢复并且循环应该停止。
<div class="c-grid c-grid--models">
<a href="#link-to-model" class="c-model" data-id="1">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 1</figcaption>
</figure>
</a>
<a href="#link-to-model" class="c-model" data-id="2">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 2</figcaption>
</figure>
</a>
</div>
图像出现在视口中时会延迟加载。它们存储在数据原始标签中。下面是我开始工作的脚本。
var _brakes = 1;
var _timer1 = null;
var _timer2 = null;
var _data = null;
$('.c-grid--models .c-model').hover(
function() {
_brakes = 0;
_id = $(this).attr('data-id');
$image = $('img',$(this));
var $this = $(this);
_timer1 = setTimeout(function (){
$this.request('onHover', {
data : {
id : _id
},
success: function(data) {
_data = $.parseJSON(data.result);
$.each(_data, function(i, new_image) {
_timer2 = setTimeout(function (){
if(_brakes == 0) {
$image.attr('src', new_image);
} else {
clearTimeout(_timer1);
clearTimeout(_timer2);
_data = null;
_timer1 = null;
_timer2 = null;
}
}, i * 1000);
});
}
});
}, 1000);
}, function() {
_brakes = 1;
$image = $('img',$(this));
$image.attr('src',$image.attr('data-original'));
clearTimeout(_timer1);
clearTimeout(_timer2);
_data = null;
_timer1 = null;
_timer2 = null;
}
);
问题:
- 当到达最后一张图像时循环停止。我想一直循环直到触发 mouseleave 事件
- 在鼠标离开和鼠标(重新)进入时,图像旋转速度加快并且行为不稳定。似乎第一个循环没有正确停止。
- 来回悬停时,一个模型的图像与另一个模型的图像交叉。
注意:$(this).request('onHover'...
是 October CMS Ajax 框架的一部分。它执行一个 PHP 函数,该函数 returns 当前悬停的模型的所有图像的 JSON 数组。
谁能帮忙解决这个问题?可能是我使用的逻辑不对。任何投入将不胜感激。谢谢!
相关:
Stopping infinite loop on mouseleave or mouseout
好朋友帮我解决了问题
我们采用了不同的方法,将图像总数和当前图像存储在每个 html 元素的数据属性中。
我们现在不返回整个图像数组,而是逐个旋转图像。
新 HTML:
<div class="c-grid c-grid--models">
<a href="#link-to-model" class="c-model" data-id="1" data-image-counter="5" data-current-image="0">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 1</figcaption>
</figure>
</a>
<a href="#link-to-model" class="c-model" data-id="2" data-image-counter="5" data-current-image="0">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 2</figcaption>
</figure>
</a>
</div>
新 JavaScript:
$(function() {
var hoveredItem = null;
// Don't fire on touch devices
if($('.c-grid--models').length && !Modernizr.touchevents) {
$('.c-grid--models .c-model').hover(
function() { // mouseenter
$(this).data("mouse-hover", true);
if(!$(this).data("is-busy") ) {
$(this).data("is-busy", true);
GetNextImage($(this));
}
// get next image with delay
}, function() { // mouseleave
// set original image and stop loop
$(this).data("mouse-hover", false);
var orignalimage = $("img",$(this)).data("original");
$("img", $(this)).attr("src", orignalimage);
}
);
}
function GetNextImage(imageContainer) {
hoveredItem = imageContainer;
if (parseInt(imageContainer.data("image-counter")) <= 1) return;
setTimeout( function() {
if (imageContainer.data("mouse-hover") == true)
{
imageContainer.data("current-image", parseInt(imageContainer.data("current-image")) + 1);
$(this).request("onHover", {
data: {
id: imageContainer.data("id"),
image_id: imageContainer.data("current-image")
}, success: function (data) {
// Reset
var total = parseInt(imageContainer.data("image-counter"))-1;
var current = parseInt(imageContainer.data("current-image"));
if (current >= total) imageContainer.data("current-image", 0);
// async callback finished. no longer busy
if (imageContainer.data("mouse-hover") == true) {
var _data = $.parseJSON(data.result);
$('img',imageContainer).attr('src', _data);
GetNextImage(imageContainer); //Loop
} else {
imageContainer.data("is-busy", false);
}
}
});
} else {
imageContainer.data("is-busy", false);
}
}, 1000);
}
$(window).scroll(function() {
if (hoveredItem != null) {
hoveredItem.data("mouse-hover", false);
}
});
});
需要注意的重要一点是,滚动并不总是触发 onmouseleave。因此,在滚动时我们取消图像旋转,直到用户鼠标再次输入。
希望这对您有用。如果有不清楚的地方,请在下方评论,我会更新答案。
我有一个模型网格,每个模型都包含 link、图像和名称。在 mouseenter 上,我希望每秒用循环中的 AJAX 加载图像列表替换悬停图像的 src 属性。在 mouseleave 上,原始图像应该恢复并且循环应该停止。
<div class="c-grid c-grid--models">
<a href="#link-to-model" class="c-model" data-id="1">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 1</figcaption>
</figure>
</a>
<a href="#link-to-model" class="c-model" data-id="2">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 2</figcaption>
</figure>
</a>
</div>
图像出现在视口中时会延迟加载。它们存储在数据原始标签中。下面是我开始工作的脚本。
var _brakes = 1;
var _timer1 = null;
var _timer2 = null;
var _data = null;
$('.c-grid--models .c-model').hover(
function() {
_brakes = 0;
_id = $(this).attr('data-id');
$image = $('img',$(this));
var $this = $(this);
_timer1 = setTimeout(function (){
$this.request('onHover', {
data : {
id : _id
},
success: function(data) {
_data = $.parseJSON(data.result);
$.each(_data, function(i, new_image) {
_timer2 = setTimeout(function (){
if(_brakes == 0) {
$image.attr('src', new_image);
} else {
clearTimeout(_timer1);
clearTimeout(_timer2);
_data = null;
_timer1 = null;
_timer2 = null;
}
}, i * 1000);
});
}
});
}, 1000);
}, function() {
_brakes = 1;
$image = $('img',$(this));
$image.attr('src',$image.attr('data-original'));
clearTimeout(_timer1);
clearTimeout(_timer2);
_data = null;
_timer1 = null;
_timer2 = null;
}
);
问题:
- 当到达最后一张图像时循环停止。我想一直循环直到触发 mouseleave 事件
- 在鼠标离开和鼠标(重新)进入时,图像旋转速度加快并且行为不稳定。似乎第一个循环没有正确停止。
- 来回悬停时,一个模型的图像与另一个模型的图像交叉。
注意:$(this).request('onHover'...
是 October CMS Ajax 框架的一部分。它执行一个 PHP 函数,该函数 returns 当前悬停的模型的所有图像的 JSON 数组。
谁能帮忙解决这个问题?可能是我使用的逻辑不对。任何投入将不胜感激。谢谢!
相关:
Stopping infinite loop on mouseleave or mouseout
好朋友帮我解决了问题
我们采用了不同的方法,将图像总数和当前图像存储在每个 html 元素的数据属性中。
我们现在不返回整个图像数组,而是逐个旋转图像。
新 HTML:
<div class="c-grid c-grid--models">
<a href="#link-to-model" class="c-model" data-id="1" data-image-counter="5" data-current-image="0">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 1</figcaption>
</figure>
</a>
<a href="#link-to-model" class="c-model" data-id="2" data-image-counter="5" data-current-image="0">
<figure class="c-model__wrap">
<img src="http://placeholder.image" data-original="http://lazyloaded.image" class="c-model__image" />
<figcaption class="c-model__name">Model 2</figcaption>
</figure>
</a>
</div>
新 JavaScript:
$(function() {
var hoveredItem = null;
// Don't fire on touch devices
if($('.c-grid--models').length && !Modernizr.touchevents) {
$('.c-grid--models .c-model').hover(
function() { // mouseenter
$(this).data("mouse-hover", true);
if(!$(this).data("is-busy") ) {
$(this).data("is-busy", true);
GetNextImage($(this));
}
// get next image with delay
}, function() { // mouseleave
// set original image and stop loop
$(this).data("mouse-hover", false);
var orignalimage = $("img",$(this)).data("original");
$("img", $(this)).attr("src", orignalimage);
}
);
}
function GetNextImage(imageContainer) {
hoveredItem = imageContainer;
if (parseInt(imageContainer.data("image-counter")) <= 1) return;
setTimeout( function() {
if (imageContainer.data("mouse-hover") == true)
{
imageContainer.data("current-image", parseInt(imageContainer.data("current-image")) + 1);
$(this).request("onHover", {
data: {
id: imageContainer.data("id"),
image_id: imageContainer.data("current-image")
}, success: function (data) {
// Reset
var total = parseInt(imageContainer.data("image-counter"))-1;
var current = parseInt(imageContainer.data("current-image"));
if (current >= total) imageContainer.data("current-image", 0);
// async callback finished. no longer busy
if (imageContainer.data("mouse-hover") == true) {
var _data = $.parseJSON(data.result);
$('img',imageContainer).attr('src', _data);
GetNextImage(imageContainer); //Loop
} else {
imageContainer.data("is-busy", false);
}
}
});
} else {
imageContainer.data("is-busy", false);
}
}, 1000);
}
$(window).scroll(function() {
if (hoveredItem != null) {
hoveredItem.data("mouse-hover", false);
}
});
});
需要注意的重要一点是,滚动并不总是触发 onmouseleave。因此,在滚动时我们取消图像旋转,直到用户鼠标再次输入。
希望这对您有用。如果有不清楚的地方,请在下方评论,我会更新答案。