mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 11:06:40 +07:00
stickers: text editing
This commit is contained in:
parent
fa9bff5756
commit
f183c8593d
6 changed files with 130 additions and 21 deletions
44
src/components/StickerDesc.jsx
Normal file
44
src/components/StickerDesc.jsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
|
||||
type State = {
|
||||
text: String,
|
||||
}
|
||||
|
||||
export class StickerDesc extends React.PureComponent<void, State> {
|
||||
state = {
|
||||
text: this.props.value,
|
||||
};
|
||||
|
||||
setText = e => {
|
||||
this.setState({ text: e.target.value });
|
||||
this.props.onChange(e.target.value);
|
||||
};
|
||||
|
||||
blockMouse = e => e.stopPropagation(); // todo: pass here locker for moving markers from Sticker.js
|
||||
|
||||
render() {
|
||||
const { text } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="sticker-desc"
|
||||
onMouseDown={this.blockMouse}
|
||||
onMouseUp={this.blockMouse}
|
||||
>
|
||||
<div className="sticker-desc-sizer">
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: (text.replace(/\n$/, '\n ').replace(/\n/g, '<br />') || ' ')
|
||||
}}
|
||||
/>
|
||||
<textarea
|
||||
onChange={this.setText}
|
||||
value={text}
|
||||
onMouseDown={this.blockMouse}
|
||||
onDragStart={this.blockMouse}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import { Router } from '$modules/Router';
|
|||
import { DEFAULT_LOGO } from '$constants/logos';
|
||||
|
||||
import { parseStickerAngle, parseStickerStyle } from '$utils/import';
|
||||
import { getUrlData, pushPath } from '$utils/history';
|
||||
import { getUrlData } from '$utils/history';
|
||||
import { store } from '$redux/store';
|
||||
import {
|
||||
resetSaveDialog,
|
||||
|
@ -236,6 +236,7 @@ export class Editor {
|
|||
latlng: sticker.latlng,
|
||||
angle: parseStickerAngle({ sticker, version }),
|
||||
sticker: parseStickerStyle({ sticker, version }),
|
||||
text: sticker.text,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,14 @@ import { DomMarker } from '$utils/DomMarker';
|
|||
|
||||
import { STICKERS } from '$constants/stickers';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { StickerDesc } from '$components/StickerDesc';
|
||||
import classnames from 'classnames';
|
||||
|
||||
export class Sticker {
|
||||
constructor({
|
||||
latlng, deleteSticker, map, lockMapClicks, sticker, triggerOnChange, angle = 2.2
|
||||
latlng, deleteSticker, map, lockMapClicks, sticker, triggerOnChange, angle = 2.2, text = '',
|
||||
}) {
|
||||
this.text = text;
|
||||
this.latlng = latlng;
|
||||
this.angle = angle;
|
||||
this.isDragging = false;
|
||||
|
@ -17,7 +20,7 @@ export class Sticker {
|
|||
this.sticker = sticker;
|
||||
this.editable = true;
|
||||
this.triggerOnChange = triggerOnChange;
|
||||
|
||||
this.direction = 'right';
|
||||
this.deleteSticker = deleteSticker;
|
||||
this.lockMapClicks = lockMapClicks;
|
||||
|
||||
|
@ -29,11 +32,12 @@ export class Sticker {
|
|||
ref={el => { this.stickerArrow = el; }}
|
||||
/>
|
||||
<div
|
||||
className="sticker-label"
|
||||
className={classnames('sticker-label', {})}
|
||||
ref={el => { this.stickerImage = el; }}
|
||||
onMouseDown={this.onDragStart}
|
||||
onMouseUp={this.onDragStop}
|
||||
>
|
||||
<StickerDesc value={this.text} onChange={this.setText} />
|
||||
{this.generateStickerSVG(sticker)}
|
||||
<div
|
||||
className="sticker-delete"
|
||||
|
@ -80,13 +84,16 @@ export class Sticker {
|
|||
this.triggerOnChange();
|
||||
}
|
||||
|
||||
setText = text => {
|
||||
this.text = text;
|
||||
};
|
||||
|
||||
onDelete = () => {
|
||||
this.triggerOnChange();
|
||||
if (!this.isDragging) this.deleteSticker(this);
|
||||
};
|
||||
|
||||
onDragStart = e => {
|
||||
console.log('drag start');
|
||||
this.preventPropagations(e);
|
||||
|
||||
this.isDragging = true;
|
||||
|
@ -132,13 +139,20 @@ export class Sticker {
|
|||
};
|
||||
|
||||
setAngle = angle => {
|
||||
const rad = 56;
|
||||
const mrad = 76;
|
||||
const x = ((Math.cos(angle + 3.14) * rad) - 30);
|
||||
const y = ((Math.sin(angle + 3.14) * rad) - 30);
|
||||
const direction = (angle > -(Math.PI / 2) && angle < (Math.PI / 2)) ? 'left' : 'right';
|
||||
|
||||
const ax = ((Math.cos(angle + 3.4) * mrad) - 12);
|
||||
const ay = ((Math.sin(angle + 3.4) * mrad) - 12);
|
||||
if (direction !== this.direction) {
|
||||
this.direction = direction;
|
||||
this.stickerImage.className = `sticker-label ${direction}`;
|
||||
}
|
||||
|
||||
const rad = 56;
|
||||
// const mrad = 76;
|
||||
const x = ((Math.cos(angle + Math.PI) * rad) - 30);
|
||||
const y = ((Math.sin(angle + Math.PI) * 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;
|
||||
|
@ -146,7 +160,7 @@ export class Sticker {
|
|||
// this.stickerDelete.style.left = ax;
|
||||
// this.stickerDelete.style.top = ay;
|
||||
|
||||
this.stickerArrow.style.transform = `rotate(${angle + 3.14}rad)`;
|
||||
this.stickerArrow.style.transform = `rotate(${angle + Math.PI}rad)`;
|
||||
};
|
||||
|
||||
generateStickerSVG = ({ set, sticker }) => (
|
||||
|
@ -163,6 +177,7 @@ export class Sticker {
|
|||
angle: this.angle,
|
||||
latlng: { ...this.marker.getLatLng() },
|
||||
sticker: this.sticker,
|
||||
text: this.text,
|
||||
});
|
||||
|
||||
stopEditing = () => {
|
||||
|
|
|
@ -20,7 +20,7 @@ export class Stickers {
|
|||
// this.createSticker({ latlng });
|
||||
// };
|
||||
|
||||
createSticker = ({ latlng, sticker, angle = 2.2 }) => {
|
||||
createSticker = ({ latlng, sticker, angle = 2.2, text = '' }) => {
|
||||
const marker = new Sticker({
|
||||
latlng,
|
||||
angle,
|
||||
|
@ -29,6 +29,7 @@ export class Stickers {
|
|||
lockMapClicks: this.lockMapClicks,
|
||||
sticker,
|
||||
triggerOnChange: this.triggerOnChange,
|
||||
text,
|
||||
});
|
||||
this.stickers.push(marker);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
position: absolute;
|
||||
border-radius: 40px;
|
||||
opacity: 0.25;
|
||||
transform: scale(0.6);
|
||||
transform: scale(0.5);
|
||||
transition: opacity 250ms, transform 500ms;
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@
|
|||
//}
|
||||
|
||||
svg {
|
||||
left: -12px;
|
||||
top: -12px;
|
||||
left: -8px;
|
||||
top: -8px;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
|
@ -78,12 +78,20 @@
|
|||
.sticker-image {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
left: -8px;
|
||||
top: -8px;
|
||||
left: -12px;
|
||||
top: -12px;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
&.left {
|
||||
.sticker-desc {
|
||||
padding: 10px 36px 10px 10px;
|
||||
left: auto;
|
||||
right: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sticker-arrow {
|
||||
|
@ -116,8 +124,8 @@
|
|||
transform: scale(1);
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
left: 42px;
|
||||
top: 0;
|
||||
left: 28px;
|
||||
top: -16px;
|
||||
z-index: 20;
|
||||
|
||||
&:hover {
|
||||
|
@ -151,3 +159,42 @@
|
|||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.sticker-desc {
|
||||
min-width: 60px;
|
||||
|
||||
height: auto;
|
||||
background: #222222;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 24px;
|
||||
transform: translate3d(0, -50%, 0);
|
||||
color: white;
|
||||
box-sizing: border-box;
|
||||
padding: 10px 10px 10px 36px;
|
||||
}
|
||||
|
||||
.sticker-desc-sizer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: rgba(0,0,0,0);
|
||||
white-space: nowrap;
|
||||
padding: 1px;
|
||||
|
||||
textarea {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font: inherit;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
color: white;
|
||||
resize: none;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue