@cropper/element-shade
Version:
A custom shade element for the Cropper.
134 lines (130 loc) • 4.83 kB
JavaScript
import CropperElement from '@cropper/element';
import { CROPPER_SHADE, CROPPER_CANVAS, CROPPER_SELECTION, ACTION_SELECT, on, EVENT_ACTION_START, EVENT_ACTION_END, EVENT_CHANGE, off, isNumber, WINDOW } from '@cropper/utils';
var style = `:host{display:block;height:0;left:0;outline:var(--theme-color) solid 1px;position:relative;top:0;width:0}:host([transparent]){outline-color:transparent}`;
const canvasCache = new WeakMap();
class CropperShade extends CropperElement {
constructor() {
super(...arguments);
this.$onCanvasChange = null;
this.$onCanvasActionEnd = null;
this.$onCanvasActionStart = null;
this.$style = style;
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
this.slottable = false;
this.themeColor = 'rgba(0, 0, 0, 0.65)';
}
set $canvas(element) {
canvasCache.set(this, element);
}
get $canvas() {
return canvasCache.get(this);
}
static get observedAttributes() {
return super.observedAttributes.concat([
'height',
'width',
'x',
'y',
]);
}
connectedCallback() {
super.connectedCallback();
const $canvas = this.closest(this.$getTagNameOf(CROPPER_CANVAS));
if ($canvas) {
this.$canvas = $canvas;
this.style.position = 'absolute';
const $selection = $canvas.querySelector(this.$getTagNameOf(CROPPER_SELECTION));
if ($selection) {
this.$onCanvasActionStart = (event) => {
if ($selection.hidden && event.detail.action === ACTION_SELECT) {
this.hidden = false;
}
};
this.$onCanvasActionEnd = (event) => {
if ($selection.hidden && event.detail.action === ACTION_SELECT) {
this.hidden = true;
}
};
this.$onCanvasChange = (event) => {
const { x, y, width, height, } = event.detail;
this.$change(x, y, width, height);
if ($selection.hidden || (x === 0 && y === 0 && width === 0 && height === 0)) {
this.hidden = true;
}
};
on($canvas, EVENT_ACTION_START, this.$onCanvasActionStart);
on($canvas, EVENT_ACTION_END, this.$onCanvasActionEnd);
on($canvas, EVENT_CHANGE, this.$onCanvasChange);
}
}
this.$render();
}
disconnectedCallback() {
const { $canvas } = this;
if ($canvas) {
if (this.$onCanvasActionStart) {
off($canvas, EVENT_ACTION_START, this.$onCanvasActionStart);
this.$onCanvasActionStart = null;
}
if (this.$onCanvasActionEnd) {
off($canvas, EVENT_ACTION_END, this.$onCanvasActionEnd);
this.$onCanvasActionEnd = null;
}
if (this.$onCanvasChange) {
off($canvas, EVENT_CHANGE, this.$onCanvasChange);
this.$onCanvasChange = null;
}
}
super.disconnectedCallback();
}
/**
* Changes the position and/or size of the shade.
* @param {number} x The new position in the horizontal direction.
* @param {number} y The new position in the vertical direction.
* @param {number} [width] The new width.
* @param {number} [height] The new height.
* @returns {CropperShade} Returns `this` for chaining.
*/
$change(x, y, width = this.width, height = this.height) {
if (!isNumber(x)
|| !isNumber(y)
|| !isNumber(width)
|| !isNumber(height)
|| (x === this.x && y === this.y && width === this.width && height === this.height)) {
return this;
}
if (this.hidden) {
this.hidden = false;
}
this.x = x;
this.y = y;
this.width = width;
this.height = height;
return this.$render();
}
/**
* Resets the shade to its initial position and size.
* @returns {CropperShade} Returns `this` for chaining.
*/
$reset() {
return this.$change(0, 0, 0, 0);
}
/**
* Refreshes the position or size of the shade.
* @returns {CropperShade} Returns `this` for chaining.
*/
$render() {
return this.$setStyles({
transform: `translate(${this.x}px, ${this.y}px)`,
width: this.width,
height: this.height,
outlineWidth: WINDOW.innerWidth,
});
}
}
CropperShade.$name = CROPPER_SHADE;
CropperShade.$version = '2.0.0';
export { CropperShade as default };