Javascript 如何检测元素是否在其容器外部?
因此,我创建了以下内容。我有一个很大程度上依赖用户输入的网络应用程序。出于演示的目的,我通过在a4格式的页面上显示一组作者来保持简单。Javascript 如何检测元素是否在其容器外部?,javascript,html,css,vue.js,vuejs2,Javascript,Html,Css,Vue.js,Vuejs2,因此,我创建了以下内容。我有一个很大程度上依赖用户输入的网络应用程序。出于演示的目的,我通过在a4格式的页面上显示一组作者来保持简单。页面和字体大小都使用vw单元使其响应 正如您在codesandbox中看到的,最后几位作者被迫离开页面,因为页面不再适合容器。理想情况下,我希望检测页面上不再适合的内容,并生成第二个相同的a4页面来显示特定内容 目前在我的webapp中,我刚刚添加了overflow:scroll到所有内容所在的页面div,这样它至少看起来有点“ok”。但这不是一个很好的用户体验,
页面
和字体大小
都使用vw
单元使其响应
正如您在codesandbox中看到的,最后几位作者被迫离开页面,因为页面不再适合容器。理想情况下,我希望检测页面上不再适合的内容,并生成第二个相同的a4页面来显示特定内容
目前在我的webapp中,我刚刚添加了overflow:scroll
到所有内容所在的页面div
,这样它至少看起来有点“ok”。但这不是一个很好的用户体验,我想改进它
我不知道从哪里开始,所以如果能在正确的方向上提供帮助,我将不胜感激
提前谢谢
CSS
Javascript
HTML
标题
作者:
{{item.name}
您可以查看
我更改了数据结构(和模板),使其具有一个pages
数组,其中每个页面都有一个authors
数组,而不是一个数组。最初,第一页包含所有作者
数据(){
返回{
页码:[
{
作者:[
{id:1,名字:“Smith”},
...
]
}
]
}
}
标题
作者:
{{item.name}
然后,我创建了一个方法recalcPages
,在安装组件时调用该方法:
方法:{
recalcPages(){
让pageElements=this.$el.querySelectorAll(“.page”);
数组.from(pageElements).some((p,pi)=>{
让authors=p.queryselectoral(“.author”);
if(作者长度){
返回Array.from(authors).some((a,ai)=>{
让页=a.offsetTop+a.offsetHeight>p.offsetHeight;
若有(关闭页){
让currentAuthors=this.pages[pi].authors;
var p1=currentAuthors.slice(0,ai);
var p2=currentAuthors.slice(ai);
this.pages[pi].authors=p1;
this.pages.push({authors:p2});
}
返回下页;
});
}
返回false;
});
}
},
它迭代实际的DOM节点,并使用offsetTop
+offsetHeight
计算作者是否离开页面。一旦某个元素离开页面,它和所有后续元素就会从当前页面的作者中分离出来,并插入第二个页面
更新内容删除所有页面后,您还需要调用this.recalcPages()
,并在第一个页面上设置一个新的authors
数组,以便再次自动拆分,除非您只添加到最后一个页面。您也可以尝试使用updated
hook来自动实现这一点,我还没有尝试过
当然,这是一个相当繁重的操作,因为它渲染组件只是为了通过修改数据再次触发重新渲染。但除非你不知道每个元素的确切高度,否则就没有办法绕过它(至少我不知道)
顺便说一句(虽然您的最终数据可能看起来不同,但只是为了演示的完整性),我还将您的作者:
标题包装在作者:
中,以便仅在第一页显示它。通常,使用vw对响应性不是很好。我建议只查看flexbox和/或页面的可视框架,以便向用户展示页面内容的适合程度。非常感谢您对这个问题的清晰演示和解决方法。今天我将尝试在我的网站上实现这一点。再次感谢您抽出时间:)。嗨,康斯坦丁,刚过一年,我回到这个问题上来,因为我再次需要这个(以稍微不同的形式)。你说了些我想听听你的意见的话。你说:但是除非你不知道每个元素的确切高度,否则就没有办法绕过它(至少我知道没有)。
。如果你知道每个元素的确切高度,答案会有什么变化?如果所有元素的高度都相同,你就不需要一次又一次地重新计算偏移值。您可以只计算一个页面中包含多少元素,然后将作者相应地拆分为多个页面。
#app {
-webkit-font-smoothing: antialiased;
font: 12pt "Tahoma";
}
.book {
margin: 0;
padding: 0;
background-color: #FAFAFA;
font: 3vw "Tahoma";
}
* {
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.page {
/* overflow: scroll; */
display: block;
width: calc(100 / 23 * 21vw);
height: calc(100 / 23 * 29.7vw);
margin: calc(100 / 23 * 1vw) auto;
border: 1px #D3D3D3 solid;
border-radius: 5px;
background: white;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
.subpage {
margin: calc(100 / 23 * 1vw);
width: calc(100 / 23 * 19vw);
height: calc(100 / 23 * 27.7vw);
line-height: 2;
border: 1px solid red;
outline: 0cm #FAFAFA solid;
}
.subpage-content {
height: 100%;
}
export default {
name: "App",
data() {
return {
authors: [
{ id: 1, name: "Smith" },
{ id: 2, name: "Johnson" },
{ id: 3, name: "Williams" },
{ id: 4, name: "Jones" },
{ id: 5, name: "Brown" },
{ id: 6, name: "Davis" },
{ id: 7, name: "Miller" },
{ id: 8, name: "Wilson" },
{ id: 9, name: "Moore" },
{ id: 10, name: "Taylor" },
{ id: 11, name: "Anderson" },
{ id: 12, name: "Thomas" },
{ id: 13, name: "Jackson" },
{ id: 14, name: "White" },
{ id: 15, name: "Harris" },
{ id: 16, name: "Martin" },
{ id: 17, name: "Thomspson" },
{ id: 18, name: "Garcia" },
{ id: 19, name: "Martinez" },
{ id: 20, name: "Robinson" },
{ id: 21, name: "Clark" },
{ id: 22, name: "Rodeiquez" },
{ id: 23, name: "Lewis" },
{ id: 24, name: "Lee" }
]
};
}
};
<template>
<div id="app">
<div class="container-fluid">
<div class="book">
<div class="page">HEADER
<div class="subpage" id="editor-container">Authors:
<!-- <div class="subpage-content">The real content</div> -->
<div v-for="item in authors" :key="item.id">{{ item.name }}</div>
</div>
</div>
</div>
</div>
</div>
</template>