Skip to content

CropperImage

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

Examples

Basic

TIP

The default width and height of this element is 0.

With image source

Set zoom origin

Details
vue
<template>
  <div class="cropper-container">
    <form>
      <fieldset>
        <legend>Zoom Origin:</legend>
        <input
          id="zoomOriginPointer"
          v-model="zoomOrigin"
          type="radio"
          name="zoomOrigin"
          value="pointer"
        >
        <label for="zoomOriginPointer">pointer (default)</label>
        <input
          id="zoomOriginCenter"
          v-model="zoomOrigin"
          type="radio"
          name="zoomOrigin"
          value="center"
        >
        <label for="zoomOriginCenter">center</label>
      </fieldset>
    </form>
    <cropper-canvas
      :key="zoomOrigin"
      background
      @action="onCropperCanvasAction"
    >
      <cropper-image
        ref="cropperImage"
        :src="src"
        alt="Picture"
        scalable
      />
      <cropper-handle
        action="scale"
        plain
      />
    </cropper-canvas>
  </div>
</template>

<script lang="ts">
import type CropperImage from '@cropper/element-image';

const { BASE_URL } = import.meta.env;

export default {
  name: 'CropperImageZoomOriginExample',
  data() {
    return {
      src: `${BASE_URL}picture.jpg`,
      zoomOrigin: 'center',
    };
  },
  methods: {
    onCropperCanvasAction(event: CustomEvent) {
      if (this.zoomOrigin === 'center' && typeof event.detail.scale === 'number') {
        event.preventDefault();
        (this.$refs.cropperImage as CropperImage).$zoom(event.detail.scale);
      }
    },
  },
};
</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>

Set initial fit

Details
vue
<template>
  <div class="cropper-container">
    <form>
      <fieldset>
        <legend>initialFit:</legend>
        <input
          id="initialFitCover"
          v-model="initialFit"
          type="radio"
          name="initialFit"
          value="cover"
        >
        <label for="initialFitCover">cover</label>
        <input
          id="initialFitFill"
          v-model="initialFit"
          type="radio"
          name="initialFit"
          value="fill"
        >
        <label for="initialFitFill">fill</label>
        <input
          id="initialFitContain"
          v-model="initialFit"
          type="radio"
          name="initialFit"
          value="contain"
        >
        <label for="initialFitContain">contain</label>
        <input
          id="initialFitScaleDown"
          v-model="initialFit"
          type="radio"
          name="initialFit"
          value="scale-down"
        >
        <label for="initialFitScaleDown">scale-down</label>
        <input
          id="initialFitNone"
          v-model="initialFit"
          type="radio"
          name="initialFit"
          value="none"
        >
        <label for="initialFitNone">none</label>
      </fieldset>
    </form>
    <cropper-canvas
      ref="cropperCanvas"
      :key="initialFit"
      background
    >
      <cropper-image
        ref="cropperImage"
        :src="src"
        alt="Picture"
        :initial-fit="initialFit"
        rotatable
        scalable
        skewable
        translatable
      />
      <cropper-handle
        action="move"
        plain
      />
    </cropper-canvas>
  </div>
</template>

<script lang="ts">
const { BASE_URL } = import.meta.env;

export default {
  name: 'CropperImageInitialFitExample',
  data() {
    return {
      src: `${BASE_URL}picture.jpg`,
      initialFit: 'contain',
    };
  },
};
</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>

Set max fit and/or min fit

Details
vue
<template>
  <div class="cropper-container">
    <form>
      <fieldset>
        <legend>Max Fit:</legend>
        <input
          id="maxFit"
          v-model="maxFit"
          type="radio"
          name="maxFit"
          value=""
        >
        <label for="maxFit">default</label>
        <input
          id="maxFitCover"
          v-model="maxFit"
          type="radio"
          name="maxFit"
          value="cover"
        >
        <label for="maxFitCover">cover</label>
        <input
          id="maxFitFill"
          v-model="maxFit"
          type="radio"
          name="maxFit"
          value="fill"
        >
        <label for="maxFitFill">fill</label>
        <input
          id="maxFitContain"
          v-model="maxFit"
          type="radio"
          name="maxFit"
          value="contain"
        >
        <label for="maxFitContain">contain</label>
        <input
          id="maxFitScaleDown"
          v-model="maxFit"
          type="radio"
          name="maxFit"
          value="scale-down"
        >
        <label for="maxFitScaleDown">scale-down</label>
        <input
          id="maxFitNone"
          v-model="maxFit"
          type="radio"
          name="maxFit"
          value="none"
        >
        <label for="maxFitNone">none</label>
      </fieldset>
      <fieldset>
        <legend>Min Fit:</legend>
        <input
          id="minFit"
          v-model="minFit"
          type="radio"
          name="minFit"
          value=""
        >
        <label for="minFit">default</label>
        <input
          id="minFitCover"
          v-model="minFit"
          type="radio"
          name="minFit"
          value="cover"
        >
        <label for="minFitCover">cover</label>
        <input
          id="minFitFill"
          v-model="minFit"
          type="radio"
          name="minFit"
          value="fill"
        >
        <label for="minFitFill">fill</label>
        <input
          id="minFitContain"
          v-model="minFit"
          type="radio"
          name="minFit"
          value="contain"
        >
        <label for="minFitContain">contain</label>
        <input
          id="minFitScaleDown"
          v-model="minFit"
          type="radio"
          name="minFit"
          value="scale-down"
        >
        <label for="minFitScaleDown">scale-down</label>
        <input
          id="minFitNone"
          v-model="minFit"
          type="radio"
          name="minFit"
          value="none"
        >
        <label for="minFitNone">none</label>
      </fieldset>
    </form>
    <cropper-canvas
      ref="cropperCanvas"
      :key="minFit"
      background
    >
      <cropper-image
        ref="cropperImage"
        :src="src"
        alt="Picture"
        :max-fit="maxFit"
        :min-fit="minFit"
        rotatable
        scalable
        skewable
        translatable
      />
      <cropper-handle
        action="move"
        plain
      />
    </cropper-canvas>
  </div>
</template>

<script lang="ts">
const { BASE_URL } = import.meta.env;

export default {
  name: 'CropperImageMaxFitAndMinFitExample',
  data() {
    return {
      src: `${BASE_URL}picture.jpg`,
      maxFit: 'cover',
      minFit: 'contain',
    };
  },
};
</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>

Limit boundaries

Details
vue
<template>
  <div class="cropper-container">
    <form>
      <fieldset>
        <legend>Within:</legend>
        <input
          id="withinViewport"
          v-model="within"
          type="radio"
          name="within"
          value="viewport"
        >
        <label for="withinViewport">viewport</label>
        <input
          id="withinCanvas"
          v-model="within"
          type="radio"
          name="within"
          value="canvas"
        >
        <label for="withinCanvas">canvas</label>
        <input
          id="withinNone"
          v-model="within"
          type="radio"
          name="within"
          value="none"
        >
        <label for="withinNone">none</label>
      </fieldset>
    </form>
    <cropper-canvas
      ref="cropperCanvas"
      :key="within"
      background
    >
      <cropper-image
        ref="cropperImage"
        :src="src"
        alt="Picture"
        rotatable
        scalable
        skewable
        translatable
        @change="onCropperImageChange"
      />
      <cropper-handle
        action="move"
        plain
      />
    </cropper-canvas>
  </div>
</template>

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

const { BASE_URL } = import.meta.env;

