mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 21:38:35 +03:00
Make timeline controls plain svg
This commit is contained in:
@@ -6,18 +6,21 @@ import hash from 'object-hash';
|
||||
import copy from '../js/data/copy.json';
|
||||
import { formatterWithYear, isNotNullNorUndefined } from '../js/utilities';
|
||||
import TimelineHeader from './presentational/TimelineHeader';
|
||||
import TimelineHandles from './TimelineHandles.jsx';
|
||||
import TimelineLogic from '../js/timeline/timeline.js';
|
||||
|
||||
|
||||
class Timeline extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.svgRef = React.createRef()
|
||||
this.state = {
|
||||
isFolded: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.timeline = new TimelineLogic(this.props.app, this.props.ui, this.props.methods);
|
||||
this.timeline = new TimelineLogic(this.svgRef.current, this.props.app, this.props.ui, this.props.methods);
|
||||
this.timeline.update(this.props.domain, this.props.app);
|
||||
}
|
||||
|
||||
@@ -33,6 +36,48 @@ class Timeline extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getClientDims() {
|
||||
const WIDTH_CONTROLS = 100;
|
||||
const HEIGHT = 140;
|
||||
let WIDTH = 0;
|
||||
|
||||
if (document.querySelector(`#${this.props.ui.dom.timeline}`) !== null) {
|
||||
const boundingClient = document.querySelector(`#${this.props.ui.dom.timeline}`).getBoundingClientRect();
|
||||
WIDTH = boundingClient.width - WIDTH_CONTROLS;
|
||||
}
|
||||
return {
|
||||
height: HEIGHT,
|
||||
width: WIDTH,
|
||||
width_controls: WIDTH_CONTROLS,
|
||||
height_controls: 115,
|
||||
margin_left: 120
|
||||
}
|
||||
}
|
||||
|
||||
onMoveTime(dir) {
|
||||
if (this.timeline) {
|
||||
return this.timeline.moveTime(dir);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
renderSVG() {
|
||||
const { width, height, margin_left } = this.getClientDims();
|
||||
|
||||
return (
|
||||
<svg
|
||||
ref={this.svgRef}
|
||||
width={width}
|
||||
height={height}
|
||||
>
|
||||
<clipPath id="clip">
|
||||
<rect x="120" y="0" width={width - margin_left} height={height - 25}></rect>
|
||||
</clipPath>
|
||||
<TimelineHandles dims={this.getClientDims()} onMoveTime={(dir) => { this.onMoveTime(dir) }} />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isNarrative, app, ui } = this.props
|
||||
let classes = `timeline-wrapper ${(this.state.isFolded) ? ' folded' : ''}`;
|
||||
@@ -47,7 +92,9 @@ class Timeline extends React.Component {
|
||||
hideInfo={isNarrative}
|
||||
/>
|
||||
<div className="timeline-content">
|
||||
<div id={ui.dom.timeline} className="timeline" />
|
||||
<div id={this.props.ui.dom.timeline} className="timeline">
|
||||
{this.renderSVG()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
25
src/components/TimelineHandles.jsx
Normal file
25
src/components/TimelineHandles.jsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
|
||||
class TimelineHandles extends React.Component {
|
||||
|
||||
render() {
|
||||
const dims = this.props.dims;
|
||||
return (
|
||||
<g className="time-controls-inline">
|
||||
<g transform={`translate(${dims.margin_left + 20}, 62)`} onClick={() => this.props.onMoveTime('backwards')}>
|
||||
<circle r="15">
|
||||
</circle>
|
||||
<path d="M0,-7.847549217020565L6.796176979388489,3.9237746085102825L-6.796176979388489,3.9237746085102825Z" transform="rotate(270)"></path>
|
||||
</g>
|
||||
<g transform={`translate(${dims.width - 20}, 62)`} onClick={() => this.props.onMoveTime('forward')}>
|
||||
<circle r="15">
|
||||
</circle>
|
||||
<path d="M0,-7.847549217020565L6.796176979388489,3.9237746085102825L-6.796176979388489,3.9237746085102825Z" transform="rotate(90)"></path>
|
||||
</g>
|
||||
</g>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TimelineHandles;
|
||||
@@ -13,7 +13,7 @@ import hash from 'object-hash';
|
||||
import esLocale from '../data/es-MX.json';
|
||||
import copy from '../data/copy.json';
|
||||
|
||||
export default function(newApp, ui, methods) {
|
||||
export default function(svg, newApp, ui, methods) {
|
||||
d3.timeFormatDefaultLocale(esLocale);
|
||||
|
||||
const domain = {
|
||||
@@ -60,27 +60,27 @@ export default function(newApp, ui, methods) {
|
||||
* Initilize SVG elements and groups
|
||||
*/
|
||||
const dom = {};
|
||||
console.log(svg)
|
||||
dom.svg = d3.select(svg)
|
||||
//d3.select(`#${ui.dom.timeline}`)
|
||||
//.append('svg')
|
||||
//.attr('width', WIDTH)
|
||||
//.attr('height', HEIGHT);
|
||||
|
||||
dom.svg =
|
||||
d3.select(`#${ui.dom.timeline}`)
|
||||
.append('svg')
|
||||
.attr('width', WIDTH)
|
||||
.attr('height', HEIGHT);
|
||||
// dom.clip = dom.svg.append("svg:clipPath")
|
||||
// .attr("id", "clip")
|
||||
// .append("svg:rect")
|
||||
// .attr("x", margin.left)
|
||||
// .attr("y", 0)
|
||||
// .attr("width", WIDTH - margin.left)
|
||||
// .attr("height", HEIGHT - 25);
|
||||
|
||||
dom.clip = dom.svg.append("svg:clipPath")
|
||||
.attr("id", "clip")
|
||||
.append("svg:rect")
|
||||
.attr("x", margin.left)
|
||||
.attr("y", 0)
|
||||
.attr("width", WIDTH - margin.left)
|
||||
.attr("height", HEIGHT - 25);
|
||||
|
||||
dom.controls =
|
||||
d3.select(`#${ui.dom.timeline}`)
|
||||
.append('svg')
|
||||
.attr('class', 'time-controls')
|
||||
.attr('width', WIDTH_CONTROLS)
|
||||
.attr('height', HEIGHT);
|
||||
dom.controls = d3.select(svg)
|
||||
//d3.select(`#${ui.dom.timeline}`)
|
||||
//.append('svg')
|
||||
//.attr('class', 'time-controls')
|
||||
//.attr('width', WIDTH_CONTROLS)
|
||||
//.attr('height', HEIGHT);
|
||||
|
||||
|
||||
/*
|
||||
@@ -124,13 +124,13 @@ export default function(newApp, ui, methods) {
|
||||
/*
|
||||
* Time Controls
|
||||
*/
|
||||
dom.forward = dom.svg.append('g').attr('class', 'time-controls-inline');
|
||||
dom.forward.append('circle');
|
||||
dom.forward.append('path');
|
||||
|
||||
dom.backwards = dom.svg.append('g').attr('class', 'time-controls-inline');
|
||||
dom.backwards.append('circle');
|
||||
dom.backwards.append('path');
|
||||
// dom.forward = dom.svg.append('g').attr('class', 'time-controls-inline');
|
||||
// dom.forward.append('circle');
|
||||
// dom.forward.append('path');
|
||||
//
|
||||
// dom.backwards = dom.svg.append('g').attr('class', 'time-controls-inline');
|
||||
// dom.backwards.append('circle');
|
||||
// dom.backwards.append('path');
|
||||
|
||||
dom.zooms = dom.controls.append('g');
|
||||
|
||||
@@ -491,21 +491,21 @@ export default function(newApp, ui, methods) {
|
||||
});
|
||||
|
||||
// These controls on timeline svg
|
||||
dom.backwards.select('circle')
|
||||
.attr('transform', `translate(${scale.x.range()[0] + 20}, 62)`)
|
||||
.attr('r', 15);
|
||||
|
||||
dom.backwards.select('path')
|
||||
.attr('d', d3.symbol().type(d3.symbolTriangle).size(80))
|
||||
.attr('transform', `translate(${scale.x.range()[0] + 20}, 62)rotate(270)`);
|
||||
|
||||
dom.forward.select('circle')
|
||||
.attr('transform', `translate(${scale.x.range()[1] - 20}, 62)`)
|
||||
.attr('r', 15);
|
||||
|
||||
dom.forward.select('path')
|
||||
.attr('d', d3.symbol().type(d3.symbolTriangle).size(80))
|
||||
.attr('transform', `translate(${scale.x.range()[1] - 20}, 62)rotate(90)`);
|
||||
// dom.backwards.select('circle')
|
||||
// .attr('transform', `translate(${scale.x.range()[0] + 20}, 62)`)
|
||||
// .attr('r', 15);
|
||||
//
|
||||
// dom.backwards.select('path')
|
||||
// .attr('d', d3.symbol().type(d3.symbolTriangle).size(80))
|
||||
// .attr('transform', `translate(${scale.x.range()[0] + 20}, 62)rotate(270)`);
|
||||
//
|
||||
// dom.forward.select('circle')
|
||||
// .attr('transform', `translate(${scale.x.range()[1] - 20}, 62)`)
|
||||
// .attr('r', 15);
|
||||
//
|
||||
// dom.forward.select('path')
|
||||
// .attr('d', d3.symbol().type(d3.symbolTriangle).size(80))
|
||||
// .attr('transform', `translate(${scale.x.range()[1] - 20}, 62)rotate(90)`);
|
||||
|
||||
dom.zooms.selectAll('text')
|
||||
.text(d => d.label)
|
||||
@@ -513,12 +513,6 @@ export default function(newApp, ui, methods) {
|
||||
.attr('y', (d, i) => (i * 15) + 20)
|
||||
.classed('active', level => level.active);
|
||||
|
||||
dom.forward
|
||||
.on('click', () => moveTime('forward'));
|
||||
|
||||
dom.backwards
|
||||
.on('click', () => moveTime('backwards'));
|
||||
|
||||
dom.zooms.selectAll('text')
|
||||
.on('click', zoom => applyZoom(zoom));
|
||||
}
|
||||
@@ -589,6 +583,7 @@ export default function(newApp, ui, methods) {
|
||||
}
|
||||
|
||||
return {
|
||||
moveTime,
|
||||
update,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user