Add sidebar to view pixel colors on hover.
This commit is contained in:
15
src/App.css
15
src/App.css
@@ -1,9 +1,3 @@
|
||||
html, body, #root {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -14,3 +8,12 @@ html, body, #root {
|
||||
text-shadow: 0 0 4px #000, 0 0 8px #000 ;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.value {
|
||||
text-align: center;
|
||||
border: 1px solid #888;
|
||||
}
|
||||
|
||||
138
src/App.js
138
src/App.js
@@ -1,8 +1,69 @@
|
||||
import React from 'react';
|
||||
import './App.css';
|
||||
import {
|
||||
Columns,
|
||||
Heading,
|
||||
Media,
|
||||
} from 'react-bulma-components';
|
||||
|
||||
|
||||
const ROOT = process.env.PUBLIC_URL + '/tracer/';
|
||||
const DATA_URL = ROOT + 'data.json';
|
||||
const MAX_ZOOM_FACTOR = 32;
|
||||
|
||||
const Sidebar = (props) => {
|
||||
let {binary, imageMetadata, zoomFactor, x, y, onZoom} = props;
|
||||
let samples = imageMetadata.map((md) => {
|
||||
let pix = binary[md.name];
|
||||
if (pix === undefined) { return <p key={md.name}>Loading...</p>; }
|
||||
let [w, h] = md.size;
|
||||
let xOff = Math.min(w, Math.max(0, Math.round(x*w)));
|
||||
let yOff = Math.min(h, Math.max(0, Math.round(y*h)));
|
||||
let v = pix[xOff+yOff*w];
|
||||
if (v === undefined) {
|
||||
console.log(`${x} ${y} ${w} ${h} ${xOff} ${yOff} ${v} ${pix.length}`);
|
||||
return <p key={md.name}>Loading...</p>;
|
||||
}
|
||||
let rgb = "";
|
||||
let value = "";
|
||||
if (md.format === "RGB01") {
|
||||
let r = Math.round(v[0]*255);
|
||||
let g = Math.round(v[1]*255);
|
||||
let b = Math.round(v[2]*255);
|
||||
rgb = `rgb(${r}, ${g}, ${b})`;
|
||||
value = rgb;
|
||||
} else {
|
||||
rgb = `rgb(${v}, ${v}, ${v})`;
|
||||
value = v;
|
||||
}
|
||||
return <div className="sample" key={md.name}>
|
||||
<p>{md.name}</p>
|
||||
<p className="value" style={{backgroundColor: rgb}}>{value}</p>
|
||||
</div>
|
||||
});
|
||||
return <aside className="menu">
|
||||
<p className="menu-label">
|
||||
Controls
|
||||
</p>
|
||||
<ul className="menu-list">
|
||||
<li>
|
||||
<p>Zoom:</p>
|
||||
<input
|
||||
id="zoom"
|
||||
type="range"
|
||||
min="1" max={MAX_ZOOM_FACTOR}
|
||||
value={zoomFactor}
|
||||
onChange={onZoom}
|
||||
step="0.1"/>
|
||||
<p className="value">{Math.round(zoomFactor*100)/100}x</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p className="menu-label">
|
||||
Samples
|
||||
</p>
|
||||
{samples}
|
||||
</aside>;
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -13,7 +74,7 @@ class App extends React.Component {
|
||||
isFetching: false,
|
||||
isFrozen: false,
|
||||
isZoomed: false,
|
||||
zoomFactor: 16,
|
||||
zoomFactor: 4,
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
@@ -34,15 +95,15 @@ class App extends React.Component {
|
||||
if ((data === null) ||
|
||||
(data.timestamp !== result.timestamp)) {
|
||||
this.setState({data: result, isFetching: false});
|
||||
result.image_metadatum.forEach((md) => {
|
||||
let binary_url = ROOT + md.binary;
|
||||
fetch(binary_url)
|
||||
result.imageMetadata.forEach((md) => {
|
||||
let binaryUrl = ROOT + md.binary;
|
||||
fetch(binaryUrl)
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
let cur_binary = this.state.binary;
|
||||
let curBinary = this.state.binary;
|
||||
this.setState({binary: {
|
||||
[md.name]: result,
|
||||
...cur_binary
|
||||
...curBinary
|
||||
}});
|
||||
})
|
||||
.catch(e => console.log(e));
|
||||
@@ -54,9 +115,9 @@ class App extends React.Component {
|
||||
.catch(e => console.log(e));
|
||||
}
|
||||
render() {
|
||||
console.log(this.state.binary);
|
||||
let imgs = [];
|
||||
let images = [];
|
||||
let {
|
||||
binary,
|
||||
data,
|
||||
isFrozen,
|
||||
isZoomed,
|
||||
@@ -64,9 +125,10 @@ class App extends React.Component {
|
||||
y,
|
||||
zoomFactor,
|
||||
} = this.state;
|
||||
let appContent = <h1>Loading</h1>;
|
||||
let mainContent = <h1>Loading</h1>;
|
||||
let sidebarContent = <h1>Loading</h1>;
|
||||
if (data !== null) {
|
||||
let {timestamp, image_metadatum} = data;
|
||||
let {timestamp, imageMetadata} = data;
|
||||
const mouseClick = (e) => {
|
||||
console.log('isFrozen', isFrozen, 'this.state.isFrozen', this.state.isFrozen);
|
||||
this.setState({isFrozen: !this.state.isFrozen});
|
||||
@@ -81,7 +143,9 @@ class App extends React.Component {
|
||||
let delta = parseFloat(-e.deltaY/100.0);
|
||||
let zoomFactor = delta + this.state.zoomFactor;
|
||||
if (zoomFactor < 1) { zoomFactor = 1; }
|
||||
if (zoomFactor > 24) { zoomFactor = 24; }
|
||||
if (zoomFactor > MAX_ZOOM_FACTOR) {
|
||||
zoomFactor = MAX_ZOOM_FACTOR;
|
||||
}
|
||||
this.setState({
|
||||
zoomFactor: zoomFactor,
|
||||
isZoomed: true
|
||||
@@ -93,9 +157,13 @@ class App extends React.Component {
|
||||
}
|
||||
this.setState({isZoomed: false});
|
||||
};
|
||||
imgs = image_metadatum.map((metadata) => {
|
||||
const onZoom = (e) => this.setState({
|
||||
zoomFactor: Number(e.target.value)
|
||||
});
|
||||
|
||||
images = imageMetadata.map((metadata) => {
|
||||
let {name, size, ratio, image} = metadata;
|
||||
let width = 512;
|
||||
let width = 256;
|
||||
let height = (ratio * width).toFixed();
|
||||
let url = ROOT + image + '?t=' + timestamp;
|
||||
const mouseMove = (e) => {
|
||||
@@ -111,7 +179,7 @@ class App extends React.Component {
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
imageRendering: isZoomed ? 'pixelated' : 'auto',
|
||||
backgroundSize: isZoomed ? zoomFactor * size[0] + 'px ' + zoomFactor * size[1] + 'px' : 'contain',
|
||||
backgroundSize: isZoomed ? zoomFactor * width + 'px ' + zoomFactor * height + 'px' : 'contain',
|
||||
backgroundPosition: isZoomed ? 100*x + '% ' + 100*y + '%' : 'center center',
|
||||
};
|
||||
return (
|
||||
@@ -126,29 +194,29 @@ class App extends React.Component {
|
||||
<p>{name}</p>
|
||||
</div>)
|
||||
});
|
||||
appContent = <div><h1>Run @ {new Date(timestamp * 1000).toLocaleString()}</h1>{imgs}</div>;
|
||||
mainContent = <div>
|
||||
<Heading>
|
||||
Run @ {new Date(timestamp * 1000).toLocaleString()}
|
||||
</Heading>
|
||||
{images}
|
||||
</div>;
|
||||
|
||||
sidebarContent = <Sidebar
|
||||
imageMetadata={imageMetadata}
|
||||
zoomFactor={zoomFactor}
|
||||
x={x} y={y}
|
||||
binary={binary}
|
||||
onZoom={onZoom} />;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="controls">
|
||||
<label>
|
||||
Zoom:
|
||||
<input
|
||||
id="zoom"
|
||||
type="range"
|
||||
min="1" max="24"
|
||||
value={zoomFactor}
|
||||
onChange={(e) => this.setState({
|
||||
zoomFactor: Number(e.target.value)
|
||||
})}
|
||||
step="0.1"/>
|
||||
</label>
|
||||
{zoomFactor}
|
||||
</div>
|
||||
<div className="App">
|
||||
{appContent}
|
||||
</div>
|
||||
</div>
|
||||
<Columns>
|
||||
<Columns.Column size="one-fifth">
|
||||
{sidebarContent}
|
||||
</Columns.Column>
|
||||
<Columns.Column>
|
||||
{mainContent}
|
||||
</Columns.Column>
|
||||
</Columns>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,3 +11,14 @@ code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||
monospace;
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
html, body, #root {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import 'react-bulma-components/dist/react-bulma-components.min.css';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
Reference in New Issue
Block a user