Skip to content

CropperSelection

The CropperSelection interface provides properties and methods for manipulating the layout and presentation of <cropper-selection> elements.

Examples

Basic

TIP

The default width and height of this element is 0.

Customize initial selection coverage

Customize position and size

With handles

Dynamic

Set the dynamic property to true to change as the image changes.

Multiple

Set the multiple property to true to support multiple selections on the same image.

Limit boundaries

Details
vue
<template>
  <div class="cropper-container">
    <form>
      <fieldset>
        <legend>Within:</legend>
        <input
          id="inputWithinCanvas"
          v-model="within"
          type="radio"
          name="within"
          value="canvas"
        >
        <label for="inputWithinCanvas">canvas</label>
        <input
          id="inputWithinImage"
          v-model="within"
          type="radio"
          name="within"
          value="image"
        >
        <label for="inputWithinImage">image</label>
        <input
          id="inputWithinNone"
          v-model="within"
          type="radio"
          name="within"
          value="none"
        >
        <label for="inputWithinNone">none</label>
      </fieldset>
    </form>
    <cropper-canvas
      ref="cropperCanvas"
      :key="within"
      background
    >
      <cropper-image
        ref="cropperImage"
        :src="src"
        alt="Picture"
        rotatable
        scalable
        skewable
        translatable
        @transform="onCropperImageTransform"
      />
      <cropper-handle
        action="move"
        plain
      />
      <cropper-selection
        ref="cropperSelection"
        initial-coverage="0.5"
        movable
        resizable
        outlined
        @change="onCropperSelectionChange"
      >
        <cropper-grid
          role="grid"
          covered
        />
        <cropper-crosshair centered />
        <cropper-handle
          action="move"
          theme-color="rgba(255, 255, 255, 0.35)"
        />
        <cropper-handle action="n-resize" />
        <cropper-handle action="e-resize" />
        <cropper-handle action="s-resize" />
        <cropper-handle action="w-resize" />
        <cropper-handle action="ne-resize" />
        <cropper-handle action="nw-resize" />
        <cropper-handle action="se-resize" />
        <cropper-handle action="sw-resize" />
      </cropper-selection>
    </cropper-canvas>
  </div>
</template>

<script lang="ts">
import type CropperCanvas from '@cropper/element-canvas';
import type CropperImage from '@cropper/element-image';
import type CropperSelection from '@cropper/element-selection';
import type { Selection } from '@cropper/element-selection';

const { BASE_URL } = import.meta.env;

