Skip to content

Commit 1d5dea1

Browse files
authored
Merge pull request #730 from minhsueh/crystaltoolkit_animation_scene
Crystaltoolkit animation scene
2 parents ef0fa39 + 17ea0df commit 1d5dea1

14 files changed

+4149
-445
lines changed

package-lock.json

Lines changed: 89 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"dependencies": {
2828
"@babel/preset-typescript": "^7.17.12",
2929
"@babel/runtime": "^7.17.9",
30+
"@react-three/fiber": "^9.2.0",
3031
"@types/classnames": "^2.2.11",
3132
"axios": "^0.21.1",
3233
"base64-js": "^1.5.1",
@@ -66,7 +67,7 @@
6667
"scroll-into-view-if-needed": "^2.2.28",
6768
"styled-components": "^5.3.5",
6869
"svgtodatauri": "0.0.0",
69-
"three": "^0.139.0",
70+
"three": "^0.139.2",
7071
"use-deep-compare-effect": "^1.6.1",
7172
"use-query-params": "^1.2.3",
7273
"use-resize-observer": "^8.0.0",

src/app.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { Navbar } from './components/navigation/Navbar';
2626
import periodicTableImage from './assets/images/periodictable.png';
2727
import { MofExplorer } from './pages/MofExplorer';
2828
import { MatscholarMaterialsExplorer } from './pages/MatscholarMaterialsExplorer/MatscholarMaterialsExplorer';
29+
import { CrystalStructureAnimationViewer } from './pages/CrystalStructureAnimationViewer';
2930

3031
const mountNodeSelector = 'app';
3132
const mountNode = document.getElementById(mountNodeSelector);
@@ -46,6 +47,7 @@ ReactDOM.render(
4647
<Link to="/contribs">Contributions</Link>
4748
<Link to="/crystal">Crystal Structure</Link>
4849
<Link to="/sandbox">Sandbox</Link>
50+
<Link to="/crystal_animation">Crystal Animation</Link>
4951
</div>
5052
<section>
5153
<Switch>
@@ -85,6 +87,9 @@ ReactDOM.render(
8587
<Route path="/matscholar">
8688
<MatscholarMaterialsExplorer />
8789
</Route>
90+
<Route path="/crystal_animation">
91+
<CrystalStructureAnimationViewer />
92+
</Route>
8893
<Route path="/">
8994
<MaterialsExplorer />
9095
</Route>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
.mpc-scene {
2+
position: relative;
3+
}
4+
5+
.tooltiptext {
6+
background-color: black;
7+
color: #fff;
8+
text-align: center;
9+
border-radius: 6px;
10+
padding: 5px;
11+
}
12+
13+
.show-pointer {
14+
cursor: pointer !important;
15+
}
16+
17+
.mpc-scene-square {
18+
position: relative;
19+
}
20+
21+
.mpc-scene-square:before {
22+
content: '';
23+
display: block;
24+
height: 0;
25+
width: 0;
26+
float: left;
27+
padding-bottom: 100%;
28+
}
29+
30+
.mpc-scene-square::after {
31+
clear: left;
32+
content: ' ';
33+
display: table;
34+
}
35+
36+
/**
37+
* Prevent the structure layout from growing beyond the height of the modal.
38+
* Setting max-width with vh instead of simply setting max-height so we don't interfere
39+
* with the structure's styles that force it to render with 1:1 ratio.
40+
*/
41+
.mpc-scene-square-wrapper {
42+
width: 100% !important;
43+
max-width: calc(95vh - 3rem);
44+
height: auto !important;
45+
margin: auto;
46+
}
47+
48+
.mpc-scene .mpc-button-bar {
49+
position: absolute;
50+
right: 0;
51+
z-index: 3;
52+
}
53+
54+
.mpc-scene-settings-panel {
55+
position: absolute;
56+
right: 4.5rem;
57+
max-height: 100%;
58+
max-width: 450px;
59+
overflow: auto;
60+
border: 1px solid #ccc;
61+
border-radius: 6px;
62+
padding: 1.25rem;
63+
background-color: #fff;
64+
opacity: 0.8;
65+
z-index: 2;
66+
}
67+
68+
.mpc-scene-bottom-panel {
69+
position: absolute;
70+
right: 0;
71+
bottom: 0;
72+
z-index: 1;
73+
}
74+
75+
/**
76+
* Include this explicitly so that toggling the settings panel works without bulma
77+
*/
78+
.mpc-scene-settings-panel.is-hidden {
79+
display: none;
80+
}
81+
82+
/**
83+
* Include this explicitly so that file dropdown looks okay without bulma
84+
*/
85+
.mpc-scene .dropdown-content {
86+
position: absolute;
87+
right: 0;
88+
min-width: 100px;
89+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { mount } from 'enzyme';
2+
import * as React from 'react';
3+
import { CrystalToolkitAnimationScene } from './CrystalToolkitAnimationScene';
4+
import { s2 as scene } from '../scene/simple-scene';
5+
import { MOUNT_NODE_CLASS, Renderer } from '../scene/constants';
6+
import Scene from '../scene/Scene';
7+
8+
const spy = jest.spyOn(Scene.prototype, 'renderScene');
9+
const RENDERSCENE_CALLS_BY_REACT_RENDERING = 1; // goal is to reach 1 and stay there :)
10+
11+
// When we run test, three.js is bundled differently, and we encounter again the bug
12+
// where we have 2 different instances of three
13+
describe('<CrystalToolkitAnimationScene/>', () => {
14+
it('should be rendered', () => {
15+
const wrapper = renderElement();
16+
expect(wrapper.find(`.${MOUNT_NODE_CLASS}`).length).toBe(1);
17+
expect(wrapper.find(`.mpc-scene-square`).length).toBe(1);
18+
19+
// Note(chab) we call renderScene when we mount, due to the react effect
20+
// those are the three call sites (constructor / toggleVis / inlet )
21+
expect(spy).toBeCalledTimes(1 * RENDERSCENE_CALLS_BY_REACT_RENDERING);
22+
23+
// fails because SVGRender will import a different instance of Three
24+
// expect(wrapper.find('path').length).toBe(6);
25+
});
26+
27+
it('should re-render if we change the size of the screen', () => {
28+
const wrapper = renderElement();
29+
wrapper.setProps({ size: 400 });
30+
expect(spy).toBeCalledTimes(2 * RENDERSCENE_CALLS_BY_REACT_RENDERING);
31+
});
32+
});
33+
34+
function renderElement() {
35+
// we use mount to test the rendering of the underlying elements
36+
return mount(
37+
<CrystalToolkitAnimationScene
38+
sceneSize={500}
39+
settings={{
40+
renderer: Renderer.SVG
41+
}}
42+
data={scene}
43+
debug={false}
44+
toggleVisibility={{}}
45+
/>
46+
);
47+
}

0 commit comments

Comments
 (0)