npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mlbrgn/image-editor

v1.0.126

Published

An image editor web component / custom element

Readme

Image Editor

The ImageEditor is a custom web component, built with JavaScript, that allows users to perform various edits on images, such as cropping, resizing, rotating, and applying filters.

Development

This package is developed inside the mlbrgn-node-workspace monorepo. Do not run npm run dev or npm install inside this repository.

Clone the monorepo instead: https://github.com/evertjanmlbrgn/mlbrgn-node-workspace


Installation and Import

To use the ImageEditor, import it as a "side effect import":

import "path/to/ImageEditor.js"

This class extends ImageEditorCustomElement and does not export anything directly, but registers the custom element.


local / dev test page

to visit the local dev / test page run:

npm run dev

and click the link shown at "Local", e.g. http://localhost:xxxx/ the x's should be replaced with the port number.

Key Features

The ImageEditor provides the following functionalities:

  • Image Loading and Display: Loads images from various sources and displays them within the editor.
  • Cropping/Selection: Allows users to select a specific area of the image for cropping, with support for aspect ratio locking and snapping.
  • Resizing: Enables resizing of images to specific dimensions.
  • Rotation: Supports image rotation.
  • Flipping and Flopping: Provides options to horizontally or vertically flip the image.
  • Image Filtering: Applies various filters to the image.
  • Dynamic UI Updates: Reacts to user interactions and updates the UI in real-time.
  • File Size and Format Information: Displays current and target image file sizes and allows conversion to different formats.
  • Responsive Design: Adjusts handle sizes for touch devices.

Core Concepts

Custom Element

The ImageEditor is a web component, meaning it's a reusable HTML element (<image-editor>) that encapsulates its functionality and styling. It extends ImageEditorCustomElement, providing a base for its custom element behavior.

Shadow DOM

The editor uses Shadow DOM (static shadowTemplate = mainTemplate) to encapsulate its internal structure and styles, preventing them from interfering with the rest of the document.

Canvases

The editor utilizes two main HTML canvases:

  • canvasImage: Used for drawing and manipulating the actual image.
  • canvasDraw: Used for drawing selection boxes, handles, grid lines, and other interactive elements on top of the image.

Image Dimensions and Scaling

The editor carefully manages various dimensions and scaling factors to ensure accurate drawing and display across different resolutions and zoom levels:

  • editorWidth, editorHeight: Dimensions of the container holding the canvases.
  • imageNaturalWidth, imageNaturalHeight: Original dimensions of the loaded image.
  • canvasImageWidth, canvasImageHeight: Calculated dimensions for canvasImage to fit within boundaries, considering rotation.
  • canvasDrawWidth, canvasDrawHeight: Dimensions for canvasDraw, scaled for sharp drawing on potentially low-resolution images.
  • canvasesCSSScaleRatio: Ratio by which the canvasesWrapper needs to be scaled for CSS display.
  • canvasDrawRatio: Scaling factor between canvasImage and canvasDraw for drawing elements correctly.
  • zoomRatio: User-controlled zoom level.

Selection and Handles

The image editor provides robust selection functionality:

  • selectionArea: Represents the currently selected area of the image in original image coordinates.
  • selectionAreaScaled: The selected area scaled to the canvasDraw dimensions for accurate drawing of the selection box and handles.
  • selectionHandleAreas: A collection of Area objects representing the interactive handles (corners and edges) for resizing the selection. Each handle has a type (corner/edge), mode (grab/resize), and action (e.g., 'nw-resize').
  • selectionMode: Determines the current interaction mode (e.g., 'select', 'resize', 'grab').
  • selectionAction: Specifies the active resizing or grabbing action (e.g., 'nw-resize', 'grab').
  • selectionAnimationController: Manages the animation of the selection box dashed lines.

Event Handling

The ImageEditor uses an EventBus for communication and handling various events, such as status messages (onCanvasStatusMessage). It also utilizes ResizeObserver to react to changes in the editor's container size.


