From 3057bfd14db6784f5af754d46024f616f709f6be Mon Sep 17 00:00:00 2001 From: Franc Camps-Febrer Date: Wed, 19 Dec 2018 14:09:28 +0100 Subject: [PATCH] Streamline aligning layers --- src/components/Dashboard.jsx | 12 +- src/components/Map.jsx | 199 +++++++++++++++---------------- src/components/MapEvents.jsx | 32 ++--- src/components/MapNarratives.jsx | 5 +- src/components/MapSites.jsx | 1 + src/components/Viewport.jsx | 52 -------- 6 files changed, 111 insertions(+), 190 deletions(-) delete mode 100644 src/components/Viewport.jsx diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index 984ecac..34c4687 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -3,10 +3,8 @@ import React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import * as actions from '../actions'; -import * as selectors from '../selectors'; import LoadingOverlay from './presentational/LoadingOverlay'; -import Viewport from './Viewport.jsx'; import Map from './Map.jsx'; import Toolbar from './Toolbar.jsx'; import CardStack from './CardStack.jsx'; @@ -26,6 +24,7 @@ class Dashboard extends React.Component { this.handleSelectNarrative = this.handleSelectNarrative.bind(this); this.handleTagFilter = this.handleTagFilter.bind(this); this.updateTimerange = this.updateTimerange.bind(this); + this.getCategoryColor = this.getCategoryColor.bind(this); this.eventsById = {} } @@ -91,16 +90,9 @@ class Dashboard extends React.Component { methods={{ onSelect: this.handleSelect, onSelectNarrative: this.handleSelectNarrative, - getCategoryColor: category => this.getCategoryColor(category) + getCategoryColor: this.getCategoryColor, }} /> - {/* this.getCategoryColor(category) - }} - />*/} { - this.svg.classed('hide', true); - }); - this.state.map.on('zoomend', () => { - this.svg.classed('hide', false); - }); - - this.mapLogic = new MapLogic(this.state.map, this.svg, this.props.app, this.props.ui) - this.mapLogic.update(this.props.app) - - this.setState({ isInitialized: true }) - } - } - componentWillReceiveProps(nextProps) { if (hash(nextProps.app) !== hash(this.props.app)) { this.mapLogic.update(nextProps.app) } } - initializeMap() { /** * Creates a Leaflet map and a tilelayer for the map background @@ -93,21 +69,26 @@ class Map extends React.Component { map.keyboard.disable(); - map.on("move", () => this.updateSVG()); - map.on("zoomend viewreset moveend", () => this.updateSVG()); + map.on("move", () => this.alignLayers()); + map.on("zoomend viewreset moveend", () => this.alignLayers()); this.addResizeListener(); - this.setState({ map }); + this.mapLogic = new MapLogic(map, this.svgRef.current, this.props.app, this.props.ui); + this.mapLogic.update(this.props.app); + + this.map = map; + + this.setState({ isInitialized: true }); } addResizeListener() { window.addEventListener('resize', () => { - this.updateSVG(); + this.alignLayers(); }); } - getSVGBoundaries() { - const mapNode = d3.select('.leaflet-map-pane').node(); + alignLayers() { + const mapNode = document.querySelector('.leaflet-map-pane'); if (mapNode === null) return { transformX: 0, transformY: 0 }; // We'll get the transform of the leaflet container, @@ -116,94 +97,106 @@ class Map extends React.Component { .getComputedStyle(mapNode) .getPropertyValue('transform'); - // However getComputedStyle returns an awkward string of the format - // matrix(0, 0, 1, 0, 0.56523, 123123), hence this awkwardness + // Offset with leaflet map transform boundaries + this.setState({ + mapTransformX: +transform.split(',')[4], + mapTransformY: +transform.split(',')[5].split(')')[0] + }) + } + + getClientDims() { + const boundingClient = document.querySelector(`#${this.props.mapId}`).getBoundingClientRect(); + return { - transformX: +transform.split(',')[4], - transformY: +transform.split(',')[5].split(')')[0] + width: boundingClient.width, + height: boundingClient.height } } - updateSVG() { - const boundingClient = d3.select(`#${this.props.mapId}`).node().getBoundingClientRect(); + renderSVG() { + if (this.map === null) return ''; + const pane = this.map.getPanes().overlayPane; + const { width, height } = this.getClientDims(); - let WIDTH = boundingClient.width; - let HEIGHT = boundingClient.height; - - // Offset with leaflet map transform boundaries - const { transformX, transformY } = this.getSVGBoundaries(); - - this.setState({ - mapTransformX: transformX, - mapTransformY: transformY - }) - - this.svg.attr('width', WIDTH) - .attr('height', HEIGHT) - .attr('style', `left: ${-transformX}px; top: ${-transformY}px`); + return ( + + + + + ); } renderSites() { - if (this.state.isInitialized) { - return ( - - ); - } - return ''; + return ( + + ); } renderNarratives() { - if (this.state.isInitialized) { - return ( - - ); - } - return ''; + return ( + + ); } renderEvents() { - if (this.state.isInitialized) { - return ( - - ); - } - return ''; + return ( + + ); + } + + renderMarkers() { + return ( + + + + ) } render() { const classes = this.props.app.narrative ? 'map-wrapper narrative-mode' : 'map-wrapper'; + return (
- {this.renderSites()} - {this.renderEvents()} - {this.renderNarratives()} + {this.renderSVG()} + {(this.state.isInitialized) ? this.renderMarkers() : ''} + {(this.state.isInitialized) ? this.renderSites() : ''} + {(this.state.isInitialized) ? this.renderEvents() : ''} + {(this.state.isInitialized) ? this.renderNarratives() : ''}
); } diff --git a/src/components/MapEvents.jsx b/src/components/MapEvents.jsx index eff4653..84cf6c4 100644 --- a/src/components/MapEvents.jsx +++ b/src/components/MapEvents.jsx @@ -16,33 +16,22 @@ class MapEvents extends React.Component { const categories = this.props.categories; categories.forEach(cat => { - eventCount[cat.category] = 0 + eventCount[cat.category] = []; }); location.events.forEach((event) => {; - eventCount[event.category] += 1; + eventCount[event.category].push(event); }); - let i = 0; - const events = []; - - while (i < categories.length) { - let _eventsCount = eventCount[categories[i].category]; - for (let j = i + 1; j < categories.length; j++) { - _eventsCount += eventCount[categories[j].category]; - } - events.push(_eventsCount); - i++; - } - return events; + return eventCount; } - renderCategory(counts, events) { + renderCategory(events, category) { return ( this.props.onSelect(events)} > @@ -51,22 +40,23 @@ class MapEvents extends React.Component { renderLocation(location) { const { x, y } = this.projectPoint([location.latitude, location.longitude]); - const eventsCounts = this.getLocationEventsDistribution(location); + const eventsByCategory = this.getLocationEventsDistribution(location); return ( - {eventsCounts.map(eventsCount => this.renderCategory(eventsCount, location.events))} + {Object.keys(eventsByCategory).map(cat => { + return this.renderCategory(eventsByCategory[cat], cat) + })} ) } render() { - return ( - + {this.props.locations.map(loc => this.renderLocation(loc))} ); diff --git a/src/components/MapNarratives.jsx b/src/components/MapNarratives.jsx index aeefc3c..666df0e 100644 --- a/src/components/MapNarratives.jsx +++ b/src/components/MapNarratives.jsx @@ -1,8 +1,6 @@ import React from 'react'; import { Portal } from 'react-portal'; -import MapDefsMarkers from './MapDefsMarkers.jsx'; - class MapNarratives extends React.Component { projectPoint(location) { @@ -81,10 +79,9 @@ class MapNarratives extends React.Component { render() { if (this.props.narrative === null) return (
); - /**/ return ( - + {this.props.narratives.map(n => this.renderNarrative(n))} ); diff --git a/src/components/MapSites.jsx b/src/components/MapSites.jsx index 8fdcd28..16d4a92 100644 --- a/src/components/MapSites.jsx +++ b/src/components/MapSites.jsx @@ -23,6 +23,7 @@ class MapSites extends React.Component { render () { if (!this.props.sites || !this.props.sites.length) return
; + return (
{this.props.sites.map(site => { return this.renderSite(site); })} diff --git a/src/components/Viewport.jsx b/src/components/Viewport.jsx deleted file mode 100644 index 55673b0..0000000 --- a/src/components/Viewport.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react' -import { connect } from 'react-redux' -import * as selectors from '../selectors' -import hash from 'object-hash'; - -import Map from './Map.jsx'; -import { areEqual } from '../js/utilities.js' - -class Viewport extends React.Component { - constructor(props) { - super(props) - } - - render() { - const classes = this.props.app.narrative ? 'map-wrapper narrative-mode' : 'map-wrapper'; - return ( -
- -
- ) - } -} - -function mapStateToProps(state) { - return { - domain: { - locations: selectors.selectLocations(state), - narratives: selectors.selectNarratives(state), - categories: selectors.selectCategories(state), - sites: selectors.getSites(state) - }, - app: { - views: state.app.filters.views, - selected: state.app.selected, - highlighted: state.app.highlighted, - mapAnchor: state.app.mapAnchor, - narrative: state.app.narrative - }, - ui: { - dom: state.ui.dom, - narratives: state.ui.style.narratives - } - } -} - -export default connect(mapStateToProps)(Viewport)