export default {
  name: 'CropperImageExample',
  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)
      );
    },
    onCropperImageChange(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 'viewport': {
          const maxSelection: Selection = {
            x: -cropperCanvasRect.x,
            y: -cropperCanvasRect.y,
            width: window.innerWidth,
            height: window.innerHeight,
          };

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

        case 'canvas': {
          const maxSelection: Selection = {
            x: 0,
            y: 0,
            width: cropperCanvasRect.width,
            height: cropperCanvasRect.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
initialFit ^2.2.0string"contain""cover" | "fill" | "contain" | "scale-down" | "none"Indicates the initial size of the image when aligned with the center of its parent element.
maxFit ^2.2.0string"""cover" | "fill" | "contain" | "scale-down" | "none"Indicates the max size of this element relative to its parent element.
minFit ^2.2.0string"""cover" | "fill" | "contain" | "scale-down" | "none"Indicates the min size of this element relative to its parent element.
rotatablebooleanfalse-Indicates whether this element is rotatable.
scalablebooleanfalse-Indicates whether this element is scalable.
skewablebooleanfalse-Indicates whether this element is skewable.
slottablebooleanfalse-Indicates whether this element is slottable.
translatablebooleanfalse-Indicates whether this element is translatable.
initialCenterSize deprecatedstring"contain""contain", "cover"Indicates the initial size of this element when aligned with the center of its parent element.

The built-in <img> element will inherit the following attributes by default:

  • alt
  • crossorigin
  • decoding
  • elementtiming
  • fetchpriority
  • loading
  • referrerpolicy
  • sizes
  • src
  • srcset

Methods

$ready

  • Syntax:

    • $ready()
    • $ready(callback)
  • Arguments:

    • callback:
      • Type: Function
      • The callback to execute after successfully loading the image.
  • Returns:

    • Type: Promise
    • A promise that resolves to the image element.
  • Example:

    js
    const cropperImage = new CropperImage();
    
    cropperImage.$ready((image) => {
      console.log(image.naturalWidth, image.naturalHeight);
    });
    cropperImage.src = '/cropperjs/picture.jpg';

Defers the callback to execute after successfully loading the image.

$center

  • Syntax:
    • $center()
    • $center(size)
  • Arguments:
    • size:
      • Type: string
      • Options: "cover", "fill", "contain", "scale-down", and "none".
      • The size of the image.
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.

Aligns the image to the center of its parent element.

$move

  • Syntax:
    • $move(x)
    • $move(x, 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: CropperImage
    • The element instance for chaining.

Moves the image.

$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: CropperImage
    • The element instance for chaining.

Moves the image to a specific position.

$rotate

  • Syntax: $rotate(angle)
  • Arguments:
    • angle:
      • Type: number | string
      • The rotation angle (in radians). The default unit is rad.
    • x:
      • Type: number
      • Default: The center of the image in the horizontal.
      • The rotation origin in the horizontal.
    • y:
      • Type: number
      • Default: The center of the image in the vertical.
      • The rotation origin in the vertical.
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.
  • Examples:
    • $rotate(0.8)
    • $rotate('0.8rad')
    • $rotate('45deg')
    • $rotate('50grad')
    • $rotate('0.1turn')
    • $rotate('90deg', 0, 0)

Rotates the image. It is similar to CSS function rotate() or CanvasRenderingContext2D.rotate().

$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 image in the horizontal.
      • The zoom origin in the horizontal.
    • y:
      • Type: number
      • Default: The center of the image in the vertical.
      • The zoom origin in the vertical.
  • Returns:

    • Type: CropperImage
    • The element instance for chaining.
  • Examples:

    js
    cropperImage.$zoom(0.1); // Zoom in 10%
    cropperImage.$zoom(-0.1); // Zoom out 10%
    cropperImage.$zoom(0.1, 0, 0); // Zoom in from the top-left corner
    cropperImage.$zoom(-0.1, 0, 0); // Zoom out from the top-left corner

Zooms the image.

$scale

  • Syntax:

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

    • x:
      • Type: number
      • The scaling factor in the horizontal direction.
    • y:
      • Type: number
      • Default: x
      • The scaling factor in the vertical direction.
  • Returns:

    • Type: CropperImage
    • The element instance for chaining.
  • Examples:

    js
    cropperImage.$scale(1.1); // Zoom in 10%
    cropperImage.$scale(0.9); // Zoom out 10%
    cropperImage.$scale(-1); // Flip both the horizontal and vertical directions
    cropperImage.$scale(-1, 1); // Flip the horizontal direction
    cropperImage.$scale(1, -1); // Flip the vertical direction

Scales the image. It is similar to CSS function scale() or CanvasRenderingContext2D.scale().

$skew

  • Syntax:
    • $skew(x)
    • $skew(x, y)
  • Arguments:
    • x:
      • Type: number | string
      • The skewing angle in the horizontal direction. The default unit is rad.
    • y:
      • Type: number | string
      • Default: x
      • The skewing angle in the vertical direction. The default unit is rad.
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.
  • Examples:
    • $skew(0.8)
    • $skew('0.8rad')
    • $skew('45deg')
    • $skew('50grad')
    • $skew('0.1turn')
    • $skew(0, 0.8)

Skews the image. It is similar to CSS function skew().

$translate

  • Syntax:
    • $translate(x)
    • $translate(x, y)
  • Arguments:
    • x:
      • Type: number
      • The translating distance in the horizontal direction.
    • y:
      • Type: number
      • Default: x
      • The translating distance in the vertical direction.
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.

Translates the image. It is similar to CSS function translate() or CanvasRenderingContext2D.translate().

$transform

  • Syntax: $transform(a, b, c, d, e, f)
  • Arguments:
    • a:
      • Type: number
      • The scaling factor in the horizontal direction.
    • b:
      • Type: number
      • The skewing angle in the vertical direction.
    • c:
      • Type: number
      • The skewing angle in the horizontal direction.
    • d:
      • Type: number
      • The scaling factor in the vertical direction.
    • e:
      • Type: number
      • The translating distance in the horizontal direction.
    • f:
      • Type: number
      • The translating distance in the vertical direction.
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.

Transforms the image. It is similar to CSS function matrix() or CanvasRenderingContext2D.transform().

$setTransform

  • Syntax:
    • $setTransform(a, b, c, d, e, f)
    • $setTransform(a)
  • Arguments:
    • a:
      • Type: number | Array
      • The scaling factor in the horizontal direction, or the transformation matrix.
    • b:
      • Type: number
      • The skewing angle in the vertical direction.
    • c:
      • Type: number
      • The skewing angle in the horizontal direction.
    • d:
      • Type: number
      • The scaling factor in the vertical direction.
    • e:
      • Type: number
      • The translating distance in the horizontal direction.
    • f:
      • Type: number
      • The translating distance in the vertical direction.
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.

Resets (overrides) the current transform to the specific identity matrix, and then invokes a transform described by the arguments of this method. This lets you scale, rotate, translate (move), and skew the context. It is similar to CanvasRenderingContext2D.setTransform().

$getTransform

  • Syntax: $getTransform()
  • Returns:
    • Type: Array
    • The current transformation matrix of the element.

Retrieves the current transformation matrix being applied to the element. It is similar to CanvasRenderingContext2D.getTransform().

$resetTransform

  • Syntax:
    • $resetTransform()
  • Alternatives:
    • $setTransform(1, 0, 0, 1, 0, 0)
    • $setTransform([1, 0, 0, 1, 0, 0])
  • Returns:
    • Type: CropperImage
    • The element instance for chaining.

Resets the current transform to the initial identity matrix. It is similar to CanvasRenderingContext2D.resetTransform().

Events

transform

  • Event:
    • event.bubbles: true
    • event.cancelable: true
    • event.composed: true
    • event.detail:
      • Type: Object
      • The transform information of the image.
    • event.detail.matrix:
      • Type: Array
      • The new (next) matrix object.
    • event.detail.oldMatrix:
      • Type: Array
      • The old (current) matrix object.

The event is fired when the transform CSS property of the element is going to change.

change ^2.2.0

The event is fired when the position or size of the image 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 image.
    • event.detail.x:
      • Type: number
      • The x-axis coordinate of the image.
    • event.detail.y:
      • Type: number
      • The y-axis coordinate of the image.
    • event.detail.width:
      • Type: number
      • The width of the image.
    • event.detail.height:
      • Type: number
      • The height of the image.
  • Example:
html
<cropper-image id="image"></cropper-image>

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

Slots

There are no available slots in this element.

You can enable the default slot by setting the slottable property to true:

html
<cropper-image slottable></cropper-image>

Released under the MIT License.