Public Methods

  • constructor(): Initializes the custom element, creates canvases, disables controls, sets up filters, determines file format support, and adds event listeners.
  • getImageFileConfiguration(): Returns an object defining image file constraints (e.g., formatsRegex, minWidth, maxWidth, maxUploadFileSize).
  • connectedCallback(): Lifecycle method called when the custom element is added to the DOM.
  • disconnectedCallback(): Lifecycle method called when the custom element is removed from the DOM.
  • enableControls(enable): Enables or disables the editor's control elements (menu and canvas buttons).
  • updateFilter(canvasImageFilter): Applies a CSS filter string to the image canvas and redraws the image.

Private Methods

  • #createCanvases(): Creates and appends the canvasImage and canvasDraw elements to the DOM.
  • #initializeResizeObserver(): Sets up a ResizeObserver to redraw the canvas when the editor's container resizes.
  • #calculateFileSize(mimeType): Calculates the size of the image on the canvas in the specified MIME type.
  • #checkConversionSupport(mimeType): Checks if a given MIME type is supported for image conversion by the browser.
  • #formatBytes(bytes, decimals = 2): Formats a number of bytes into a human-readable string (e.g., "1.2 MB").
  • #getImageAspectRatioLabel(width, height): Calculates and formats the aspect ratio of an image as a fraction, including common aspect ratio labels.
  • #calculateCanvasImageSize(imageWidth, imageHeight, rotationAngle): Calculates the required canvas size to fit a rotated image without cropping.
  • #updateImageDimensions(): Recalculates all relevant image and canvas dimensions based on current state (rotation, original image size, editor size).
  • #calculateCanvasesCssDimensions(): Determines the CSS dimensions for the canvases wrapper to fit within the editor's boundaries.
  • #calculateCssScaleRatio(): Calculates the CSS scale factor needed to fit the image within the editor's display area.
  • #getCorrectedDimension(value): Corrects a dimension value for zooming, CSS scaling, and canvasDrawRatio.
  • #getCorrectedDimension2(value): Corrects a dimension value for zooming and CSS scaling, but not canvasDrawRatio.
  • #dispatchStatusMessage(message): Fires an onCanvasStatusMessage event with the given message.
  • #applyImageDimensions(): Applies the calculated width and height to the canvas elements' attributes and CSS styles.
  • #draw(): Main drawing function, which calls #drawImage() and #drawDrawing().
  • #drawImage(): Draws the current image onto canvasImage, applying rotation, flipping, flopping, and filters.
  • #resizeImage(resizeWidth, resizeHeight): Resizes the current image to the specified dimensions and updates the editor.
  • #updateSelectionHandles(): Calculates and updates the positions and sizes of the selection handles based on the selectionArea.
  • #calculateGridLines(): Calculates the positions of grid and sub-grid lines.
  • #drawDrawing(): Draws the selection box, handles, and grid lines onto canvasDraw.
  • #limitAndSnapSelectedArea(selectedArea): Adjusts the selected area to snap to canvas edges if within a defined threshold.
  • #checkOutOfBounds(area): Checks if a given area is outside the bounds of the image canvas.
  • #updateSelectedArea(selectedArea): Updates the selectionArea and its scaled version, and then updates selection properties.
  • #validateSelectedArea(selectedArea): Checks if the selectedArea meets the minimum and maximum width/height constraints.
  • #drawSelectionBox(): Draws the dashed selection box on canvasDraw.
  • #startSelectionAnimation(): Starts the animation for the selection box dashed lines.
  • animateSelection(): Updates the animationOffset for the selection box animation.
  • #stopSelectionAnimation(): Pauses the selection box animation.
  • #drawGrabCross(): Draws a crosshair in the center of the selection area (not currently used in the provided code).
  • #drawSelectionHandles(): Draws the interactive handles around the selection area.
  • #drawGrid(): Draws the grid and sub-grid lines on canvasDraw.
  • #getPointerRelativeToCanvasStart(clientX, clientY): Converts client-side pointer coordinates to coordinates relative to the canvas origin, considering scaling.
  • #updatePointerStart(clientX, clientY): Updates the starting pointer position for selection/resizing.
  • #updatePointer(clientX, clientY): Updates the current pointer position.
  • #getPointerOverArea(): Determines which selection handle (if any) the pointer is currently over and updates the cursor.
  • #getAspectRatioFromCurrentSelection(): Returns the aspect ratio of the current selection.
  • #getAspectRatioValueFromSelect(): Retrieves the selected aspect ratio value from the aspect ratio dropdown.
  • #drawAnchorPoint(anchorPoint): Draws a small rectangle at a given anchor point (used for debugging/visualization).
  • #applySelectBoxRatioToWidth(area): Adjusts the width of an area to maintain a specific aspect ratio.
  • #applySelectBoxRatioToHeight(area): Adjusts the height of an area to maintain a specific aspect ratio.
  • #determineSelectionMode(): Determines whether the user is in 'select', 'resize', or 'grab' mode based on pointer position.
  • #selectStart(): Initiates a new selection, clearing any previous selection.
  • #selectMove(shiftKey = false): Handles pointer movement during selection, adjusting the selected area and redrawing.
  • #resizeStart(): Prepares for a resizing operation by storing the initial selection and determining the anchor point.

