Compare commits
3 Commits
1bbb36c85a
...
d7dcbbd318
| Author | SHA1 | Date | |
|---|---|---|---|
| d7dcbbd318 | |||
| 43fba05875 | |||
| c2aef6df5b |
@ -8,7 +8,8 @@
|
|||||||
"react": "^16.10.2",
|
"react": "^16.10.2",
|
||||||
"react-bulma-components": "3.1.3",
|
"react-bulma-components": "3.1.3",
|
||||||
"react-dom": "^16.10.2",
|
"react-dom": "^16.10.2",
|
||||||
"react-scripts": "3.2.0"
|
"react-scripts": "3.2.0",
|
||||||
|
"transformation-matrix": "^2.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
@ -13,14 +13,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
|
|||||||
186
src/App.js
186
src/App.js
@ -3,7 +3,9 @@ import moment from 'moment';
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
import {
|
import {
|
||||||
Columns,
|
Columns,
|
||||||
|
Footer,
|
||||||
Heading,
|
Heading,
|
||||||
|
Table,
|
||||||
} from 'react-bulma-components';
|
} from 'react-bulma-components';
|
||||||
|
|
||||||
|
|
||||||
@ -13,7 +15,7 @@ const MAX_ZOOM_FACTOR = 32;
|
|||||||
|
|
||||||
const Sidebar = (props) => {
|
const Sidebar = (props) => {
|
||||||
let {
|
let {
|
||||||
binary, binaryMax, imageMetadata, zoomFactor, x, y,
|
renderTimeSeconds, binary, binaryMax, scene, imageMetadata, zoomFactor, mouseX, mouseY,
|
||||||
onZoom,
|
onZoom,
|
||||||
} = props;
|
} = props;
|
||||||
let samples = imageMetadata.map((md) => {
|
let samples = imageMetadata.map((md) => {
|
||||||
@ -21,13 +23,9 @@ const Sidebar = (props) => {
|
|||||||
if (pix === undefined) { return <p key={md.name}>Loading...</p>; }
|
if (pix === undefined) { return <p key={md.name}>Loading...</p>; }
|
||||||
let max = binaryMax[md.name];
|
let max = binaryMax[md.name];
|
||||||
let [w, h] = md.size;
|
let [w, h] = md.size;
|
||||||
let xOff = Math.min(w, Math.max(0, Math.round(x*w)));
|
let xOff = mouseX; // Math.min(w, Math.max(0, Math.round(x*w)));
|
||||||
let yOff = Math.min(h, Math.max(0, Math.round(y*h)));
|
let yOff = mouseY; // Math.min(h, Math.max(0, Math.round(y*h)));
|
||||||
let v = pix[xOff+yOff*w];
|
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 color = "#fff";
|
let color = "#fff";
|
||||||
let rgb = "";
|
let rgb = "";
|
||||||
let value = "";
|
let value = "";
|
||||||
@ -35,23 +33,53 @@ const Sidebar = (props) => {
|
|||||||
let r = Math.round(v[0]*255);
|
let r = Math.round(v[0]*255);
|
||||||
let g = Math.round(v[1]*255);
|
let g = Math.round(v[1]*255);
|
||||||
let b = Math.round(v[2]*255);
|
let b = Math.round(v[2]*255);
|
||||||
rgb = `rgb(${r}, ${g}, ${b})`;
|
value = `${r}, ${g}, ${b}`;
|
||||||
|
rgb = `rgb(${value})`;
|
||||||
color = `rgb(${255^r}, ${255^g}, ${255^b})`;
|
color = `rgb(${255^r}, ${255^g}, ${255^b})`;
|
||||||
value = rgb;
|
|
||||||
} else {
|
} else {
|
||||||
let c = 255*v/max;
|
let c = 255*v/max;
|
||||||
rgb = `rgb(${c}, ${c}, ${c})`;
|
rgb = `rgb(${c}, ${c}, ${c})`;
|
||||||
color = `rgb(${255^c}, ${255^c}, ${255^c})`;
|
color = `rgb(${255^c}, ${255^c}, ${255^c})`;
|
||||||
value = v;
|
value = v;
|
||||||
}
|
}
|
||||||
return <div className="sample" key={md.name}>
|
return <li className="sample" key={md.name}>
|
||||||
<p>{md.name}</p>
|
<p>{md.name}</p>
|
||||||
<p className="value" style={{
|
<p className="value" style={{
|
||||||
color,
|
color,
|
||||||
backgroundColor: rgb,
|
backgroundColor: rgb,
|
||||||
}}>{value}</p>
|
}}>{value}</p>
|
||||||
</div>
|
</li>
|
||||||
});
|
});
|
||||||
|
let sceneInfo = <ul className="menu-list">
|
||||||
|
<Table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>render time</td>
|
||||||
|
<td>{renderTimeSeconds}s</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>subsamples</td>
|
||||||
|
<td>{scene.subsamples || "default"}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>adaptive subsampling</td>
|
||||||
|
<td>{scene.adaptiveSubsampling || "default"}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>numThreads</td>
|
||||||
|
<td>{scene.numThreads || "default"}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>width</td>
|
||||||
|
<td>{scene.width}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>height</td>
|
||||||
|
<td>{scene.height}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
</ul>;
|
||||||
return <aside className="menu">
|
return <aside className="menu">
|
||||||
<p className="menu-label">
|
<p className="menu-label">
|
||||||
Controls
|
Controls
|
||||||
@ -72,10 +100,17 @@ const Sidebar = (props) => {
|
|||||||
<p className="menu-label">
|
<p className="menu-label">
|
||||||
Samples
|
Samples
|
||||||
</p>
|
</p>
|
||||||
{samples}
|
<ul className="menu-list">
|
||||||
|
{samples}
|
||||||
|
</ul>
|
||||||
|
<p className="menu-label">
|
||||||
|
Scene
|
||||||
|
</p>
|
||||||
|
{sceneInfo}
|
||||||
</aside>;
|
</aside>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ELEMENT_WIDTH = 384;
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -85,10 +120,13 @@ class App extends React.Component {
|
|||||||
binaryMax: {},
|
binaryMax: {},
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
isFrozen: false,
|
isFrozen: false,
|
||||||
isZoomed: false,
|
isMouseDown: false,
|
||||||
|
isZoomed: true,
|
||||||
zoomFactor: 4,
|
zoomFactor: 4,
|
||||||
x: 0,
|
mouseX: 0,
|
||||||
y: 0,
|
mouseY: 0,
|
||||||
|
offsetX: -1.5*ELEMENT_WIDTH,
|
||||||
|
offsetY: -1.5*ELEMENT_WIDTH,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -101,7 +139,6 @@ class App extends React.Component {
|
|||||||
fetchTracerData() {
|
fetchTracerData() {
|
||||||
this.setState({...this.state, isFetching: true})
|
this.setState({...this.state, isFetching: true})
|
||||||
const max = (acc, cur) => Math.max(acc, cur);
|
const max = (acc, cur) => Math.max(acc, cur);
|
||||||
// console.log(array1.reduce(max));
|
|
||||||
fetch(DATA_URL)
|
fetch(DATA_URL)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(result => {
|
.then(result => {
|
||||||
@ -117,7 +154,6 @@ class App extends React.Component {
|
|||||||
let curBinary = this.state.binary;
|
let curBinary = this.state.binary;
|
||||||
let curBinaryMax = this.state.binaryMax;
|
let curBinaryMax = this.state.binaryMax;
|
||||||
let binaryMax = result.reduce(max);
|
let binaryMax = result.reduce(max);
|
||||||
console.log(`${md.name} ${binaryMax}`);
|
|
||||||
this.setState({
|
this.setState({
|
||||||
binary: {
|
binary: {
|
||||||
[md.name]: result,
|
[md.name]: result,
|
||||||
@ -144,73 +180,110 @@ class App extends React.Component {
|
|||||||
binaryMax,
|
binaryMax,
|
||||||
data,
|
data,
|
||||||
isFrozen,
|
isFrozen,
|
||||||
|
isMouseDown,
|
||||||
isZoomed,
|
isZoomed,
|
||||||
x,
|
mouseX,
|
||||||
y,
|
mouseY,
|
||||||
|
offsetX,
|
||||||
|
offsetY,
|
||||||
zoomFactor,
|
zoomFactor,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
let mainContent = <h1>Loading</h1>;
|
let mainContent = <h1>Loading</h1>;
|
||||||
let sidebarContent = <h1>Loading</h1>;
|
let sidebarContent = <h1>Loading</h1>;
|
||||||
if (data !== null) {
|
if (data !== null) {
|
||||||
let {timestamp, imageMetadata} = data;
|
let {timestamp, renderTimeSeconds, imageMetadata, scene} = data;
|
||||||
const mouseClick = (e) => {
|
|
||||||
console.log('isFrozen', isFrozen, 'this.state.isFrozen', this.state.isFrozen);
|
|
||||||
this.setState({isFrozen: !this.state.isFrozen});
|
|
||||||
};
|
|
||||||
const mouseEnter = (e) => {
|
const mouseEnter = (e) => {
|
||||||
if (isFrozen) {
|
if (isFrozen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setState({isZoomed: true});
|
this.setState({isZoomed: true});
|
||||||
};
|
};
|
||||||
const mouseScroll = (e) => {
|
|
||||||
let delta = parseFloat(-e.deltaY/100.0);
|
|
||||||
let zoomFactor = delta + this.state.zoomFactor;
|
|
||||||
if (zoomFactor < 1) { zoomFactor = 1; }
|
|
||||||
if (zoomFactor > MAX_ZOOM_FACTOR) {
|
|
||||||
zoomFactor = MAX_ZOOM_FACTOR;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
zoomFactor: zoomFactor,
|
|
||||||
isZoomed: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const mouseLeave = (e) => {
|
const mouseLeave = (e) => {
|
||||||
if (isFrozen) {
|
this.setState({isMouseDown: false});
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.setState({isZoomed: false});
|
|
||||||
};
|
};
|
||||||
const onZoom = (e) => this.setState({
|
const onZoom = (e) => this.setState({
|
||||||
zoomFactor: Number(e.target.value)
|
zoomFactor: Number(e.target.value)
|
||||||
});
|
});
|
||||||
|
|
||||||
images = imageMetadata.map((metadata) => {
|
images = imageMetadata.map((metadata) => {
|
||||||
let {name, ratio, image} = metadata;
|
let {name, ratio, image, size} = metadata;
|
||||||
let width = 384;
|
let width = ELEMENT_WIDTH;
|
||||||
let height = (ratio * width).toFixed();
|
let height = (ratio * width).toFixed();
|
||||||
let url = ROOT + image + '?t=' + timestamp;
|
let url = ROOT + image + '?t=' + timestamp;
|
||||||
const mouseMove = (e) => {
|
|
||||||
if (isFrozen) {
|
const clamp = (offsetX, offsetY) => {
|
||||||
return;
|
let minX = width - width * zoomFactor;
|
||||||
|
let minY = height - height * zoomFactor;
|
||||||
|
let maxX = 0;//width * zoomFactor - width;
|
||||||
|
let maxY = 0;//height * zoomFactor - height;
|
||||||
|
offsetX = Math.max(minX, Math.min(maxX, offsetX));
|
||||||
|
offsetY = Math.max(minY, Math.min(maxY, offsetY));
|
||||||
|
this.setState({offsetX, offsetY});
|
||||||
|
};
|
||||||
|
|
||||||
|
const pointerDown = (e) => {
|
||||||
|
// TODO(wathiede): figure out how to grab a ref and
|
||||||
|
// setPointerCapture on that.
|
||||||
|
//this.setPointerCapture(e.pointerId);
|
||||||
|
this.setState({isMouseDown: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
const pointerUp = (e) => {
|
||||||
|
// TODO(wathiede): figure out how to grab a ref and
|
||||||
|
// releasePointerCapture on that.
|
||||||
|
//this.releasePointerCapture(e.pointerId);
|
||||||
|
this.setState({isMouseDown: false});
|
||||||
|
};
|
||||||
|
|
||||||
|
const pointerMove = (e) => {
|
||||||
|
if (isMouseDown) {
|
||||||
|
offsetX += e.movementX;
|
||||||
|
offsetY += e.movementY;
|
||||||
|
clamp(offsetX, offsetY);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let rect = e.currentTarget.getBoundingClientRect();
|
||||||
|
let screenX = e.clientX - rect.left;
|
||||||
|
let screenY = e.clientY - rect.top;
|
||||||
|
let viewW = size[0] / zoomFactor;
|
||||||
|
let viewH = size[1] / zoomFactor;
|
||||||
|
let xOff = (-offsetX*size[0])/(zoomFactor * width) + (screenX / width) * viewW;
|
||||||
|
let yOff = (-offsetY*size[1])/(zoomFactor * height) + (screenY / height) * viewH;
|
||||||
|
this.setState({mouseX: Math.round(xOff), mouseY: Math.round(yOff)});
|
||||||
}
|
}
|
||||||
let rect = e.currentTarget.getBoundingClientRect();
|
e.preventDefault();
|
||||||
let x = e.clientX - rect.left;
|
};
|
||||||
let y = e.clientY - rect.top;
|
|
||||||
this.setState({x: x/width, y: y/height});
|
const mouseScroll = (e) => {
|
||||||
|
let localOffsetX = this.state.offsetX;
|
||||||
|
let localOffsetY = this.state.offsetY;
|
||||||
|
let delta = parseFloat(-e.deltaY/100.0);
|
||||||
|
let zoomFactor = delta + this.state.zoomFactor;
|
||||||
|
if (zoomFactor < 1) { zoomFactor = 1; }
|
||||||
|
if (zoomFactor > MAX_ZOOM_FACTOR) {
|
||||||
|
zoomFactor = MAX_ZOOM_FACTOR;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
zoomFactor: zoomFactor,
|
||||||
|
isZoomed: true
|
||||||
|
});
|
||||||
|
|
||||||
|
clamp(offsetX, offsetY);
|
||||||
};
|
};
|
||||||
let style = {
|
let style = {
|
||||||
width: width + 'px',
|
width: width + 'px',
|
||||||
height: height + 'px',
|
height: height + 'px',
|
||||||
imageRendering: isZoomed ? 'pixelated' : 'auto',
|
imageRendering: isZoomed ? 'pixelated' : 'auto',
|
||||||
backgroundSize: isZoomed ? zoomFactor * width + 'px ' + zoomFactor * height + 'px' : 'contain',
|
backgroundSize: isZoomed ? zoomFactor * width + 'px ' + zoomFactor * height + 'px' : 'contain',
|
||||||
backgroundPosition: isZoomed ? 100*x + '% ' + 100*y + '%' : 'center center',
|
backgroundPosition: isZoomed ? offsetX + 'px ' + offsetY + 'px' : 'center center',
|
||||||
};
|
};
|
||||||
|
console.log('offset', offsetX, offsetY);
|
||||||
return (
|
return (
|
||||||
<div key={name}
|
<div key={name}
|
||||||
onClick={mouseClick}
|
onPointerDown={pointerDown}
|
||||||
onMouseMove={mouseMove}
|
onPointerUp={pointerUp}
|
||||||
onMouseEnter={mouseEnter}
|
onPointerMove={pointerMove}
|
||||||
|
//onMouseEnter={mouseEnter}
|
||||||
onMouseLeave={mouseLeave}
|
onMouseLeave={mouseLeave}
|
||||||
onWheel={mouseScroll}
|
onWheel={mouseScroll}
|
||||||
className="frame"
|
className="frame"
|
||||||
@ -230,16 +303,19 @@ class App extends React.Component {
|
|||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
sidebarContent = <Sidebar
|
sidebarContent = <Sidebar
|
||||||
|
scene={scene}
|
||||||
|
renderTimeSeconds={renderTimeSeconds}
|
||||||
imageMetadata={imageMetadata}
|
imageMetadata={imageMetadata}
|
||||||
zoomFactor={zoomFactor}
|
zoomFactor={zoomFactor}
|
||||||
x={x} y={y}
|
mouseX={mouseX}
|
||||||
|
mouseY={mouseY}
|
||||||
binary={binary}
|
binary={binary}
|
||||||
binaryMax={binaryMax}
|
binaryMax={binaryMax}
|
||||||
onZoom={onZoom} />;
|
onZoom={onZoom} />;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Columns>
|
<Columns>
|
||||||
<Columns.Column size="one-fifth">
|
<Columns.Column size="one-quarter">
|
||||||
{sidebarContent}
|
{sidebarContent}
|
||||||
</Columns.Column>
|
</Columns.Column>
|
||||||
<Columns.Column>
|
<Columns.Column>
|
||||||
|
|||||||
6
src/bulmaswatch.min.css
vendored
Normal file
6
src/bulmaswatch.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import 'react-bulma-components/dist/react-bulma-components.min.css';
|
import 'react-bulma-components/dist/react-bulma-components.min.css';
|
||||||
|
import './bulmaswatch.min.css';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import * as serviceWorker from './serviceWorker';
|
import * as serviceWorker from './serviceWorker';
|
||||||
|
|||||||
@ -8268,6 +8268,10 @@ tr46@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
transformation-matrix@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/transformation-matrix/-/transformation-matrix-2.1.1.tgz#50c1cf4049ac9a2c778eda62bb404e158723657d"
|
||||||
|
|
||||||
ts-pnp@1.1.4, ts-pnp@^1.1.2:
|
ts-pnp@1.1.4, ts-pnp@^1.1.2:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90"
|
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user