diff --git a/src/components/save/CancelDialog.jsx b/src/components/dialogs/CancelDialog.jsx similarity index 100% rename from src/components/save/CancelDialog.jsx rename to src/components/dialogs/CancelDialog.jsx diff --git a/src/components/logo/LogoDialog.jsx b/src/components/dialogs/LogoDialog.jsx similarity index 100% rename from src/components/logo/LogoDialog.jsx rename to src/components/dialogs/LogoDialog.jsx diff --git a/src/components/dialogs/ProviderDialog.jsx b/src/components/dialogs/ProviderDialog.jsx new file mode 100644 index 0000000..1019dcc --- /dev/null +++ b/src/components/dialogs/ProviderDialog.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { PROVIDERS, replaceProviderUrl } from '$constants/providers'; +import { Icon } from '$components/panels/Icon'; +import classnames from 'classnames'; +import { MODES } from '$constants/modes'; + +type Props = { + setProvider: Function, + setMode: Function, + provider: String, +}; + +export class ProviderDialog extends React.Component { + closeDialog = () => this.props.setMode(MODES.NONE); + + render() { + const { provider, setProvider } = this.props; + + return ( + +
+ { + Object.keys(PROVIDERS).map(item => ( +
setProvider(item)} + key={PROVIDERS[item].name} + > + { + provider === item && +
+ +
+ } +
+ )) + } +
+
+
+ +
ВЫБЕРИТЕ СТИЛЬ КАРТЫ
+
+
+ +
+
+
+ ); + } +} diff --git a/src/components/router/RouterDialog.jsx b/src/components/dialogs/RouterDialog.jsx similarity index 100% rename from src/components/router/RouterDialog.jsx rename to src/components/dialogs/RouterDialog.jsx diff --git a/src/components/save/SaveDialog.jsx b/src/components/dialogs/SaveDialog.jsx similarity index 100% rename from src/components/save/SaveDialog.jsx rename to src/components/dialogs/SaveDialog.jsx diff --git a/src/components/stickers/StickersDialog.jsx b/src/components/dialogs/StickersDialog.jsx similarity index 100% rename from src/components/stickers/StickersDialog.jsx rename to src/components/dialogs/StickersDialog.jsx diff --git a/src/components/trash/TrashDialog.jsx b/src/components/dialogs/TrashDialog.jsx similarity index 100% rename from src/components/trash/TrashDialog.jsx rename to src/components/dialogs/TrashDialog.jsx diff --git a/src/components/panels/EditorDialog.jsx b/src/components/panels/EditorDialog.jsx index 8cb6263..88cdc8b 100644 --- a/src/components/panels/EditorDialog.jsx +++ b/src/components/panels/EditorDialog.jsx @@ -1,12 +1,12 @@ import React from 'react'; import { MODES } from '$constants/modes'; -import { RouterDialog } from '$components/router/RouterDialog'; -import { StickersDialog } from '$components/stickers/StickersDialog'; -import { TrashDialog } from '$components/trash/TrashDialog'; -import { LogoDialog } from '$components/logo/LogoDialog'; -import { SaveDialog } from '$components/save/SaveDialog'; -import { CancelDialog } from '$components/save/CancelDialog'; +import { RouterDialog } from '$components/dialogs/RouterDialog'; +import { StickersDialog } from '$components/dialogs/StickersDialog'; +import { TrashDialog } from '$components/dialogs/TrashDialog'; +import { LogoDialog } from '$components/dialogs/LogoDialog'; +import { SaveDialog } from '$components/dialogs/SaveDialog'; +import { CancelDialog } from '$components/dialogs/CancelDialog'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; @@ -24,7 +24,9 @@ import { stopEditing, setEditing, sendSaveRequest, + setProvider, } from '$redux/user/actions'; +import { ProviderDialog } from '$components/dialogs/ProviderDialog'; type Props = { mode: String, @@ -44,6 +46,7 @@ export const Component = (props: Props) => { || mode === MODES.LOGO || mode === MODES.SAVE || mode === MODES.CONFIRM_CANCEL + || mode === MODES.PROVIDER ); const dialogIsSmall = ( @@ -65,6 +68,7 @@ export const Component = (props: Props) => { { mode === MODES.LOGO && } { mode === MODES.SAVE && } { mode === MODES.CONFIRM_CANCEL && } + { mode === MODES.PROVIDER && } ); }; @@ -84,6 +88,7 @@ const mapDispatchToProps = dispatch => bindActionCreators({ setEditing, setMode, sendSaveRequest, + setProvider, }, dispatch); export const EditorDialog = connect( diff --git a/src/components/panels/EditorPanel.jsx b/src/components/panels/EditorPanel.jsx index e486ac5..adc0a94 100644 --- a/src/components/panels/EditorPanel.jsx +++ b/src/components/panels/EditorPanel.jsx @@ -45,7 +45,7 @@ class Component extends React.PureComponent { startPolyMode = () => this.props.setMode(MODES.POLY); startStickerMode = () => this.props.setMode(MODES.STICKERS); startRouterMode = () => this.props.setMode(MODES.ROUTER); - startShotterMode = () => this.props.setMode(MODES.SHOTTER); + startProviderMode = () => this.props.setMode(MODES.PROVIDER); startTrashMode = () => this.props.setMode(MODES.TRASH); startLogoMode = () => this.props.setMode(MODES.LOGO); startSaveMode = () => this.props.setMode(MODES.SAVE); @@ -111,7 +111,8 @@ class Component extends React.PureComponent { diff --git a/src/constants/providers.js b/src/constants/providers.js index c5b5927..964e7f2 100644 --- a/src/constants/providers.js +++ b/src/constants/providers.js @@ -1,56 +1,66 @@ // Стили карт +import { editor } from '$modules/Editor'; + const TILEMAPS = { WATERCOLOR: { name: 'Watercolor', url: 'http://stamen-tiles-{s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg', - range: [1, 4], + range: [1, 2, 3, 4], }, DGIS: { name: '2gis', url: 'https://tile1.maps.2gis.com/tiles?x={x}&y={y}&z={z}&v=1', - range: [1, 3], + range: [1, 2, 3], }, DEFAULT: { name: 'OpenStreetMap', url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - range: [1, 4], + range: ['a', 'b', 'c'], }, DARQ: { name: 'Darq', url: 'http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', - range: [1, 4], + range: [1, 2, 3, 4], }, BLANK: { name: 'Blanque', url: 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', - range: [1, 4], + range: [1, 2, 3, 4], }, HOT: { name: 'Hot', url: 'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', - range: [1, 4], + range: ['a', 'b', 'c'], }, - SAY: { - name: 'Google?', + SAT: { + name: 'Google Sattelite', url: 'http://mt{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', - range: [0, 3], + range: [0, 1, 2, 3], }, YMAP: { name: 'Yandex', url: 'https://vec0{s}.maps.yandex.net/tiles?l=map&v=17.04.16-0&x={x}&y={y}&z={z}&scale=1&lang=ru_RU', - range: [1, 4], + range: [1, 2, 3, 4], }, YSAT: { name: 'YandexSat', url: 'https://sat0{s}.maps.yandex.net/tiles?l=sat&v=3.330.0&x={x}&y={y}&z={z}&lang=ru_RU', - range: [1, 4], + range: [1, 2, 3, 4], }, }; -const ENABLED = ['BLANK', 'DEFAULT', 'DGIS']; +const ENABLED = ['BLANK', 'DEFAULT', 'DGIS', 'HOT']; export const DEFAULT_PROVIDER = ENABLED[0]; export const PROVIDERS = ENABLED.reduce((obj, provider) => ({ ...obj, [provider]: TILEMAPS[provider], }), {}); + +export const replaceProviderUrl = (provider, { x, y, zoom }) => { + console.log('got provider', provider); + const { url, range } = (PROVIDERS[provider] || PROVIDERS[DEFAULT_PROVIDER]); + const random = (range && range.length >= 2) ? range[Math.round((Math.random() * (range.length - 1)))] : 1; + + return url.replace('{x}', x).replace('{y}', y).replace('{z}', zoom).replace('{s}', random); +}; diff --git a/src/modules/Editor.js b/src/modules/Editor.js index f47ad06..a8992f8 100644 --- a/src/modules/Editor.js +++ b/src/modules/Editor.js @@ -72,6 +72,9 @@ export class Editor { }, [MODES.SAVE]: { stop: this.resetSaveDialog, + }, + [MODES.PROVIDER]: { + toggle: this.clearMode, } }; @@ -310,6 +313,8 @@ export class Editor { }); setProvider = provider => { + if (provider === this.provider) return; + this.provider = provider; this.map.setProvider(provider); }; diff --git a/src/redux/user/sagas.js b/src/redux/user/sagas.js index 7805726..771fc65 100644 --- a/src/redux/user/sagas.js +++ b/src/redux/user/sagas.js @@ -286,7 +286,9 @@ function* cropAShotSaga(params) { } function setProviderSaga({ provider }) { - editor.setProvider(provider); + return editor.setProvider(provider); + + // return put(setMode(MODES.NONE)) } export function* userSaga() { diff --git a/src/styles/panel.less b/src/styles/panel.less index 8d9bd33..cdcd240 100644 --- a/src/styles/panel.less +++ b/src/styles/panel.less @@ -220,10 +220,24 @@ .helper__buttons { display: flex; align-items: center; + user-select: none; .button { margin-left: 10px; } + + svg { + fill: white; + stroke: white; + + cursor: pointer; + opacity: 0.5; + transition: opacity 250ms; + } + + &:hover svg { + opacity: 1; + } } .logo-helper { @@ -270,3 +284,40 @@ } } +.provider-helper { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-column-gap: 10px; + grid-row-gap: 10px; + padding-bottom: 0; + + .provider-helper-thumb { + height: 100px; + background: #333333; + display: flex; + align-items: flex-end; + justify-content: center; + background: 50% 50% no-repeat; + border-radius: @panel_radius; + cursor: pointer; + position: relative; + } + + .provider-helper-check { + width: 40px; + height: 40px; + position: absolute; + bottom: 50%; + right: 50%; + background: rgba(0, 0, 0, 0.7); + border-radius: 20px; + transform: translate(50%, 50%); + + svg { + fill: white; + padding: 4px; + } + } +} + + diff --git a/src/utils/renderer.js b/src/utils/renderer.js index 8870335..c4a6761 100644 --- a/src/utils/renderer.js +++ b/src/utils/renderer.js @@ -1,7 +1,7 @@ import { editor } from '$modules/Editor'; import { COLORS, CONFIG } from '$config'; import saveAs from 'file-saver'; -import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers'; +import { DEFAULT_PROVIDER, PROVIDERS, replaceProviderUrl } from '$constants/providers'; const latLngToTile = latlng => { const { map } = editor.map; @@ -65,13 +65,6 @@ export const getPolyPlacement = () => ( : editor.poly.poly.getLatLngs().map((latlng) => ({ ...editor.map.map.latLngToContainerPoint(latlng) })) ); -const replaceProviderUrl = (provider, { x, y, zoom }) => { - const { url, range } = (PROVIDERS[editor.provider] || PROVIDERS[DEFAULT_PROVIDER]); - const random = (range && range.length >= 2) ? Math.round((Math.random() * (range[1] - range[0])) + range[0]) : 1; - - return url.replace('{x}', x).replace('{y}', y).replace('{z}', zoom).replace('{s}', random); -}; - const getImageSource = coords => replaceProviderUrl(editor.provider, coords); export const imageFetcher = source => new Promise((resolve, reject) => {