mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 19:16:41 +07:00
stickers: text editing
This commit is contained in:
parent
fa9bff5756
commit
f183c8593d
6 changed files with 130 additions and 21 deletions
|
@ -9,7 +9,7 @@ module.exports.parseRoute = route => route.filter(el => (
|
||||||
));
|
));
|
||||||
|
|
||||||
module.exports.parseStickers = stickers => stickers.filter(el => (
|
module.exports.parseStickers = stickers => stickers.filter(el => (
|
||||||
Object.keys(el).length === 3
|
Object.keys(el).length === 4
|
||||||
&& el.latlng
|
&& el.latlng
|
||||||
&& Object.keys(el.latlng).length === 2
|
&& Object.keys(el.latlng).length === 2
|
||||||
&& el.latlng.lat
|
&& el.latlng.lat
|
||||||
|
@ -19,6 +19,7 @@ module.exports.parseStickers = stickers => stickers.filter(el => (
|
||||||
&& parseInt(el.latlng.lng, 10) > 0
|
&& parseInt(el.latlng.lng, 10) > 0
|
||||||
&& parseInt(el.latlng.lng, 10) < 1000
|
&& parseInt(el.latlng.lng, 10) < 1000
|
||||||
));
|
));
|
||||||
|
// .map(el => ((el.text && String(el.text).substr(0, 100)) || ''));
|
||||||
|
|
||||||
module.exports.parseString = (value, size) => (value && String(value).substr(0, size)) || '';
|
module.exports.parseString = (value, size) => (value && String(value).substr(0, size)) || '';
|
||||||
module.exports.parseNumber = (value, min, max) => (value && Number(value) && Math.min(max, Math.max(min, value))) || 0;
|
module.exports.parseNumber = (value, min, max) => (value && Number(value) && Math.min(max, Math.max(min, value))) || 0;
|
||||||
|
|
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 { DEFAULT_LOGO } from '$constants/logos';
|
||||||
|
|
||||||
import { parseStickerAngle, parseStickerStyle } from '$utils/import';
|
import { parseStickerAngle, parseStickerStyle } from '$utils/import';
|
||||||
import { getUrlData, pushPath } from '$utils/history';
|
import { getUrlData } from '$utils/history';
|
||||||
import { store } from '$redux/store';
|
import { store } from '$redux/store';
|
||||||
import {
|
import {
|
||||||
resetSaveDialog,
|
resetSaveDialog,
|
||||||
|
@ -236,6 +236,7 @@ export class Editor {
|
||||||
latlng: sticker.latlng,
|
latlng: sticker.latlng,
|
||||||
angle: parseStickerAngle({ sticker, version }),
|
angle: parseStickerAngle({ sticker, version }),
|
||||||
sticker: parseStickerStyle({ sticker, version }),
|
sticker: parseStickerStyle({ sticker, version }),
|
||||||
|
text: sticker.text,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,14 @@ import { DomMarker } from '$utils/DomMarker';
|
||||||
|
|
||||||
import { STICKERS } from '$constants/stickers';
|
import { STICKERS } from '$constants/stickers';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import { StickerDesc } from '$components/StickerDesc';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
export class Sticker {
|
export class Sticker {
|
||||||
constructor({
|
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.latlng = latlng;
|
||||||
this.angle = angle;
|
this.angle = angle;
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
|
@ -17,7 +20,7 @@ export class Sticker {
|
||||||
this.sticker = sticker;
|
this.sticker = sticker;
|
||||||
this.editable = true;
|
this.editable = true;
|
||||||
this.triggerOnChange = triggerOnChange;
|
this.triggerOnChange = triggerOnChange;
|
||||||
|
this.direction = 'right';
|
||||||
this.deleteSticker = deleteSticker;
|
this.deleteSticker = deleteSticker;
|
||||||
this.lockMapClicks = lockMapClicks;
|
this.lockMapClicks = lockMapClicks;
|
||||||
|
|
||||||
|
@ -29,11 +32,12 @@ export class Sticker {
|
||||||
ref={el => { this.stickerArrow = el; }}
|
ref={el => { this.stickerArrow = el; }}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="sticker-label"
|
className={classnames('sticker-label', {})}
|
||||||
ref={el => { this.stickerImage = el; }}
|
ref={el => { this.stickerImage = el; }}
|
||||||
onMouseDown={this.onDragStart}
|
onMouseDown={this.onDragStart}
|
||||||
onMouseUp={this.onDragStop}
|
onMouseUp={this.onDragStop}
|
||||||
>
|
>
|
||||||
|
<StickerDesc value={this.text} onChange={this.setText} />
|
||||||
{this.generateStickerSVG(sticker)}
|
{this.generateStickerSVG(sticker)}
|
||||||
<div
|
<div
|
||||||
className="sticker-delete"
|
className="sticker-delete"
|
||||||
|
@ -80,13 +84,16 @@ export class Sticker {
|
||||||
this.triggerOnChange();
|
this.triggerOnChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setText = text => {
|
||||||
|
this.text = text;
|
||||||
|
};
|
||||||
|
|
||||||
onDelete = () => {
|
onDelete = () => {
|
||||||
this.triggerOnChange();
|
this.triggerOnChange();
|
||||||
if (!this.isDragging) this.deleteSticker(this);
|
if (!this.isDragging) this.deleteSticker(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
onDragStart = e => {
|
onDragStart = e => {
|
||||||
console.log('drag start');
|
|
||||||
this.preventPropagations(e);
|
this.preventPropagations(e);
|
||||||
|
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
@ -132,13 +139,20 @@ export class Sticker {
|
||||||
};
|
};
|
||||||
|
|
||||||
setAngle = angle => {
|
setAngle = angle => {
|
||||||
const rad = 56;
|
const direction = (angle > -(Math.PI / 2) && angle < (Math.PI / 2)) ? 'left' : 'right';
|
||||||
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);
|
if (direction !== this.direction) {
|
||||||
const ay = ((Math.sin(angle + 3.4) * mrad) - 12);
|
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.left = 6 + x;
|
||||||
this.stickerImage.style.top = 6 + y;
|
this.stickerImage.style.top = 6 + y;
|
||||||
|
@ -146,7 +160,7 @@ export class Sticker {
|
||||||
// this.stickerDelete.style.left = ax;
|
// this.stickerDelete.style.left = ax;
|
||||||
// this.stickerDelete.style.top = ay;
|
// 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 }) => (
|
generateStickerSVG = ({ set, sticker }) => (
|
||||||
|
@ -163,6 +177,7 @@ export class Sticker {
|
||||||
angle: this.angle,
|
angle: this.angle,
|
||||||
latlng: { ...this.marker.getLatLng() },
|
latlng: { ...this.marker.getLatLng() },
|
||||||
sticker: this.sticker,
|
sticker: this.sticker,
|
||||||
|
text: this.text,
|
||||||
});
|
});
|
||||||
|
|
||||||
stopEditing = () => {
|
stopEditing = () => {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class Stickers {
|
||||||
// this.createSticker({ latlng });
|
// this.createSticker({ latlng });
|
||||||
// };
|
// };
|
||||||
|
|
||||||
createSticker = ({ latlng, sticker, angle = 2.2 }) => {
|
createSticker = ({ latlng, sticker, angle = 2.2, text = '' }) => {
|
||||||
const marker = new Sticker({
|
const marker = new Sticker({
|
||||||
latlng,
|
latlng,
|
||||||
angle,
|
angle,
|
||||||
|
@ -29,6 +29,7 @@ export class Stickers {
|
||||||
lockMapClicks: this.lockMapClicks,
|
lockMapClicks: this.lockMapClicks,
|
||||||
sticker,
|
sticker,
|
||||||
triggerOnChange: this.triggerOnChange,
|
triggerOnChange: this.triggerOnChange,
|
||||||
|
text,
|
||||||
});
|
});
|
||||||
this.stickers.push(marker);
|
this.stickers.push(marker);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 40px;
|
border-radius: 40px;
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
transform: scale(0.6);
|
transform: scale(0.5);
|
||||||
transition: opacity 250ms, transform 500ms;
|
transition: opacity 250ms, transform 500ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@
|
||||||
//}
|
//}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
left: -12px;
|
left: -8px;
|
||||||
top: -12px;
|
top: -8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,20 @@
|
||||||
.sticker-image {
|
.sticker-image {
|
||||||
width: 72px;
|
width: 72px;
|
||||||
height: 72px;
|
height: 72px;
|
||||||
left: -8px;
|
left: -12px;
|
||||||
top: -8px;
|
top: -12px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
.sticker-desc {
|
||||||
|
padding: 10px 36px 10px 10px;
|
||||||
|
left: auto;
|
||||||
|
right: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticker-arrow {
|
.sticker-arrow {
|
||||||
|
@ -116,8 +124,8 @@
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
left: 42px;
|
left: 28px;
|
||||||
top: 0;
|
top: -16px;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -151,3 +159,42 @@
|
||||||
z-index: 2;
|
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