import {
ACTION_CROP,
ACTION_ZOOM,
CLASS_CROP,
CLASS_MODAL,
DATA_ACTION,
DRAG_MODE_CROP,
DRAG_MODE_MOVE,
DRAG_MODE_NONE,
EVENT_CROP_END,
EVENT_CROP_MOVE,
EVENT_CROP_START,
REGEXP_ACTIONS,
} from './constants';
import {
addClass,
assign,
dispatchEvent,
forEach,
getData,
getPointer,
hasClass,
isNumber,
toggleClass,
} from './utilities';
export default {
resize() {
if (this.disabled) {
return;
}
const { options, container, containerData } = this;
const ratio = container.offsetWidth / containerData.width;
// Resize when width changed or height changed
if (ratio !== 1 || container.offsetHeight !== containerData.height) {
let canvasData;
let cropBoxData;
if (options.restore) {
canvasData = this.getCanvasData();
cropBoxData = this.getCropBoxData();
}
this.render();
if (options.restore) {
this.setCanvasData(forEach(canvasData, (n, i) => {
canvasData[i] = n * ratio;
}));
this.setCropBoxData(forEach(cropBoxData, (n, i) => {
cropBoxData[i] = n * ratio;
}));
}
}
},
dblclick() {
if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) {
return;
}
this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP);
},
wheel(event) {
const ratio = Number(this.options.wheelZoomRatio) || 0.1;
let delta = 1;
if (this.disabled) {
return;
}
event.preventDefault();
// Limit wheel speed to prevent zoom too fast (#21)
if (this.wheeling) {
return;
}
this.wheeling = true;
setTimeout(() => {
this.wheeling = false;
}, 50);
if (event.deltaY) {
delta = event.deltaY > 0 ? 1 : -1;
} else if (event.wheelDelta) {
delta = -event.wheelDelta / 120;
} else if (event.detail) {
delta = event.detail > 0 ? 1 : -1;
}
this.zoom(-delta * ratio, event);
},
cropStart(event) {
const { buttons, button } = event;
if (
this.disabled
// Handle mouse event and pointer event and ignore touch event
|| ((
event.type === 'mousedown'
|| (event.type === 'pointerdown' && event.pointerType === 'mouse')
) && (
// No primary button (Usually the left button)
(isNumber(buttons) && buttons !== 1)
|| (isNumber(button) && button !== 0)
// Open context menu
|| event.ctrlKey
))
) {
return;
}
const { options, pointers } = this;
let action;
if (event.changedTouches) {
// Handle touch event
forEach(event.changedTouches, (touch) => {
pointers[touch.identifier] = getPointer(touch);
});
} else {
// Handle mouse event and pointer event
pointers[event.pointerId || 0] = getPointer(event);
}
if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) {
action = ACTION_ZOOM;
} else {
action = getData(event.target, DATA_ACTION);
}
if (!REGEXP_ACTIONS.test(action)) {
return;
}
if (dispatchEvent(this.element, EVENT_CROP_START, {
originalEvent: event,
action,
}) === false) {
return;
}
// This line is required for preventing page zooming in iOS browsers
event.preventDefault();
this.action = action;
this.cropping = false;
if (action === ACTION_CROP) {
this.cropping = true;
addClass(this.dragBox, CLASS_MODAL);
}
},
cropMove(event) {
const { action } = this;
if (this.disabled || !action) {
return;
}
const { pointers } = this;
event.preventDefault();
if (dispatchEvent(this.element, EVENT_CROP_MOVE, {
originalEvent: event,
action,
}) === false) {
return;
}
if (event.changedTouches) {
forEach(event.changedTouches, (touch) => {
// The first parameter should not be undefined (#432)
assign(pointers[touch.identifier] || {}, getPointer(touch, true));
});
} else {
assign(pointers[event.pointerId || 0] || {}, getPointer(event, true));
}
this.change(event);
},
cropEnd(event) {
if (this.disabled) {
return;
}
const { action, pointers } = this;
if (event.changedTouches) {
forEach(event.changedTouches, (touch) => {
delete pointers[touch.identifier];
});
} else {
delete pointers[event.pointerId || 0];
}
if (!action) {
return;
}
event.preventDefault();
if (!Object.keys(pointers).length) {
this.action = '';
}
if (this.cropping) {
this.cropping = false;
toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal);
}
dispatchEvent(this.element, EVENT_CROP_END, {
originalEvent: event,
action,
});
},
};