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.