export default {
  name: 'CropperSelectionExample',
  data() {
    return {
      src: `${BASE_URL}picture.jpg`,
      within: 'canvas',
    };
  },
  methods: {
    inSelection(selection: Selection, maxSelection: Selection) {
      return (
        selection.x >= maxSelection.x
        && selection.y >= maxSelection.y
        && (selection.x + selection.width) <= (maxSelection.x + maxSelection.width)
        && (selection.y + selection.height) <= (maxSelection.y + maxSelection.height)
      );
    },
    onCropperImageTransform(event: CustomEvent) {
      const cropperCanvas = this.$refs.cropperCanvas as CropperCanvas;

      if (!cropperCanvas || this.within !== 'image') {
        return;
      }

      const cropperImage = this.$refs.cropperImage as CropperImage;
      const cropperSelection = this.$refs.cropperSelection as CropperSelection;
      const cropperCanvasRect = cropperCanvas.getBoundingClientRect();

      // 1. Clone the cropper image.
      const cropperImageClone = cropperImage.cloneNode() as CropperImage;

      // 2. Apply the new matrix to the cropper image clone.
      cropperImageClone.style.transform = `matrix(${event.detail.matrix.join(', ')})`;

      // 3. Make the cropper image clone invisible.
      cropperImageClone.style.opacity = '0';

      // 4. Append the cropper image clone to the cropper canvas.
      cropperCanvas.appendChild(cropperImageClone);

      // 5. Compute the boundaries of the cropper image clone.
      const cropperImageRect = cropperImageClone.getBoundingClientRect();

      // 6. Remove the cropper image clone.
      cropperCanvas.removeChild(cropperImageClone);

      const selection = cropperSelection as Selection;
      const maxSelection: Selection = {
        x: cropperImageRect.left - cropperCanvasRect.left,
        y: cropperImageRect.top - cropperCanvasRect.top,
        width: cropperImageRect.width,
        height: cropperImageRect.height,
      };

      if (!this.inSelection(selection, maxSelection)) {
        event.preventDefault();
      }
    },
    onCropperSelectionChange(event: CustomEvent) {
      const cropperCanvas = this.$refs.cropperCanvas as CropperCanvas;

      if (!cropperCanvas || this.within === 'none') {
        return;
      }

      const cropperCanvasRect = cropperCanvas.getBoundingClientRect();
      const selection = event.detail as Selection;

      switch (this.within) {
        case 'canvas': {
          const maxSelection: Selection = {
            x: 0,
            y: 0,
            width: cropperCanvasRect.width,
            height: cropperCanvasRect.height,
          };

          if (!this.inSelection(selection, maxSelection)) {
            event.preventDefault();
          }
          break;
        }

        case 'image': {
          const cropperImage = this.$refs.cropperImage as CropperImage;
          const cropperImageRect = cropperImage.getBoundingClientRect();
          const maxSelection: Selection = {
            x: cropperImageRect.left - cropperCanvasRect.left,
            y: cropperImageRect.top - cropperCanvasRect.top,
            width: cropperImageRect.width,
            height: cropperImageRect.height,
          };

          if (!this.inSelection(selection, maxSelection)) {
            event.preventDefault();
          }
          break;
        }

        default:
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.cropper-container {
  border: 1px solid var(--vp-c-divider);
  border-radius: 0.375rem;
  margin-bottom: 1rem;
  margin-top: 1rem;
  padding: 1.25rem 1.5rem;

  fieldset {
    border: 1px solid var(--vp-c-divider);
    border-radius: 0.375rem;
    margin-bottom: 1rem;
    padding: 0.25rem 0.75rem 0.75rem 0.75rem;

    > input {
      margin: 0 0.25rem 0 0;
      transform: translateY(-0.5px);
      vertical-align: middle;
    }

    > label {
      margin-right: 0.5rem;
    }
  }

  cropper-canvas {
    height: 320px;
  }
}
</style>

Properties

Inherits properties from its parent, CropperElement, and implements the following properties:

NameTypeDefaultOptionsDescription
xnumber0-Indicates the x-axis coordinate of the selection.
ynumber0-Indicates the y-axis coordinate of the selection.
widthnumber0-Indicates the width of the selection.
heightnumber0-Indicates the height of the selection.
aspectRationumberNaN-Indicates the aspect ratio of the selection, must a positive number.
initialAspectRationumberNaN-Indicates the initial aspect ratio of the selection, must a positive number.
initialCoveragenumberNaN-Indicates the initial coverage of the selection, must a positive number between 0 (0%) and 1 (100%).
dynamicbooleanfalse-Indicates whether this selection is dynamic and changes as the image changes.
movablebooleanfalse-Indicates whether this element is movable.
resizablebooleanfalse-Indicates whether this element is resizable.
zoomablebooleanfalse-Indicates whether this element is zoomable.
multiplebooleanfalse-Indicates whether multiple selections is supported.
keyboardbooleanfalse-Indicates whether keyboard control is supported.
outlinedbooleanfalse-Indicates whether show the outlined or not.
precisebooleanfalse-Indicates whether reserve the precise of the x, y, width, and height properties or not.

The supported keyboard keys:

  • Delete or Command + Backspace: Removes the active selection.
  • ArrowLeft: Moves the active selection to the left by 1 pixel.
  • ArrowRight: Moves the active selection to the right by 1 pixel.
  • ArrowUp: Moves the active selection to the top by 1 pixel.
  • ArrowDown: Moves the active selection to the bottom by 1 pixel.
  • +: Zooms in the active selection by 10%.
  • -: Zooms out the active selection by 10%.

Methods

$center

  • Syntax: $center()
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Aligns the selection to the center of its parent element.

$move

  • Syntax:
    • $move(x)
    • $move(x, y)
  • Alternatives:
    • $moveTo(selection.x + x)
    • $moveTo(selection.x + x, selection.y + y)
  • Arguments:
    • x:
      • Type: number
      • The moving distance in the horizontal direction.
    • y:
      • Type: number
      • Default: x
      • The moving distance in the vertical direction.
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Moves the selection.

$moveTo

  • Syntax:
    • $moveTo(x)
    • $moveTo(x, y)
  • Arguments:
    • x:
      • Type: number
      • The new position in the horizontal direction.
    • y:
      • Type: number
      • Default: x
      • The new position in the vertical direction.
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Moves the selection to a specific position.

$resize

  • Syntax:
    • $resize(action)
    • $resize(action, offsetX)
    • $resize(action, offsetX, offsetY)
    • $resize(action, offsetX, offsetY, aspectRatio)
  • Arguments:
    • action:
      • Type: string
      • Options: "n-resize", "e-resize", "s-resize", "w-resize", "ne-resize", "nw-resize", "se-resize", and "sw-resize".
      • Indicates the side or corner to resize.
    • offsetX:
      • Type: number
      • Default: 0
      • The horizontal offset of the specific side or corner.
    • offsetY:
      • Type: number
      • Default: 0
      • The vertical offset of the specific side or corner.
    • aspectRatio:
      • Type: number
      • Default: this.aspectRatio
      • The aspect ratio for computing the new size if it is necessary.
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Adjusts the size of the selection on a specific side or corner.

$zoom

  • Syntax:

    • $zoom(scale)
    • $zoom(scale, x, y)
  • Arguments:

    • scale:
      • Type: number
      • The zoom factor. Positive numbers for zooming in, and negative numbers for zooming out.
    • x:
      • Type: number
      • Default: The center of the selection in the horizontal.
      • The zoom origin in the horizontal.
    • y:
      • Type: number
      • Default: The center of the selection in the vertical.
      • The zoom origin in the vertical.
  • Returns:

    • Type: CropperSelection
    • The element instance for chaining.
  • Example:

    js
    cropperSelection.$zoom(0.1); // Zoom in 10%
    cropperSelection.$zoom(-0.1); // Zoom out 10%

Zooms the selection. Changes the width and height of the selection in pixels directly at the same time.

$change

  • Syntax:
    • $change(x, y)
    • $change(x, y, width, height)
    • $change(x, y, width, height, aspectRatio)
  • Arguments:
    • x:
      • Type: number
      • The new position in the horizontal direction.
    • y:
      • Type: number
      • The new position in the vertical direction.
    • width:
      • Type: number
      • Default: this.width
      • The new width.
    • height:
      • Type: number
      • Default: this.height
      • The new height.
    • aspectRatio:
      • Type: number
      • Default: this.aspectRatio
      • The new aspect ratio for this change only.
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Changes the position and/or size of the selection.

$reset

  • Syntax: $reset()
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Resets the selection to its initial position and size.

$clear

  • Syntax: $clear()
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Clears the selection.

$render

  • Syntax: $render()
  • Returns:
    • Type: CropperSelection
    • The element instance for chaining.

Refreshes the position or size of the selection.

$toCanvas

  • Syntax:
    • $toCanvas()
    • $toCanvas(options)
  • Arguments:
    • options:
      • Type: Object
      • The available options.
      • Properties:
        • width:
          • Type: number
          • The width of the canvas.
        • height:
          • Type: number
          • The height of the canvas.
        • beforeDraw:
          • Type: Function
          • The function called before drawing the image onto the canvas.
          • Syntax: beforeDraw(context, canvas)
          • Arguments:
            • context:
              • Type: CanvasRenderingContext2D
              • The 2D rendering context of the canvas.
            • canvas:
              • Type: HTMLCanvasElement
              • The canvas element itself.
          • Example: function (context) { context.filter = 'grayscale(100%)'; }
  • Returns:
    • Type: Promise
    • A promise that resolves to the generated canvas element.
  • Example:

Generates a real canvas element, with the image (selected area only) drawn into if there is one.

Events

change

The event is fired when the position or size of the selection is going to change.

  • Event:
    • event.bubbles: true
    • event.cancelable: true
    • event.composed: true
    • event.detail:
      • Type: Object
      • The position and size data of the selection.
    • event.detail.x:
      • Type: number
      • The x-axis coordinate of the selection.
    • event.detail.y:
      • Type: number
      • The y-axis coordinate of the selection.
    • event.detail.width:
      • Type: number
      • The width of the selection.
    • event.detail.height:
      • Type: number
      • The height of the selection.
  • Example:
html
<cropper-selection id="selection"></cropper-selection>

<script>
document.querySelector('#selection').addEventListener('change', function (event) {
  console.log(event);
});
</script>

Slots

There is only one default slot in this element.

You can disable it by setting the slottable property to false:

html
<cropper-selection slottable="false"></cropper-selection>

Released under the MIT License.