Properties

Static Properties

  • shadowTemplate: Reference to the HTML template for the Shadow DOM.
  • elementLookup: An array of CSS selectors used to find and store references to key DOM elements within the component.
  • translationsPath: The path to the translation files.
  • observedAttributes: An array of attribute names that the component should observe for changes (currently only disabled).

Instance Properties

  • #overRideAspectRatio: Internal property to temporarily override the aspect ratio for selection (e.g., when Shift key is pressed).
  • #fileSizeOriginal: Stores the original file size of the loaded image.
  • canvasFilters: An instance of CanvasFilters for managing image filters.
  • #originalImage: Stores the original Image object.
  • #originalImageFile: Stores the original ImageFile object.
  • #currentImage: Stores the currently displayed Image object.
  • #currentImageId: ID of the current image.
  • #currentImageFile: Stores the ImageFile object for the currently displayed image.
  • #initiallySelected: Stores the selection area at the start of a resize operation.
  • #initiallySelectedHalfway: Stores the midpoint of the selection area at the start of a resize operation.
  • selectionAnimationController: Controls the animation of the selection box.
  • editorWidth, editorHeight: Width and height of the editor element.
  • imageNaturalWidth, imageNaturalHeight: Natural (unscaled) width and height of the current image.
  • canvasImageWidth, canvasImageHeight: Width and height of canvasImage.
  • canvasDrawRatio: Scaling ratio between canvasImage and canvasDraw.
  • canvasDrawWidth, canvasDrawHeight: Width and height of canvasDraw.
  • canvasesCSSScaleRatio: CSS scaling factor for the canvases.
  • canvasesCSSWidth, canvasesCSSHeight: CSS width and height of the canvases.
  • canvasImageXOrigin, canvasImageYOrigin: Center point of canvasImage.
  • canvasImageDrawStart: Starting point for drawing the image on canvasImage.
  • flipXAxisDirection, flipYAxisDirection: Direction multipliers for horizontal and vertical flipping.
  • flipXOrigin, flipYOrigin: Origin points for flipping transformations.
  • imageAspectRatio: Calculated aspect ratio of the current image.
  • imageOrientation: Orientation of the current image (Landscape, Portrait, Square).
  • gridGap: Spacing between major grid lines.
  • lineWidth: Line width for drawing on canvases.
  • selectionLineDashSize: Dash size for the selection box line.
  • crossLineSize: Size of the crosshair lines.
  • handleCornerSize, handleEdgeSize, handleEdgeMargin: Dimensions for selection handles.
  • zoomPercentage: Current zoom level as a percentage.
  • canvasImageFilter: Current CSS filter string applied to the image.
  • showGrid: Boolean indicating whether the grid should be displayed.
  • selectionArea: An Area object representing the current selection.
  • selectionAreaScaled: A scaled version of selectionArea for drawing.
  • selectionHandleAreas: An object containing Area objects for each selection handle.
  • selectionValid: Boolean indicating if the current selection meets size constraints.
  • animationOffset: Offset for the selection box dash animation.
  • gridLines: Array of objects defining grid line start and end points.
  • selectionPointerStart: Point object storing the starting pointer position for an interaction.
  • selectionPointerCurrent: Point object storing the current pointer position.
  • selectionStartPointerOver: Information about which handle the pointer was over when an interaction started.
  • selectionWasTouchEvent: Boolean indicating if the last selection interaction was a touch event.

Configuration (this.config)

The ImageEditor relies on a config object (likely inherited from ImageEditorCustomElement) for various settings, including:

  • animateFPS: Frames per second for selection animation.
  • aspectRatioTolerance: Tolerance for matching aspect ratios.
  • minWidth, maxWidth, minHeight, maxHeight: Minimum and maximum dimensions for image editing.
  • maxUploadFileSize, maxEditFileSize: Maximum file sizes for upload and editing.
  • drawCanvasWidth: Target width for the canvasDraw element.
  • gridLineCount: Number of major grid lines.
  • lineWidth: Default line width for drawing.
  • selectionLineDashSize: Default dash size for selection box.
  • crossLineSize: Default size for crosshair lines.
  • handleCornerSize, handleEdgeSize, handleEdgeMargin: Default sizes for selection handles.
  • touchHandleMultiplierBreakpoint: Breakpoint for adjusting handle sizes on touch devices.
  • touchHandleMultiplier: Multiplier for handle sizes on touch devices.
  • selectionBoxStrokeStyle: CSS stroke style for the selection box.
  • selectionBoxLineDashStrokeStyle: CSS stroke style for the dashed selection box.
  • selectionBoxInvalidLineDashStrokeStyle: CSS stroke style for invalid selection box.
  • crossStrokeStyle: CSS stroke style for the crosshair.
  • selectionHandleStrokeStyle: CSS stroke style for selection handles.
  • selectionHandleOverFillStyle: CSS fill style for hovered selection handles.
  • selectionHandleLineDashStrokeStyle: CSS stroke style for dashed selection handles.
  • gridStrokeStyle: CSS stroke style for major grid lines.
  • showSubGrid: Boolean to enable or disable sub-grid display.
  • subGridStrokeStyle: CSS stroke style for sub-grid lines.
  • snapThresholdPercentage: Percentage threshold for snapping selection to canvas edges.
  • animateSelection: Boolean to enable or disable selection animation.

Usage Example (Conceptual)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Editor</title>
    <style>
        image-editor {
            display: block;
            width: 800px;
            height: 600px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>

    <image-editor id="myImageEditor"></image-editor>

    <script type="module">
        import "./path/to/ImageEditor.js"; // Import as side effect

        const imageEditor = document.getElementById('myImageEditor');

        // Example: Load an image
        // This functionality would typically be exposed via methods on the ImageEditorCustomElement
        // or through external controls interacting with the custom element.
        // For demonstration, imagine a function to load an image:
        // imageEditor.loadImage('/path/to/your/image.jpg');

        // Example: Listen for status messages
        document.addEventListener('onCanvasStatusMessage', (event) => {
            console.log('Status:', event.detail.message);
        });

        // You would interact with the image editor through its exposed properties and methods
        // or through events dispatched by the custom element.
    </script>
</body>
</html>


## Events

The ImageEditor custom element dispatches the following events that can be listened to from outside the custom element:

### canvasStatusMessage

Fired when there's a status message from the canvas.

```javascript
imageEditor.addEventListener('canvasStatusMessage', function(event) {
  console.log('Canvas status message:', event.detail.message);
});

closeImageEditor

Fired when the image editor is closed.

imageEditor.addEventListener('closeImageEditor', function(event) {
  console.log('Image editor closed');
});

imageSave

Fired when an image is saved.

imageEditor.addEventListener('imageSave', function(event) {
  console.log('Image saved:', event.detail.id, event.detail.file);
});

Usage Example

document.addEventListener("DOMContentLoaded", function () {
  let imageEditor = document.querySelector('#image-editor');

  // Listen to events from the custom element
  imageEditor.addEventListener('canvasStatusMessage', function(event) {
    console.log('Canvas status message:', event.detail.message);
  });

  imageEditor.addEventListener('closeImageEditor', function(event) {
    console.log('Image editor closed');
  });

  imageEditor.addEventListener('imageSave', function(event) {
    console.log('Image saved:', event.detail.id, event.detail.file);
  });

  imageEditor.setImage('heart', 'test/images/heart.png', 'heart');
}, false);

---