Skip to content

[geometry-2] Proposal: Geometry Utility Methods #602

@lukewarlow

Description

@lukewarlow

Proposal: Geometry Utility Methods

Summary

This proposal adds common utility methods to the geometry interfaces such as DOMRectReadOnly and DOMQuadReadOnly.

These methods are widely used across DOM APIs and developer code, but currently require developers to write the logic themselves.

Proposed Additions

Web IDL:

typedef (DOMPointInit or DOMRectInit or DOMQuadInit) GeometryInit;

interface mixin BikeshedBruce {
  boolean contains(GeometryInit other);
  boolean intersects(GeometryInit other);
};

DOMRectReadOnly includes BikeshedBruce;
DOMQuadReadOnly includes BikeshedBruce;

partial interface DOMRectReadOnly {
  DOMRectReadOnly? intersectionRect(DOMRectInit other);
};

partial interface DOMRect {
  static boolean contains(DOMRectInit initial, GeometryInit other);
  static boolean intersects(DOMRectInit initial, GeometryInit other);
  static DOMRectReadOnly? intersectionRect(DOMRectInit initial, DOMRectInit other);
};

partial interface DOMQuad {
  static boolean contains(DOMQuadInit initial, GeometryInit other);
  static boolean intersects(DOMQuadInit initial, GeometryInit other);
};
Original
partial interface DOMRectReadOnly {  
 boolean containsPoint(DOMPointInit point);  
 boolean contains(DOMRectInit other);  
 boolean intersects(DOMRectInit other);  
 DOMRectReadOnly? intersection(DOMRectInit other);
 // ... Other such methods?
};
  • Uses dictionary arguments so raw objects aswell as DOMRect and DOMPoint objects can be used.
  • Instance method mixin aswell as static equivalents so its ergonomic if you have a concrete type as well as for those just using conforming objects.

Motivation

Web developers frequently need to:

  • Determine whether a point lies inside a rectangle (e.g. Does this pointer event lie inside or outside an element's bounding client rect)
  • Calculate the overlap between two rectangles

Currently these sorts of calculations require developers to write this logic themselves.

Most other platforms provide a more complete API out the box (e.g. Android's Rect object)

Current workaround:

const r = el.getBoundingClientRect();  
if (event.clientX >= r.left &&  
  event.clientX <= r.right &&  
  event.clientY >= r.top &&  
  event.clientY <= r.bottom) {
  // inside
}

With proposed API:

if (rect.contains({ x: event.clientX, y: event.clientY })) {  
  // inside  
}

Benefits

  • A more complete platform API surface familiar to newcomers who have used other platforms.
  • Less repeated code.

Prior Art

  • Searching GitHub provides numerous instances of codeblocks that implement these functions.
  • As mentioned other platform's Rect have built-in .intersects(), .contains(), etc.
  • The Set JS type recently had helper methods added to it. (https://github.com/tc39/proposal-set-methods)

Polyfill Example

DOMRectReadOnly.prototype.contains = function ({ x, y, width, height, p1, p2, p3, p4 }) {
  if (is point argument) {
      return x >= this.left && x <= this.right &&  
         y >= this.top  && y <= this.bottom;
  } else if (is rect argument) {
      //...
  } else if (is quad argument) {
     // ...
  }
  
  return false;
};

Would love to know if there's any interest on solving this, I'm sure there's more methods that could be added both to DOMRect but also to the other geometric interfaces.

Questions

  • Should return types be ReadOnly or writable?
  • Should contains allow you to pass (double x, double y) args?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions