Skip to content

IroComponentWrapper performance improvement #266

@dcog989

Description

@dcog989

Hi. I'll leave this as an issue as I don't time to backtrack and apply to the tsx code and raise PR.

"The function element.getBoundingClientRect() calculates the size and position of an element relative to the viewport. Calling it repeatedly, especially within event handlers like mousemove or touchmove (which can fire many times per second during a drag), is a performance concern. Each call can potentially trigger a "reflow" or "layout" in the browser, where the browser has to recalculate the positions and geometries of elements on the page. This is computationally expensive and can lead to janky or unresponsive UI."

IroComponentWrapper.prototype.handleEvent = function handleEvent (e) {
    var this$1 = this;
    var inputHandler = this.props.onInput;
    var point = e.touches ? e.changedTouches[0] : e;
    var x, y;

    // Prevent default browser action for events where we are handling interaction
    // (touchstart, touchmove, mousedown, mousemove).
    // mouseup and touchend don't typically need preventDefault unless they cause unwanted clicks.
    if (e.type === "touchstart" || e.type === "touchmove" || e.type === "mousedown" || e.type === "mousemove") {
        e.preventDefault();
    }

    switch (e.type) {
        case "mousedown": /* MouseDown */
        case "touchstart": /* TouchStart */
            // Cache the bounds at the start of an interaction
            this._interactionBounds = this.base.getBoundingClientRect(); // <<<<< CACHE HERE
            x = point.clientX - this._interactionBounds.left;
            y = point.clientY - this._interactionBounds.top;

            var result = inputHandler(x, y, 0 /* Start */);
            if (result !== false) {
                SECONDARY_EVENTS.forEach(function (event) {
                    document.addEventListener(event, this$1, { passive: false });
                });
            }
            break;
        case "mousemove": /* MouseMove */
        case "touchmove": /* TouchMove */
            // Use cached bounds if they exist (they should after mousedown/touchstart)
            if (!this._interactionBounds) { break; } // Safety break
            x = point.clientX - this._interactionBounds.left; // <<<<< USE CACHED BOUNDS
            y = point.clientY - this._interactionBounds.top;  // <<<<< USE CACHED BOUNDS
            inputHandler(x, y, 1 /* Move */);
            break;
        case "mouseup": /* MouseUp */
        case "touchend": /* TouchEnd */
            // Use cached bounds for the final position
            if (!this._interactionBounds) { break; } // Safety break
            x = point.clientX - this._interactionBounds.left; // <<<<< USE CACHED BOUNDS
            y = point.clientY - this._interactionBounds.top;  // <<<<< USE CACHED BOUNDS
            inputHandler(x, y, 2 /* End */);

            // Clear the cached bounds now that the interaction has ended
            this._interactionBounds = null; // <<<<< CLEAR CACHE

            SECONDARY_EVENTS.forEach(function (event) {
                document.removeEventListener(event, this$1, { passive: false });
            });
            break;
    }
};

I've briefly tested the amended code and it seems to work OK and improve smoothness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions