我的目标是如果用户进一步滚动到视频元素,则将位置更改为视频元素。我使用的是Intersection Observer API,因为我需要处理AdForm Banner / iFrame中的页面滚动。
这是我的代码:
function createObserver() {
var observer;
var options = {
root: null,
rootMargin: "0px",
threshold: buildThresholdList()
};
observer = new IntersectionObserver(handleIntersect, options);
observer.observe(boxElement);
}
Run Code Online (Sandbox Code Playgroud)
这是handleIntersect函数:
function handleIntersect(entries, observer) {
entries.forEach(function(entry) {
if (entry.intersectionRatio > prevRatio) {
console.log("VIDEO IN");
p.style.position = "relative";
} else if(entry.intersectionRatio === 0 && scrolled === 1 ) {
console.log("VIDEO OUT");
p.style.position = "fixed";
}
});
}
Run Code Online (Sandbox Code Playgroud)
这是我的代码笔:https ://codepen.io/alex18min/pen/gXXYJb
它可以在Chrome / Firefox / Edge和Android设备上完美运行,但通常不能在iOS和Safari上运行,似乎未检测到监听器。
有人能帮我吗?先感谢您。
在单页应用程序中,通常会删除和替换元素。在从DOM中删除的元素上,可能有一个IntersectionObserver(或任何其他种类)
对于事件,我从不打扰,因为它们是绑定在目标上并触发的,因此保留它们应该相当无害。对于IntersectionObserver,我有点担心在任何视图更改时都会检查所有实例。
考虑一下我的Lazy.ts的以下部分
setIntersectionObserver(config:LazyConfig)
{
let intersectionObserver = new IntersectionObserver((entries:Array<IntersectionObserverEntry>) => {
for (let entry of entries) {
if (entry.isIntersecting) {
this.lazyLoad(config);
intersectionObserver.disconnect();
mutationOberserver.disconnect();
}
}
}, {
threshold: 0,
rootMargin: `${config.offset}px`,
});
intersectionObserver.observe(config.element);
let mutationOberserver = new MutationObserver((entries:Array<MutationRecord>) => {
if (
entries[0].removedNodes &&
document.body.contains(config.element) === false
) {
intersectionObserver.disconnect();
mutationOberserver.disconnect();
}
});
mutationOberserver.observe(document.body, {
childList: true,
subtree: true
});
}
Run Code Online (Sandbox Code Playgroud)
底部(mutationOberserver)是否无效?由于进行了许多检查,甚至可能损害性能document.body。
通常,我只是假定垃圾收集会很好地完成其工作,但是脚本保留了对所有Attached元素的引用数组。而且该数组不会被清除(没有观察者也无法清除)
- 编辑 -
它没有得到“删除”(或至少不会在10秒内)https://jsfiddle.net/c1sgdcrd/所以,问题仍然有效羯羊,最好只保留在内存中或积极利用MutationObserver和断开。
javascript performance dom mutation-observers intersection-observer
如何使用:https://github.com/w3c/IntersectionObserver/tree/master/polyfill
我应该将其加载到webpack配置-vue.config.js中还是应该使用导入将其加载到.vue模板中?
我陷入了十字路口观察者问题。使用document.querySelectorAll('.entry')会抛出 TypeError:“未捕获 TypeError:无法在 'IntersectionObserver' 上执行 'observe':参数 1 不是 'Element' 类型。”
改变document.querySelectorAll('.entry');以document.querySelector('.entry');解决问题并且有效。
我究竟做错了什么?
基本的 HTML 结构:
<html>
<body>
<div id="content-container">
<div class="content">
<div class="entry">Some content here on each entry</div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
</div>
</div>
</body
</html>
Run Code Online (Sandbox Code Playgroud)
JavaScript:
const blog = document.querySelectorAll('.entry');
const options = {
root: null,
rootMargin: '0px',
};
const observer = new IntersectionObserver(function(entries, observer) {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
return;
}
else {
console.log(entry); …Run Code Online (Sandbox Code Playgroud) 我想在元素完全居中时修复它的位置。目前,当它完全可见时,它正在被修复,因此会捕捉到中心。- 我可以以某种方式观察元素何时居中吗?
const box = document.querySelector(".box");
const obs = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
box.style.position = "fixed";
box.style.top = "50%";
box.style.transform = "translateY(-50%)"
}
}, {threshold: 1})
obs.observe(box);Run Code Online (Sandbox Code Playgroud)
.v-detail__video {
width: 100vw;
height: 300vh;
display: flex;
padding-top: 70vh;
justify-content: center;
}
.box {
background-color: black;
width: 50vw;
height: 200px;
}Run Code Online (Sandbox Code Playgroud)
<div class="v-detail__video">
<div class="box"></div>
</div>Run Code Online (Sandbox Code Playgroud)
情况
我在页面顶部有一个固定的导航栏。当您向下滚动页面的不同部分时,导航栏会动态更新(下划线和突出显示)。您还可以单击导航栏上的某个部分,它将向下滚动到该部分。
这是使用交集观察器 API 来检测它所在的部分并使用scrollIntoView 滚动到每个部分来完成的。
问题
假设您位于第 1 部分,单击最后一个部分 5,页面就会向下滚动到中间的所有其他部分。滚动速度很快,并且当滚动时,交叉点观察器会检测到所有部分,因此导航会更新。当每个导航项经过每个相应部分时,您最终会得到导航快速变化的效果。
目标
如果该部分仅在帧中持续一毫秒,如何延迟交叉口观察器触发菜单更改?快速滚动时,导航栏仅应在滚动停止在某个部分后更新。
代码设置
const sectionItemOptions = {
threshold: 0.7,
};
const sectionItemObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// select navigation link corresponding to section
} else {
// deselect navigation link corresponding to section
}
});
}, sectionItemOptions);
// start observing all sections on page
sections.forEach((section) => {
sectionItemObserver.observe(section);
});
Run Code Online (Sandbox Code Playgroud)
想法
我的第一个想法是设置一个 setTimeout,以便导航在超时完成之前不会更改,然后如果该部分在超时完成之前离开屏幕,则取消超时。但由于超时是在 forEach 循环中,所以这不起作用。
const sectionItemObserver = new IntersectionObserver((entries, observer) => …Run Code Online (Sandbox Code Playgroud) 我有一段 jQuery 代码,当元素滚动到视口中时,它会向元素添加一个 css 类;当元素滚动出视口时,会删除该类。
到目前为止,代码的工作原理如下:
到目前为止,一切都很好。但我想要实现的是:
滚动到视图中:
滚动到视图之外:
打扫干净:
评论中建议使用Intersection Observer API,在阅读更多相关内容后,我相信它提供了满足要求的最佳方法。
这是我的代码(以整页打开 - 预览效果不佳)。您还可以在 jsFiddle 上找到相同的代码。
function inView(opt) {
if (opt.selector === undefined) {
console.log('Valid selector required for inView');
return false;
}
var elems = [].slice.call(document.querySelectorAll(opt.selector)),
once = opt.once === undefined ? true : opt.once,
offsetTop = opt.offsetTop === undefined ? 0 : opt.offsetTop,
offsetBot = opt.offsetBot === undefined ? 0 : opt.offsetBot,
count = elems.length, …Run Code Online (Sandbox Code Playgroud)是否有针对view 中的内容(即在视口中可见的内容)的 CSS 选择器?
我正在使用 nuxt 创建一个登陆页面,我使用哈希来指示页面上的每个路线,为此我使用scrollBehavior来处理路线上的哈希并滚动到平滑的部分:
router: {
scrollBehavior: async (to, from, savedPosition) => {
console.log(to, from, savedPosition);
if (savedPosition) {
return savedPosition;
}
const findEl = async (hash, x) => {
return (
document.querySelector(hash) ||
new Promise((resolve, reject) => {
if (x > 50) {
return resolve();
}
setTimeout(() => {
resolve(findEl(hash, ++x || 1));
}, 100);
})
);
};
console.log("to.hash", to.hash);
if (to.hash) {
let el = await findEl(to.hash);
console.log("el", el);
if ("scrollBehavior" in document.documentElement.style) {
return window.scrollTo({ top: …Run Code Online (Sandbox Code Playgroud) 我这里有一个运行完美的文本动画。我现在要添加的是一个 Intersection Observer,这样动画只有在我向下滚动到 Box 时才开始。
所以我为实现这一目标所做的是:我使用了 React hookuseRef作为对我想要观察的元素的引用,并将其应用到我的 Box 中ref={containerRef}。然后声明一个回调函数,该函数接收 IntersectionObserverEntries 数组作为参数,在该函数内,我获取第一个也是唯一一个条目,并检查它是否与视口相交,如果是,则使用 Entry.isIntersecting 的值调用 setIsVisible (真假)。之后,我添加了反应钩子 useEffect 并使用回调函数和我之前创建的选项创建了一个观察者构造函数。我在一个新的钩子中实现了这个逻辑,我称之为useElementOnscreen
但是 Typescript 告诉我一个错误containerRef?.current:
Argument of type 'IntersectionObserver' is not assignable to parameter of type 'Element'.
Type 'IntersectionObserver' is missing the following properties from type 'Element': attributes, classList, className, clientHeight, and 160 more.
Run Code Online (Sandbox Code Playgroud)
而且我不知道如何解决这个错误。ref={containerRef}我认为这也是我抛出错误的原因
The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & { component: ElementType<any>; } & …Run Code Online (Sandbox Code Playgroud) javascript ×8
css ×4
html ×3
vue.js ×2
banner ×1
dom ×1
jquery ×1
nuxt.js ×1
performance ×1
reactjs ×1
scroll ×1
settimeout ×1
typescript ×1
vue-router ×1