How best to convert a ClientRect / DomRect into a plain Object

13,274

Solution 1

Let's not overcomplicate things!

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 )
)

Solution 2

This is something that I can live with:

const persistRect = JSON.parse(JSON.stringify(someElement.getBoundingClientRect()))

Solution 3

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();

Solution 4

You could use the extend method if you are using jQuery.

var obj = $.extend( {}, element.getBoundingClientRect());

Solution 5

Functional ES6 variant:

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())
Share:
13,274

Related videos on Youtube

Zach Lysobey
Author by

Zach Lysobey

Updated on October 04, 2022

Comments

  • Zach Lysobey
    Zach Lysobey over 1 year

    The result of someElement.getBoundingClientRect() returns a special object of type ClientRect (or DomRect apparently)

    It is structured like {top: 10, right: 20, bottom: 30, left: 10, width: 10}

    Unfortunately, this object does not behave quite like other objects.

    For example, using Object.keys on it returns an empty array (I think because ClientRect properties are not enumerable

    I found something of a dirty way to convert to a plain object:

    var obj = {}
    for (key in rect) {
      obj[key] = rect[key]
    }
    

    My question is, is there a better way?

    • Joseph Marikle
      Joseph Marikle over 7 years
      This is soooo hacky, but Object.keys(document.body.getBoundingClientRect().__proto__) seems to work in chrome. :P
    • Gust van de Wal
      Gust van de Wal about 2 years
      Make that Object.keys(Object.getPrototypeOf(document.body.getBoundingC‌​lientRect())) and it isn't as hacky anymore
  • kamelkev
    kamelkev about 7 years
    This can and does work, but $.extend is notoriously inefficient compared to various other cloning methods. See jsben.ch/#/bWfk9. As OP notes ClientRect is a special object though, and most (all?) other techniques do not work as expected, so not a lot of choices here.
  • aboutaaron
    aboutaaron almost 7 years
    Here's an ES6 version: const getBoundingClientRect = (element) => { const {top, right, bottom, left, width, height, x, y} = element.getBoundingClientRect(); return {top, right, bottom, left, width, height, x, y} }
  • Zach Lysobey
    Zach Lysobey about 6 years
    I think you don't even need the Object.assign there. .toJSON retuns a proper object (Object.keys($0.getBoundingClientRect().toJSON()) works). You get a fresh object every time too! $0.getBoundingClientRect().toJSON() !== $0.getBoundingClientRect().toJSON()
  • mkg
    mkg about 6 years
    keep in mind, toJSON is not working for rect objects at firefox folks
  • Yami Odymel
    Yami Odymel almost 6 years
    Sorry, but I have to downvote the answer since you didn't mention it doesn't support with Firefox
  • Fredrik_Borgstrom
    Fredrik_Borgstrom over 4 years
    Doesn't work in Edge. But when Edge switches to Chromium, that will be resolved.
  • Michael Johansen
    Michael Johansen over 2 years
    As a general rule, one should avoid converting numbers to strings (and back) unless necessary. String operations are a lot more expensive that working with numbers, so if you have to do this operation many times performance will suffer.
  • Skyrocker
    Skyrocker over 2 years
    @MichaelJohansen, completely agree, good remark