如何最好地将 ClientRect / DomRect 转换为普通对象
How best to convert a ClientRect / DomRect into a plain Object
someElement.getBoundingClientRect()
returns special 类型 ClientRect
对象的结果(显然是 DomRect
)
它的结构类似于 {top: 10, right: 20, bottom: 30, left: 10, width: 10}
遗憾的是,此对象的行为与其他对象不同。
例如,在 returns 上使用 Object.keys
一个空数组(我认为是因为 ClientRect
属性不是 enumerable
我发现了一些转换为普通对象的肮脏方法:
var obj = {}
for (key in rect) {
obj[key] = rect[key]
}
我的问题是,有没有更好的方法?
我们不要把事情想得太复杂了!
function getBoundingClientRect(element) {
var rect = element.getBoundingClientRect();
return {
top: rect.top,
right: rect.right,
bottom: rect.bottom,
left: rect.left,
width: rect.width,
height: rect.height,
x: rect.x,
y: rect.y
};
}
ES2015:
const getBoundingClientRect = element => {
const {top, right, bottom, left, width, height, x, y} = element.getBoundingClientRect()
return {top, right, bottom, left, width, height, x, y}
}
console.log(
getBoundingClientRect( document.body )
)
如果您使用 jQuery,您可以使用 extend 方法。
var obj = $.extend( {}, element.getBoundingClientRect());
Warning: non-standard behavior (doesn't work in Firefox < 62, including ESR 60 and possibly other browsers other than Chrome)
var obj = el.getBoundingClientRect().toJSON();
这是我可以忍受的东西:
const persistRect = JSON.parse(JSON.stringify(someElement.getBoundingClientRect()))
功能性 ES6 变体:
const propValueSet = (prop) => (value) => (obj) => ({...obj, [prop]: value})
const toObj = keys => obj => keys.reduce((o, k) => propValueSet(k)(obj[k])(o), {})
const getBoundingClientRect = el => toObj(['top', 'right', 'bottom', 'left', 'width', 'height', 'x', 'y'])(el.getBoundingClientRect())
您可以使用 Object.fromEntries()
来创建您的对象。
- Obj 键可以取自
DOMRectReadOnly
的原型
- 目标值可以映射到
Array.from()
的第二个参数(callbak fn)
let domRec = document.getElementById('test').getBoundingClientRect();
// Convert to plain Object
let domObj = Object.fromEntries(Array.from(Object.keys(DOMRectReadOnly.prototype).filter(k => !isNaN(domRec[k])), k => [k, domRec[k]]));
// Convert back to DOMRectReadOnly
let domRec2 = DOMRectReadOnly.fromRect(domObj);
console.log('DOMRectReadOnly', domRec);
console.log('Plain Object', domObj);
console.log('DOMRectReadOnly', domRec2);
#test {
width: 200px;
height: 50px;
background-color: #f00;
}
<div id="test"></div>
然而,这也会将 toJSON
fn 复制到新的 obj。因此我建议过滤非数字值:.filter(k => !isNaN(domRec[k])
.
轻巧
如果您只对x
、y
、width
、height
感兴趣,您可以使用DOMRect
而不是 DOMRectReadOnly
并跳过 .filter()
部分。
You can calc values for bottom
, right
from these 4 values and left
, top
are just aliases for x
, y
.
let domRec = someElement.getBoundingClientRect();
let domObj = Object.fromEntries(Array.from(Object.keys(DOMRect.prototype), k => [k, domRec[k]]));
someElement.getBoundingClientRect()
returns special 类型 ClientRect
对象的结果(显然是 DomRect
)
它的结构类似于 {top: 10, right: 20, bottom: 30, left: 10, width: 10}
遗憾的是,此对象的行为与其他对象不同。
例如,在 returns 上使用 Object.keys
一个空数组(我认为是因为 ClientRect
属性不是 enumerable
我发现了一些转换为普通对象的肮脏方法:
var obj = {}
for (key in rect) {
obj[key] = rect[key]
}
我的问题是,有没有更好的方法?
我们不要把事情想得太复杂了!
function getBoundingClientRect(element) {
var rect = element.getBoundingClientRect();
return {
top: rect.top,
right: rect.right,
bottom: rect.bottom,
left: rect.left,
width: rect.width,
height: rect.height,
x: rect.x,
y: rect.y
};
}
ES2015:
const getBoundingClientRect = element => {
const {top, right, bottom, left, width, height, x, y} = element.getBoundingClientRect()
return {top, right, bottom, left, width, height, x, y}
}
console.log(
getBoundingClientRect( document.body )
)
如果您使用 jQuery,您可以使用 extend 方法。
var obj = $.extend( {}, element.getBoundingClientRect());
Warning: non-standard behavior (doesn't work in Firefox < 62, including ESR 60 and possibly other browsers other than Chrome)
var obj = el.getBoundingClientRect().toJSON();
这是我可以忍受的东西:
const persistRect = JSON.parse(JSON.stringify(someElement.getBoundingClientRect()))
功能性 ES6 变体:
const propValueSet = (prop) => (value) => (obj) => ({...obj, [prop]: value})
const toObj = keys => obj => keys.reduce((o, k) => propValueSet(k)(obj[k])(o), {})
const getBoundingClientRect = el => toObj(['top', 'right', 'bottom', 'left', 'width', 'height', 'x', 'y'])(el.getBoundingClientRect())
您可以使用 Object.fromEntries()
来创建您的对象。
- Obj 键可以取自
DOMRectReadOnly
的原型 - 目标值可以映射到
Array.from()
的第二个参数(callbak fn)
let domRec = document.getElementById('test').getBoundingClientRect();
// Convert to plain Object
let domObj = Object.fromEntries(Array.from(Object.keys(DOMRectReadOnly.prototype).filter(k => !isNaN(domRec[k])), k => [k, domRec[k]]));
// Convert back to DOMRectReadOnly
let domRec2 = DOMRectReadOnly.fromRect(domObj);
console.log('DOMRectReadOnly', domRec);
console.log('Plain Object', domObj);
console.log('DOMRectReadOnly', domRec2);
#test {
width: 200px;
height: 50px;
background-color: #f00;
}
<div id="test"></div>
然而,这也会将 toJSON
fn 复制到新的 obj。因此我建议过滤非数字值:.filter(k => !isNaN(domRec[k])
.
轻巧
如果您只对x
、y
、width
、height
感兴趣,您可以使用DOMRect
而不是 DOMRectReadOnly
并跳过 .filter()
部分。
You can calc values for
bottom
,right
from these 4 values andleft
,top
are just aliases forx
,y
.
let domRec = someElement.getBoundingClientRect();
let domObj = Object.fromEntries(Array.from(Object.keys(DOMRect.prototype), k => [k, domRec[k]]));