From 857a2a0c12ce4025e43d4ec90e3e5fec6bda063d Mon Sep 17 00:00:00 2001 From: muerwre Date: Wed, 28 Nov 2018 11:52:04 +0700 Subject: [PATCH] render: moved functions out of Renderer render: created reducer data structure --- src/components/renderer/Renderer.jsx | 92 +++------------------------- src/containers/App.jsx | 2 +- src/redux/user/reducer.js | 24 ++++++-- src/utils/renderer.js | 79 ++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 90 deletions(-) diff --git a/src/components/renderer/Renderer.jsx b/src/components/renderer/Renderer.jsx index 433304d..21cfff0 100644 --- a/src/components/renderer/Renderer.jsx +++ b/src/components/renderer/Renderer.jsx @@ -1,6 +1,5 @@ import React from 'react'; -import { getPolyPlacement, getTilePlacement } from '$utils/renderer'; -import { COLORS, CONFIG } from '$config'; +import { getPolyPlacement, getTilePlacement, composeImages, composePoly, fetchImages } from '$utils/renderer'; export class Renderer extends React.Component { componentDidMount() { @@ -11,92 +10,15 @@ export class Renderer extends React.Component { const ctx = this.canvas.getContext('2d'); const geometry = getTilePlacement(); const points = getPolyPlacement(); + ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - this.fetchImages(ctx, geometry) - .then(images => this.composeImages({ geometry, images, ctx })) - .then(() => this.composePoly({ geometry, points, ctx })) - .then(() => this.canvas.toDataURL('image/jpeg')) - .then(image => window.open().document.write(``)) + fetchImages(ctx, geometry) + .then(images => composeImages({ geometry, images, ctx })) + .then(() => composePoly({ points, ctx })) + .then(() => this.canvas.toDataURL('image/jpeg')); + // .then(image => window.open().document.write(``)) } - 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.crossOrigin = 'anonymous'; - 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) - shiftY; - - return ctx.drawImage(image, posX, posY, 256, 256); - }); - - return images; - }; - - composePoly = ({ points, geometry, ctx }) => { - let minX = points[0].x; - let maxX = points[0].x; - let minY = points[0].y; - let maxY = points[0].y; - - ctx.strokeStyle = 'red'; - ctx.strokeLinecap = 'round'; - ctx.strokeLinejoin = 'round'; - ctx.lineWidth = CONFIG.STROKE_WIDTH; - - ctx.beginPath(); - ctx.moveTo(points[0].x, points[0].y); - - for (let i = 1; i < points.length; i += 1) { - ctx.lineTo(points[i].x, points[i].y); - - // gradient bounds - if (points[i].x < minX) minX = points[i].x; - if (points[i].x > maxX) maxX = points[i].x; - if (points[i].y < minY) minY = points[i].y; - if (points[i].y > maxY) maxY = points[i].y; - } - - const gradient = ctx.createLinearGradient(minX, minY, minX, maxY); - gradient.addColorStop(0, COLORS.PATH_COLOR[0]); - gradient.addColorStop(1, COLORS.PATH_COLOR[1]); - - ctx.strokeStyle = gradient; - ctx.stroke(); - ctx.closePath(); - - return true; - }; - render() { return (
diff --git a/src/containers/App.jsx b/src/containers/App.jsx index f7ff756..e396fd6 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -32,7 +32,7 @@ const Component = (props: Props) => ( const mapStateToProps = ({ user }) => ({ - renderer_active: user.renderer_active + renderer_active: user.renderer.renderer_active }); const mapDispatchToProps = dispatch => bindActionCreators({ hideRenderer }, dispatch); export const App = connect(mapStateToProps, mapDispatchToProps)(hot(module)(Component)); diff --git a/src/redux/user/reducer.js b/src/redux/user/reducer.js index f647b41..7702c56 100644 --- a/src/redux/user/reducer.js +++ b/src/redux/user/reducer.js @@ -40,7 +40,11 @@ const setSaveError = (state, { save_error }) => ({ }); const setSaveOverwrite = state => ({ - ...state, save_overwriting: true, save_finished: false, save_processing: false, save_error: TIPS.SAVE_OVERWRITE, + ...state, + save_overwriting: true, + save_finished: false, + save_processing: false, + save_error: TIPS.SAVE_OVERWRITE, }); const setSaveSuccess = (state, { save_error }) => ({ @@ -51,8 +55,15 @@ 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 showRenderer = state => ({ + ...state, + renderer: { ...state.renderer, renderer_active: true } +}); + +const hideRenderer = state => ({ + ...state, + renderer: { ...state.renderer, renderer_active: false } +}); const HANDLERS = { [ACTIONS.SET_USER]: setUser, @@ -94,7 +105,12 @@ export const INITIAL_STATE = { save_overwriting: false, save_processing: false, - renderer_active: false + renderer: { + data: '', + width: 0, + height: 0, + renderer_active: false, + } }; export const userReducer = createReducer(INITIAL_STATE, HANDLERS); diff --git a/src/utils/renderer.js b/src/utils/renderer.js index 5b2b125..67c694f 100644 --- a/src/utils/renderer.js +++ b/src/utils/renderer.js @@ -1,4 +1,5 @@ import { editor } from '$modules/Editor'; +import { COLORS, CONFIG } from '$config'; const { map } = editor.map; map.addEventListener('mousedown', ({ latlng }) => console.log('CLICK', latlng)); @@ -61,3 +62,81 @@ export const getPolyPlacement = () => ( ? [] : editor.poly.poly.getLatLngs().map((latlng) => ({ ...map.latLngToContainerPoint(latlng) })) ); + +const getImageSource = ({ x, y, zoom }) => (`http://b.basemaps.cartocdn.com/light_all/${zoom}/${x}/${y}.png`); + +const imageFetcher = source => new Promise((resolve, reject) => { + const img = new Image(); + img.crossOrigin = 'anonymous'; + img.onload = () => resolve(img); + img.onerror = () => reject(img); + + img.src = source; +}); + +export const 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: getImageSource({ x, y, zoom }) }); + } + } + + return Promise.all(images.map(({ x, y, source }) => ( + imageFetcher(source).then(image => ({ x, y, image })) + ))); +}; + +export const 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) - shiftY; + + return ctx.drawImage(image, posX, posY, 256, 256); + }); + + return images; +}; + +export const composePoly = ({ points, ctx }) => { + let minX = points[0].x; + let maxX = points[0].x; + let minY = points[0].y; + let maxY = points[0].y; + + ctx.strokeStyle = 'red'; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.lineWidth = CONFIG.STROKE_WIDTH + 0.5; + + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + + for (let i = 1; i < points.length; i += 1) { + ctx.lineTo(points[i].x, points[i].y); + + // gradient bounds + if (points[i].x < minX) minX = points[i].x; + if (points[i].x > maxX) maxX = points[i].x; + if (points[i].y < minY) minY = points[i].y; + if (points[i].y > maxY) maxY = points[i].y; + } + + const gradient = ctx.createLinearGradient(minX, minY, minX, maxY); + gradient.addColorStop(0, COLORS.PATH_COLOR[0]); + gradient.addColorStop(1, COLORS.PATH_COLOR[1]); + + ctx.strokeStyle = gradient; + ctx.stroke(); + ctx.closePath(); + + return true; +};