From 4747c918e25785bcbb9f168b99ae37c5ac46797f Mon Sep 17 00:00:00 2001 From: muerwre Date: Tue, 27 Nov 2018 17:18:15 +0700 Subject: [PATCH] render: map composing (working) --- src/components/panels/EditorPanel.jsx | 8 +-- src/components/renderer/Renderer.jsx | 71 +++++++++++++++++++++++++++ src/containers/App.jsx | 19 +++++-- src/redux/user/actions.js | 2 + src/redux/user/constants.js | 3 ++ src/redux/user/reducer.js | 8 +++ src/styles/main.less | 1 + src/styles/renderer.less | 15 ++++++ src/utils/renderer.js | 2 +- 9 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 src/components/renderer/Renderer.jsx create mode 100644 src/styles/renderer.less diff --git a/src/components/panels/EditorPanel.jsx b/src/components/panels/EditorPanel.jsx index eecc5a4..6cf7ebb 100644 --- a/src/components/panels/EditorPanel.jsx +++ b/src/components/panels/EditorPanel.jsx @@ -9,7 +9,7 @@ import { EditorDialog } from '$components/panels/EditorDialog'; import { LogoPreview } from '$components/logo/LogoPreview'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import { setMode, startEditing, stopEditing, setLogo } from '$redux/user/actions'; +import { setMode, startEditing, stopEditing, setLogo, showRenderer } from '$redux/user/actions'; import type { UserType } from '$constants/types'; import { editor } from '$modules/Editor'; import { getTilePlacement } from '$utils/renderer'; @@ -31,6 +31,7 @@ type Props = { startEditing: Function, stopEditing: Function, setLogo: Function, + showRenderer: Function, } class Component extends React.PureComponent { @@ -108,8 +109,8 @@ class Component extends React.PureComponent { @@ -220,6 +221,7 @@ const mapDispatchToProps = dispatch => bindActionCreators({ setLogo, startEditing, stopEditing, + showRenderer, }, dispatch); export const EditorPanel = connect( diff --git a/src/components/renderer/Renderer.jsx b/src/components/renderer/Renderer.jsx new file mode 100644 index 0000000..88f24ab --- /dev/null +++ b/src/components/renderer/Renderer.jsx @@ -0,0 +1,71 @@ +import React from 'react'; +import { getTilePlacement } from '$utils/renderer'; + +export class Renderer extends React.Component { + componentDidMount() { + if (this.canvas) this.init(); + } + + init() { + const ctx = this.canvas.getContext('2d'); + const geometry = getTilePlacement(); + + this.fetchImages(ctx, geometry) + .then(images => this.composeImages({ geometry, images, ctx })); + + // myimage = new Image(); + // myimage.onload = function() { + // ctx.drawImage(myimage, x, y); + // } + // myimage.src = 'http://myserver/nextimage.cgi'; + } + + fetchImages = (ctx, geometry) => { + const { + minX, maxX, minY, maxY, zoom + } = geometry; + + const images = []; + for (let x = minX; x <= maxX; x += 1) { + for (let y = minY; y <= maxY; y += 1) { + images.push({ x, y, source: this.getImageSource({ x, y, zoom }) }); + } + } + + return Promise.all(images.map(({ x, y, source }) => ( + this.imageFetcher(source).then(image => ({ x, y, image })) + ))); + }; + + imageFetcher = source => new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = () => reject(img); + + img.src = source; + }); + + getImageSource = ({ x, y, zoom }) => (`http://b.basemaps.cartocdn.com/light_all/${zoom}/${x}/${y}.png`); + + composeImages = ({ images, geometry, ctx }) => { + const { + minX, minY, shiftX, shiftY, size + } = geometry; + + images.map(({ x, y, image }) => { + const posX = ((x - minX) * size) + shiftX; + const posY = ((y - minY) * size) + (window.innerHeight - shiftY - size); + + return ctx.drawImage(image, posX, posY, 256, 256); + }); + }; + + render() { + return ( +
+ { this.canvas = el; }} /> +
+ ); + } +} + diff --git a/src/containers/App.jsx b/src/containers/App.jsx index 87b3875..f7ff756 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -9,17 +9,30 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { hot } from 'react-hot-loader'; +import { Renderer } from '$components/renderer/Renderer'; +import { hideRenderer } from '$redux/user/actions'; -const Component = () => ( +type Props = { + renderer_active: Boolean, + hideRenderer: Function, +} + +const Component = (props: Props) => (
+ { + props.renderer_active && + + }
); -const mapStateToProps = () => ({}); -const mapDispatchToProps = dispatch => bindActionCreators({}, dispatch); +const mapStateToProps = ({ user }) => ({ + renderer_active: user.renderer_active +}); +const mapDispatchToProps = dispatch => bindActionCreators({ hideRenderer }, dispatch); export const App = connect(mapStateToProps, mapDispatchToProps)(hot(module)(Component)); diff --git a/src/redux/user/actions.js b/src/redux/user/actions.js index 4f3af93..2460942 100644 --- a/src/redux/user/actions.js +++ b/src/redux/user/actions.js @@ -32,3 +32,5 @@ export const setSaveSuccess = payload => ({ type: ACTIONS.SET_SAVE_SUCCESS, ...p export const setSaveError = save_error => ({ type: ACTIONS.SET_SAVE_ERROR, save_error }); export const setSaveOverwrite = () => ({ type: ACTIONS.SET_SAVE_OVERWRITE }); +export const showRenderer = () => ({ type: ACTIONS.SHOW_RENDERER }); +export const hideRenderer = () => ({ type: ACTIONS.HIDE_RENDERER }); diff --git a/src/redux/user/constants.js b/src/redux/user/constants.js index 45ac0ba..9180b5c 100644 --- a/src/redux/user/constants.js +++ b/src/redux/user/constants.js @@ -30,4 +30,7 @@ export const ACTIONS = { SET_SAVE_SUCCESS: 'SET_SAVE_SUCCESS', SET_SAVE_ERROR: 'SET_SAVE_ERROR', SET_SAVE_OVERWRITE: 'SET_SAVE_OVERWRITE', + + SHOW_RENDERER: 'SHOW_RENDERER', + HIDE_RENDERER: 'HIDE_RENDERER', }; diff --git a/src/redux/user/reducer.js b/src/redux/user/reducer.js index a084ca2..f647b41 100644 --- a/src/redux/user/reducer.js +++ b/src/redux/user/reducer.js @@ -51,6 +51,9 @@ const resetSaveDialog = state => ({ ...state, save_overwriting: false, save_finished: false, save_processing: false, save_error: '', }); +const showRenderer = state => ({ ...state, renderer_active: true }); +const hideRenderer = state => ({ ...state, renderer_active: false }); + const HANDLERS = { [ACTIONS.SET_USER]: setUser, [ACTIONS.SET_EDITING]: setEditing, @@ -68,6 +71,9 @@ const HANDLERS = { [ACTIONS.SET_SAVE_SUCCESS]: setSaveSuccess, [ACTIONS.SEND_SAVE_REQUEST]: sendSaveRequest, [ACTIONS.RESET_SAVE_DIALOG]: resetSaveDialog, + + [ACTIONS.SHOW_RENDERER]: showRenderer, + [ACTIONS.HIDE_RENDERER]: hideRenderer, }; export const INITIAL_STATE = { @@ -87,6 +93,8 @@ export const INITIAL_STATE = { save_finished: false, save_overwriting: false, save_processing: false, + + renderer_active: false }; export const userReducer = createReducer(INITIAL_STATE, HANDLERS); diff --git a/src/styles/main.less b/src/styles/main.less index dbb7f34..37b4127 100644 --- a/src/styles/main.less +++ b/src/styles/main.less @@ -8,6 +8,7 @@ @import 'logo.less'; @import 'user-button.less'; @import 'save.less'; +@import 'renderer.less'; body { font-family: 'Rubik', sans-serif; diff --git a/src/styles/renderer.less b/src/styles/renderer.less new file mode 100644 index 0000000..74ad47d --- /dev/null +++ b/src/styles/renderer.less @@ -0,0 +1,15 @@ +.renderer-shade { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + + background: rgba(0, 0, 0, 0.5); + + //canvas { + // width: 50vw; + // height: 50vh; + //} +} diff --git a/src/utils/renderer.js b/src/utils/renderer.js index d56c095..f44a888 100644 --- a/src/utils/renderer.js +++ b/src/utils/renderer.js @@ -55,7 +55,7 @@ export const getTilePlacement = () => { maxY, shiftX: (rsw.x - msw.x), - shiftY: (height + (rsw.y - msw.y)), + shiftY: (height + (rsw.y - msw.y)) + 3, size: 256, width,