mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 19:16:41 +07:00
155 lines
4.1 KiB
JavaScript
155 lines
4.1 KiB
JavaScript
import { marker } from 'leaflet';
|
|
import 'leaflet-editable';
|
|
|
|
import { DomMarker } from '$utils/DomMarker';
|
|
|
|
import stickers from '$sprites/stickers.svg';
|
|
import { STICKERS } from '$constants/stickers';
|
|
|
|
export class Sticker {
|
|
constructor({
|
|
latlng, deleteSticker, map, lockMapClicks, sticker, triggerOnChange, angle = 2.2
|
|
}) {
|
|
this.latlng = latlng;
|
|
this.angle = angle;
|
|
this.isDragging = false;
|
|
this.map = map;
|
|
this.sticker = sticker;
|
|
this.editable = true;
|
|
this.triggerOnChange = triggerOnChange;
|
|
|
|
this.deleteSticker = deleteSticker;
|
|
this.lockMapClicks = lockMapClicks;
|
|
|
|
this.element = document.createElement('div');
|
|
this.stickerImage = document.createElement('div');
|
|
this.stickerArrow = document.createElement('div');
|
|
this.stickerDelete = document.createElement('div');
|
|
|
|
this.element.className = 'sticker-container';
|
|
this.stickerImage.className = 'sticker-label';
|
|
this.stickerArrow.className = 'sticker-arrow';
|
|
this.stickerDelete.className = 'sticker-delete';
|
|
|
|
this.stickerImage.innerHTML = this.generateStickerSVG(sticker);
|
|
|
|
this.element.appendChild(this.stickerArrow);
|
|
this.element.appendChild(this.stickerImage);
|
|
this.element.appendChild(this.stickerDelete);
|
|
|
|
const mark = new DomMarker({
|
|
element: this.element,
|
|
className: 'sticker-container',
|
|
});
|
|
|
|
this.marker = marker(latlng, { icon: mark });
|
|
|
|
this.setAngle(angle);
|
|
|
|
this.stickerImage.addEventListener('mousedown', this.onDragStart);
|
|
this.stickerImage.addEventListener('mouseup', this.onDragStop);
|
|
|
|
this.element.addEventListener('mouseup', this.preventPropagations);
|
|
this.stickerDelete.addEventListener('click', this.onDelete);
|
|
|
|
this.marker.addEventListener('dragend', this.triggerOnChange);
|
|
|
|
this.triggerOnChange();
|
|
}
|
|
|
|
onDelete = () => {
|
|
this.triggerOnChange();
|
|
if (!this.isDragging) this.deleteSticker(this);
|
|
};
|
|
|
|
onDragStart = e => {
|
|
this.preventPropagations(e);
|
|
|
|
this.isDragging = true;
|
|
this.marker.disableEdit();
|
|
|
|
this.lockMapClicks(true);
|
|
|
|
window.addEventListener('mousemove', this.onDrag);
|
|
window.addEventListener('mouseup', this.onDragStop);
|
|
};
|
|
|
|
preventPropagations = e => {
|
|
if (!e || !e.stopPropagation) return;
|
|
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
};
|
|
|
|
onDragStop = e => {
|
|
this.preventPropagations(e);
|
|
|
|
this.triggerOnChange();
|
|
this.isDragging = false;
|
|
this.marker.enableEdit();
|
|
|
|
window.removeEventListener('mousemove', this.onDrag);
|
|
window.removeEventListener('mouseup', this.onDragStop);
|
|
|
|
this.lockMapClicks(false);
|
|
};
|
|
|
|
onDrag = e => {
|
|
this.preventPropagations(e);
|
|
this.estimateAngle(e);
|
|
};
|
|
|
|
estimateAngle = e => {
|
|
const { x, y } = this.element.getBoundingClientRect();
|
|
const { pageX, pageY } = e;
|
|
this.angle = Math.atan2((y - pageY), (x - pageX));
|
|
|
|
this.setAngle(this.angle);
|
|
};
|
|
|
|
setAngle = angle => {
|
|
const rad = 44;
|
|
const mrad = 76;
|
|
const x = ((Math.cos(angle + 3.14) * rad) - 30);
|
|
const y = ((Math.sin(angle + 3.14) * rad) - 30);
|
|
|
|
const ax = ((Math.cos(angle + 3.4) * mrad) - 12);
|
|
const ay = ((Math.sin(angle + 3.4) * mrad) - 12);
|
|
|
|
this.stickerImage.style.left = 6 + x;
|
|
this.stickerImage.style.top = 6 + y;
|
|
|
|
this.stickerDelete.style.left = ax;
|
|
this.stickerDelete.style.top = ay;
|
|
|
|
this.stickerArrow.style.transform = `rotate(${angle + 3.14}rad)`;
|
|
};
|
|
|
|
generateStickerSVG = ({ set, sticker }) => (
|
|
// `
|
|
// <svg width="64" height="64">
|
|
// <use xlink:href="${stickers}#sticker-${sticker}" x="0" y="0" width="64" height="64" />
|
|
// </svg>
|
|
// `
|
|
`
|
|
<div
|
|
class="sticker-image"
|
|
style="background-image: url('${STICKERS[set].url}');background-position: ${-STICKERS[set].layers[sticker].off * 64} 50%">
|
|
</div>
|
|
`
|
|
);
|
|
|
|
dumpData = () => ({
|
|
angle: this.angle,
|
|
latlng: { ...this.marker.getLatLng() },
|
|
sticker: this.sticker,
|
|
});
|
|
|
|
stopEditing = () => {
|
|
this.element.className = 'sticker-container inactive';
|
|
};
|
|
|
|
startEditing = () => {
|
|
this.element.className = 'sticker-container';
|
|
};
|
|
}
|