more fixes
This commit is contained in:
parent
e1c1096458
commit
064e28a02e
6 changed files with 79 additions and 112 deletions
|
@ -1,12 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
import ProgressBar from 'component/common/progress-bar';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
status: string,
|
status: string,
|
||||||
spinner: boolean,
|
spinner: boolean,
|
||||||
progress?: number,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadingScreen extends React.PureComponent<Props> {
|
class LoadingScreen extends React.PureComponent<Props> {
|
||||||
|
@ -19,7 +17,6 @@ class LoadingScreen extends React.PureComponent<Props> {
|
||||||
return (
|
return (
|
||||||
<div className="content__loading">
|
<div className="content__loading">
|
||||||
{spinner && <Spinner light />}
|
{spinner && <Spinner light />}
|
||||||
{progress && <ProgressBar progress={progress}/>}
|
|
||||||
{status && <span className="content__loading-text">{status}</span>}
|
{status && <span className="content__loading-text">{status}</span>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
progress: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
class progressBar extends React.PureComponent<Props> {
|
|
||||||
static defaultProps = {
|
|
||||||
progress: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { progress } = this.props;
|
|
||||||
return (
|
|
||||||
<div className="progress-bar">
|
|
||||||
<div className="progress-bar__progress" style={{width: progress}}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LoadingScreen;
|
|
|
@ -1,11 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as THREE from './internal/three.js';
|
|
||||||
import detectWebGL from './internal/detector.js';
|
|
||||||
import ThreeScene from './internal/scene.js';
|
|
||||||
import ThreeLoader from './internal/loader.js';
|
|
||||||
import ThreeRenderer from './internal/renderer.js';
|
|
||||||
import LoadingScreen from 'component/common/loading-screen';
|
import LoadingScreen from 'component/common/loading-screen';
|
||||||
|
// ThreeJS
|
||||||
|
import * as THREE from './internal/three';
|
||||||
|
import detectWebGL from './internal/detector';
|
||||||
|
import ThreeScene from './internal/scene';
|
||||||
|
import ThreeLoader from './internal/loader';
|
||||||
|
import ThreeRenderer from './internal/renderer';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
theme: string,
|
theme: string,
|
||||||
|
@ -22,7 +23,7 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
|
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
|
||||||
//Main container
|
// Main container
|
||||||
this.viewer = React.createRef();
|
this.viewer = React.createRef();
|
||||||
|
|
||||||
// Object colors
|
// Object colors
|
||||||
|
@ -60,6 +61,22 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (detectWebGL()) {
|
||||||
|
this.renderScene();
|
||||||
|
// Update render on resize window
|
||||||
|
window.addEventListener('resize', this.handleResize, false);
|
||||||
|
} else {
|
||||||
|
// No webgl support, handle Error...
|
||||||
|
// TODO: Use a better error message
|
||||||
|
this.state({ error: "Sorry, your computer doesn't support WebGL." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('resize', this.handleResize, false);
|
||||||
|
}
|
||||||
|
|
||||||
createOrbitControls(camera, canvas) {
|
createOrbitControls(camera, canvas) {
|
||||||
const { autoRotate } = this.props;
|
const { autoRotate } = this.props;
|
||||||
const controls = new THREE.OrbitControls(camera, canvas);
|
const controls = new THREE.OrbitControls(camera, canvas);
|
||||||
|
@ -85,11 +102,15 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
createWireFrame(group) {
|
createWireFrame(group) {
|
||||||
const wireframe = new THREE.WireframeGeometry(group.geometry);
|
const wireframeGeometry = new THREE.WireframeGeometry(group.geometry);
|
||||||
this.wireframe = new THREE.LineSegments(wireframe);
|
const wireframeMaterial = new THREE.LineBasicMaterial({
|
||||||
this.wireframe.material.depthTest = false;
|
opacity: 0,
|
||||||
this.wireframe.material.opacity = 0;
|
transparent: true,
|
||||||
this.wireframe.transparent = true;
|
linewidth: 1,
|
||||||
|
});
|
||||||
|
// Set material color
|
||||||
|
wireframeMaterial.color.set(this.materialColors.green);
|
||||||
|
this.wireframe = new THREE.LineSegments(wireframeGeometry, wireframeMaterial);
|
||||||
group.add(this.wireframe);
|
group.add(this.wireframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +136,7 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
this.scene.add(mesh);
|
this.scene.add(mesh);
|
||||||
this.fitMeshToCamera(mesh);
|
this.fitMeshToCamera(mesh);
|
||||||
this.createWireFrame(mesh);
|
this.createWireFrame(mesh);
|
||||||
this.setControlsTarget(mesh.position);
|
this.updateControlsTarget(mesh.position);
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +146,8 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fitMeshToCamera(group) {
|
fitMeshToCamera(group) {
|
||||||
let max = { x: 0, y: 0, z: 0 };
|
const max = { x: 0, y: 0, z: 0 };
|
||||||
let min = { x: 0, y: 0, z: 0 };
|
const min = { x: 0, y: 0, z: 0 };
|
||||||
|
|
||||||
group.traverse(child => {
|
group.traverse(child => {
|
||||||
if (child instanceof THREE.Mesh) {
|
if (child instanceof THREE.Mesh) {
|
||||||
|
@ -144,29 +165,25 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
|
|
||||||
const meshY = Math.abs(max.y - min.y);
|
const meshY = Math.abs(max.y - min.y);
|
||||||
const meshX = Math.abs(max.x - min.x);
|
const meshX = Math.abs(max.x - min.x);
|
||||||
const meshZ = Math.abs(max.z - min.z);
|
const scaleFactor = 15 / Math.max(meshX, meshY);
|
||||||
const scaleFactor = 10 / Math.max(meshX, meshY);
|
|
||||||
|
|
||||||
group.scale.set(scaleFactor, scaleFactor, scaleFactor);
|
group.scale.set(scaleFactor, scaleFactor, scaleFactor);
|
||||||
group.position.y = meshY / 2 * scaleFactor;
|
group.position.setY((meshY / 2) * scaleFactor);
|
||||||
group.position.multiplyScalar(-1);
|
group.position.multiplyScalar(-1);
|
||||||
group.position.y += meshY * scaleFactor;
|
group.position.setY(meshY * scaleFactor);
|
||||||
}
|
|
||||||
|
|
||||||
setControlsTarget(point) {
|
|
||||||
this.controls.target.fromArray([point.x, point.y, point.z]);
|
|
||||||
this.controls.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startLoader() {
|
startLoader() {
|
||||||
const { source } = this.props;
|
const { source } = this.props;
|
||||||
source &&
|
|
||||||
|
if (source) {
|
||||||
ThreeLoader(source, this.renderModel.bind(this), {
|
ThreeLoader(source, this.renderModel.bind(this), {
|
||||||
onStart: this.handleStart(this),
|
onStart: this.handleStart(this),
|
||||||
onLoad: this.handleReady.bind(this),
|
onLoad: this.handleReady.bind(this),
|
||||||
onError: this.handleError.bind(this),
|
onError: this.handleError.bind(this),
|
||||||
onProgress: this.handleProgress.bind(this),
|
onProgress: this.handleProgress.bind(this),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStart() {
|
handleStart() {
|
||||||
|
@ -186,13 +203,13 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
this.renderer.setSize(width, height);
|
this.renderer.setSize(width, height);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleError(url) {
|
handleError() {
|
||||||
this.setState({ error: "Sorry, looks like we can't load this file" });
|
this.setState({ error: "Sorry, looks like we can't load this file" });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleProgress(url, currentItem, totalItems) {
|
handleProgress() {
|
||||||
const progress = (currentItem / totalItems) * 100;
|
// const progress = (currentItem / totalItems) * 100;
|
||||||
this.setState({progress});
|
// console.info(currentItem, totalItems, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleColorChange(color) {
|
handleColorChange(color) {
|
||||||
|
@ -202,6 +219,11 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
this.wireframe.material.color.set(pickColor);
|
this.wireframe.material.color.set(pickColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateControlsTarget(point) {
|
||||||
|
this.controls.target.fromArray([point.x, point.y, point.z]);
|
||||||
|
this.controls.update();
|
||||||
|
}
|
||||||
|
|
||||||
renderModel(fileType, data) {
|
renderModel(fileType, data) {
|
||||||
const geometry = this.createGeometry(data);
|
const geometry = this.createGeometry(data);
|
||||||
this.mesh = this.createMesh(geometry);
|
this.mesh = this.createMesh(geometry);
|
||||||
|
@ -243,33 +265,21 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
viewer.appendChild(canvas);
|
viewer.appendChild(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
if (detectWebGL()) {
|
|
||||||
this.renderScene();
|
|
||||||
// Update render on resize window
|
|
||||||
window.addEventListener('resize', this.handleResize, false);
|
|
||||||
} else {
|
|
||||||
// No webgl support, handle Error...
|
|
||||||
// TODO: Use a better error message
|
|
||||||
this.state({ error: 'No webgl support!' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
window.removeEventListener('resize', this.handleResize, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { error, progress, isReady, isLoading } = this.state;
|
const { error, isReady, isLoading } = this.state;
|
||||||
const loadingMessage = 'Rendering model.';
|
const loadingMessage = 'Loading 3D model.';
|
||||||
const showViewer = isReady && !error;
|
const showViewer = isReady && !error;
|
||||||
const showLoading = isLoading && !error;
|
const showLoading = isLoading && !error;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{error && <LoadingScreen status={error} spinner={false} />}
|
{error && <LoadingScreen status={error} spinner={false} />}
|
||||||
{showLoading && <LoadingScreen status={loadingMessage} spinner={false} progress={progress} />}
|
{showLoading && <LoadingScreen status={loadingMessage} spinner />}
|
||||||
<div style={{ opacity: isReady ? 1 : 0 }} className="three-viewer" ref={this.viewer} />
|
<div
|
||||||
|
style={{ opacity: showViewer ? 1 : 0 }}
|
||||||
|
className="three-viewer file-render__viewer"
|
||||||
|
ref={this.viewer}
|
||||||
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { LoadingManager, STLLoader, OBJLoader } from './three.js';
|
import { LoadingManager, STLLoader, OBJLoader } from './three';
|
||||||
|
|
||||||
const Manager = ({ onLoad, onStart, onProgress, onError }) => {
|
const Manager = ({ onLoad, onStart, onProgress, onError }) => {
|
||||||
const manager = new THREE.LoadingManager();
|
const manager = new LoadingManager();
|
||||||
manager.onLoad = onLoad;
|
manager.onLoad = onLoad;
|
||||||
manager.onStart = onStart;
|
manager.onStart = onStart;
|
||||||
//manager.onProgress = onProgress;
|
manager.onProgress = onProgress;
|
||||||
manager.onError = onError;
|
manager.onError = onError;
|
||||||
|
|
||||||
return manager;
|
return manager;
|
||||||
|
@ -19,17 +19,16 @@ const Loader = (fileType, manager) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const ThreeLoader = ({ fileType, filePath }, renderModel, managerEvents) => {
|
const ThreeLoader = ({ fileType, filePath }, renderModel, managerEvents) => {
|
||||||
if (!fileType) return;
|
if (fileType) {
|
||||||
|
const manager = Manager(managerEvents);
|
||||||
|
const loader = Loader(fileType, manager);
|
||||||
|
|
||||||
const manager = Manager(managerEvents);
|
if (loader) {
|
||||||
const loader = Loader(fileType, manager);
|
loader.load(filePath, data => {
|
||||||
|
renderModel(fileType, data);
|
||||||
// Unsuported loader
|
});
|
||||||
if (!loader) return false;
|
}
|
||||||
|
}
|
||||||
loader.load(filePath, data => {
|
|
||||||
renderModel(fileType, data);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ThreeLoader;
|
export default ThreeLoader;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as THREE from './three.js';
|
import * as THREE from './three';
|
||||||
|
|
||||||
const addGrid = (scene, { gridColor, centerLineColor, size }) => {
|
const addGrid = (scene, { gridColor, centerLineColor, size }) => {
|
||||||
const divisions = size / 2;
|
const divisions = size / 2;
|
||||||
|
@ -31,25 +31,25 @@ const addLights = (scene, color, groundColor) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Scene = ({ backgroundColor, groundColor, showFog, showGrid, gridColor, centerLineColor }) => {
|
const Scene = ({ backgroundColor, groundColor, showFog, showGrid, gridColor, centerLineColor }) => {
|
||||||
// Convert colors
|
// Convert color
|
||||||
backgroundColor = new THREE.Color(backgroundColor);
|
const bgColor = new THREE.Color(backgroundColor);
|
||||||
groundColor = new THREE.Color(groundColor);
|
|
||||||
// New scene
|
// New scene
|
||||||
const scene = new THREE.Scene();
|
const scene = new THREE.Scene();
|
||||||
// Background color
|
// Background color
|
||||||
scene.background = backgroundColor;
|
scene.background = bgColor;
|
||||||
// Fog effect
|
// Fog effect
|
||||||
scene.fog = showFog === true ? new THREE.Fog(backgroundColor, 1, 95) : null;
|
scene.fog = showFog === true ? new THREE.Fog(bgColor, 1, 95) : null;
|
||||||
|
// Add grid
|
||||||
showGrid &&
|
if (showGrid) {
|
||||||
addGrid(scene, {
|
addGrid(scene, {
|
||||||
size: 100,
|
size: 100,
|
||||||
gridColor,
|
gridColor,
|
||||||
centerLineColor,
|
centerLineColor,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
// Add basic lights
|
// Add basic lights
|
||||||
addLights(scene, '#FFFFFF', groundColor);
|
addLights(scene, '#FFFFFF', groundColor);
|
||||||
|
|
||||||
// Return new three scene
|
// Return new three scene
|
||||||
return scene;
|
return scene;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
.progress-bar {
|
|
||||||
width: 75%;
|
|
||||||
height: 5px;
|
|
||||||
display: block;
|
|
||||||
background: rgba(255, 255, 255, 0.25);
|
|
||||||
border-radius: 3px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar__progress {
|
|
||||||
width: 20px;
|
|
||||||
height: 5px;
|
|
||||||
background: var(--color-primary);
|
|
||||||
border-radius: 3px;
|
|
||||||
transition: width 0.3s ease;
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue