我正在努力确定元素在DOM中的当前位置和大小。我把一个片段放在一起,在屏幕的右边展示了一个基于卡片的系统。
我试图构建的行为是,当您单击其中一张卡片时,将添加另一张卡片(最终在下面,但现在在顶部),该卡片将在填充可用空间之前飞到屏幕的左上角。
d3.selectAll("attribute-card").on("click", function (d) {
var rect = this.getBoundingClientRect();
var card = d3.select("body")
.append("div")
.attr("class", "card")
.style("background", "transparent")
.style("border", "thin solid red")
.style("left", rect.left + "px")
.style("top", rect.top + "px")
.style("width", (rect.right - rect.left) + "px")
.style("height", (rect.bottom - rect.top) + "px")
.style("position", "absolute");
});html {
height: 100%;
margin: 0;
font-family: Arial;
overflow: hidden;
}
body {
height: 100%;
}
svg {
background: #2c272b;
width: 100%;
height: 100%;
}
.radial-menu .segment {
fill: #3b3944;
}
.radial-menu .segment:hover {
fill: #535060;
}
.radial-menu .symbol {
pointer-events: none;
fill: white;
}
.radial-menu .symbol.icon {
font-family: 'FontAwesome';
}
.beam {
stroke: #fff;
}
.planet circle {
fill: #399745;
stroke: #3b3944;
stroke-width: 0;
stroke-dasharray: 33,11;
}
.planet .related {
fill: none;
stroke: #3b3944;
stroke-dasharray: none;
stroke-width: 25px;
}
.planet text {
fill: #000;
opacity: 0.4;
text-anchor: middle;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.planet .name {
font-size: 2.5em;
width: 94%;
margin: 125px 0px 0px 10px;
}
.planet.selected text {
fill: white;
opacity: 1;
}
.planet.focused text {
fill: white;
opacity: 1;
}
.moon circle {
fill: #3b3944;
}
.moon:hover {
fill: #535060;
}
.moon text {
fill: white;
text-anchor: middle;
pointer-events: none;
}
.gravity {
stroke: #3b3944;
fill: #3b3944;
stroke-linecap: round;
stroke-width: 2px;
}
.card-list {
background: #2c272b;
position: absolute;
top: 0;
right: 0;
width: 200px;
min-height: 100%;
opacity: 1;
}
.card {
background: #dedede;
border: 2px solid #ebebeb;
margin: 5px 5px 5px 5px;
border-radius: 8px;
padding: 5px 15px 5px 15px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.card .title {
font-weight: bold;
}
.card .summary {
color: #cc8b11;
font-weight: bold;
font-size: 12px;
}
.card .summary .summary-item {
margin: 0;
}
/*# sourceMappingURL=style.css.map */<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<html><head>
<meta charset="utf-8">
<meta name="msapplication-tap-highlight" content="no">
<title name="Business Landscape Explorer Prototype"></title>
<link href="bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="styles/style.css">
<script src="d3.v3.js" charset="utf-8"></script><style type="text/css"></style>
</head>
<body>
<div id="card-list" class="card-list">
<div id="attributes" class="attribute-list" data-bind="foreach: attributes">
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Name</p> <div class="summary" data-bind="foreach: summaries"></div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Cost</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">Average: £9 million</p> <p class="summary-item" data-bind="text: $data">Total: £2,700 million</p> </div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Start Date</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">Earliest: 31st Jan 2007</p> <p class="summary-item" data-bind="text: $data">Latest: 27th Nov 2019</p> </div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Enabled</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">True: 71%</p> <p class="summary-item" data-bind="text: $data">False: 29%</p> </div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Status</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">Red: 11%</p> <p class="summary-item" data-bind="text: $data">Amber: 36%</p> <p class="summary-item" data-bind="text: $data">Green: 41%</p> </div> </div></attribute-card>
</div>
</div>
</body></html>
我所做的是相当基本的,抓取点击的元素,测量它的边界矩形,并添加一个大小和位置相同的新元素到body中:
d3.selectAll("attribute-card").on("click", function (d) {
var rect = this.getBoundingClientRect();
var card = d3.select("body")
.append("div")
.attr("class", "card")
.style("background", "transparent")
.style("border", "thin solid red")
.style("left", rect.left + "px")
.style("top", rect.top + "px")
.style("width", (rect.right - rect.left) + "px")
.style("height", (rect.bottom - rect.top) + "px")
.style("position", "absolute");
});我一直在读关于getBoundingClientRect()的文章,根据规范,它似乎做了我想要做的事情,只是在宽度/高度都关闭的情况下,它并没有达到我期望的效果,而火狐甚至不能正确地使用左键。这个函数是简单地被破坏了(这会让我很惊讶),还是我的一些CSS以某种方式破坏了这个本机函数?
我要补充的是,这里是在不同浏览器中关闭结果的屏幕截图。到目前为止,IE是最接近的,但似乎仍然在与底部/右侧的值作斗争。

发布于 2015-03-11 00:24:01
嗯,我非常困惑,但还是设法让它按我想要的那样工作。我更改了计算,以考虑到填充,边距和边框的基础上的一些猜测工作,并修改了一些样式,以验证它仍然有效。这给了我以下计算:
var rect = element.getBoundingClientRect();
rect = {
left: rect.left - margin.left,
right: rect.right - margin.right - padding.left - padding.right,
top: rect.top - margin.top,
bottom: rect.bottom - margin.bottom - padding.top - padding.bottom - border.bottom
};
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
return rect;奇怪的是,当我尝试将它插入到我的应用程序中时,它根本不起作用。去掉一些填充物,最后得到:
rect = {
left: rect.left - margin.left,
right: rect.right - border.right,
top: rect.top - margin.top,
bottom: rect.bottom - border.bottom - border.top
};
rect.height = rect.bottom - rect.top;
rect.width = rect.right - rect.left;
return rect;
function getBoundingRect(element) {
var style = window.getComputedStyle(element);
var margin = {
left: parseInt(style["margin-left"]),
right: parseInt(style["margin-right"]),
top: parseInt(style["margin-top"]),
bottom: parseInt(style["margin-bottom"])
};
var padding = {
left: parseInt(style["padding-left"]),
right: parseInt(style["padding-right"]),
top: parseInt(style["padding-top"]),
bottom: parseInt(style["padding-bottom"])
};
var border = {
left: parseInt(style["border-left"]),
right: parseInt(style["border-right"]),
top: parseInt(style["border-top"]),
bottom: parseInt(style["border-bottom"])
};
var rect = element.getBoundingClientRect();
rect = {
left: rect.left - margin.left,
right: rect.right - margin.right - padding.left - padding.right,
top: rect.top - margin.top,
bottom: rect.bottom - margin.bottom - padding.top - padding.bottom - border.bottom
};
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
return rect;
};
d3.selectAll(".card").on("click", function (d) {
var rect = getBoundingRect(this);
var card = d3.select("body")
.append("div")
.attr("class", "card")
.style("background", "transparent")
.style("border", "thin solid red")
.style("left", rect.left + "px")
.style("top", rect.top + "px")
.style("width", rect.width + "px")
.style("height", rect.height + "px")
.style("position", "absolute");
});html {
height: 100%;
margin: 0;
font-family: Arial;
overflow: hidden;
}
body {
height: 100%;
}
svg {
background: #2c272b;
width: 100%;
height: 100%;
}
.radial-menu .segment {
fill: #3b3944;
}
.radial-menu .segment:hover {
fill: #535060;
}
.radial-menu .symbol {
pointer-events: none;
fill: white;
}
.radial-menu .symbol.icon {
font-family: 'FontAwesome';
}
.beam {
stroke: #fff;
}
.planet circle {
fill: #399745;
stroke: #3b3944;
stroke-width: 0;
stroke-dasharray: 33,11;
}
.planet .related {
fill: none;
stroke: #3b3944;
stroke-dasharray: none;
stroke-width: 25px;
}
.planet text {
fill: #000;
opacity: 0.4;
text-anchor: middle;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.planet .name {
font-size: 2.5em;
width: 94%;
margin: 125px 0px 0px 10px;
}
.planet.selected text {
fill: white;
opacity: 1;
}
.planet.focused text {
fill: white;
opacity: 1;
}
.moon circle {
fill: #3b3944;
}
.moon:hover {
fill: #535060;
}
.moon text {
fill: white;
text-anchor: middle;
pointer-events: none;
}
.gravity {
stroke: #3b3944;
fill: #3b3944;
stroke-linecap: round;
stroke-width: 2px;
}
.card-list {
background: #2c272b;
position: absolute;
top: 0;
right: 0;
width: 200px;
min-height: 100%;
opacity: 1;
}
.card {
background: #dedede;
border: 2px solid #ebebeb;
margin: 5px 5px 5px 5px;
border-radius: 8px;
padding: 5px 15px 5px 15px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.card .title {
font-weight: bold;
}
.card .summary {
color: #cc8b11;
font-weight: bold;
font-size: 12px;
}
.card .summary .summary-item {
margin: 0;
}
/*# sourceMappingURL=style.css.map */<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<html><head>
<meta charset="utf-8">
<meta name="msapplication-tap-highlight" content="no">
<title name="Business Landscape Explorer Prototype"></title>
<link href="bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="styles/style.css">
<script src="d3.v3.js" charset="utf-8"></script><style type="text/css"></style>
</head>
<body>
<div id="card-list" class="card-list">
<div id="attributes" class="attribute-list" data-bind="foreach: attributes">
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Name</p> <div class="summary" data-bind="foreach: summaries"></div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Cost</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">Average: £9 million</p> <p class="summary-item" data-bind="text: $data">Total: £2,700 million</p> </div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Start Date</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">Earliest: 31st Jan 2007</p> <p class="summary-item" data-bind="text: $data">Latest: 27th Nov 2019</p> </div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Enabled</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">True: 71%</p> <p class="summary-item" data-bind="text: $data">False: 29%</p> </div> </div></attribute-card>
<attribute-card params="value: $data"><div class="card attribute-card"> <p class="title" data-bind="text: name">Status</p> <div class="summary" data-bind="foreach: summaries"> <p class="summary-item" data-bind="text: $data">Red: 11%</p> <p class="summary-item" data-bind="text: $data">Amber: 36%</p> <p class="summary-item" data-bind="text: $data">Green: 41%</p> </div> </div></attribute-card>
</div>
</div>
</body></html>
发布于 2020-05-31 01:35:09
我遇到了同样的问题,但在我的例子中,有时矩形都被固定数量的像素相等地偏移。我发现body节点本身可以相对于viewport有一定的偏移量,当您将任何元素附加到body时,您应该调整偏移量。请参阅以下代码:
d3.selectAll("attribute-card").on("click", function (d) {
var bodyRect = document.body.getBoundingClientRect(); // Get potential offset of the page's body node
var rect = this.getBoundingClientRect(); // This gives coordinates relative to the viewport, not relative to the body's origin
var card = d3.select("body")
.append("div")
.attr("class", "card")
.style("background", "transparent")
.style("border", "thin solid red")
.style("left", (rect.left - bodyRect.left) + "px") // Correct for the body's offset
.style("top", (rect.top - bodyRect.top) + "px") // Correct for the body's offset
.style("width", (rect.right - rect.left) + "px")
.style("height", (rect.bottom - rect.top) + "px")
.style("position", "absolute");
});https://stackoverflow.com/questions/28966678
复制相似问题