antd单页面应用于material-UI构架的引用
在页面中的antd的分页功能,相应mobx中的具体全局状态,来切换界面,最终做到但页面应用的效果。
具体代码如下:
import { observable, action, makeAutoObservable } from 'mobx';
import { FAILURE, REQUEST, SUCCESS, UNSET } from '../../constants/status';
class server {
constructor() {
makeAutoObservable(this);
}
@observable homeStatus=1
@observable status = UNSET;
@action request = () => {
this.status = REQUEST;
};
@action request_success = () => {
this.status = SUCCESS;
};
@action request_fail = () => {
this.status = FAILURE;
};
@action changeHomeStatue=(sum)=>{
this.homeStatus=sum
}
}
export default server;
其中对于homeStatus=1,默认是1,我们的函数changeHomeStatue就是一个更改函数,可以通过这个在全局中拿到,然后对homeStatus进行修改
然后在root界面中去维护每一个界面的调用情况,具体代码如下所示:
const menu = (
<Menu>
<Menu.Item
onClick={() => {
store.store.servers.changeHomeStatue(5);
}}
>
Disease based prediction
</Menu.Item>
<Menu.Item
onClick={() => {
store.store.servers.changeHomeStatue(6);
}}
>
Target based prediction
</Menu.Item>
</Menu>
);
const headerCon = {
1: (
<div>
<HomeOutlined className="headerCon-tab" style={{ fontSize: "20px" }} />
Home
</div>
),
2: (
<div>
{/* Services */}
<Dropdown overlay={menu}>
<div
onClick={() => {
store.store.servers.changeHomeStatue(2);
}}
Î
>
<BarChartOutlined
className="headerCon-tab"
style={{ fontSize: "20px" }}
/>
Services
</div>
{/* Services */}
</Dropdown>
</div>
),
4: (
<div>
<FileTextOutlined
className="headerCon-tab"
style={{ fontSize: "20px" }}
/>
Publications
</div>
),
5: (
<div>
<ContactsOutlined
className="headerCon-tab"
style={{ fontSize: "20px" }}
/>
Contact
</div>
),
3: (
<div>
<DesktopOutlined
className="headerCon-tab"
style={{ fontSize: "20px" }}
/>
Tutorial
</div>
),
6: (
<div>
<DatabaseOutlined
className="headerCon-tab"
style={{ fontSize: "20px" }}
/>
Resources
</div>
),
};
const [page, setPage] = useState(1);
const PageCon = () => {
switch (page) {
case 1:
return (
<div className="submit-depart-pages-home">
<HomePage />
</div>
);
case 2:
return (
<div className="submit-depart-pages">
<div className="Result-Result-body-Breadcrumb">
<Breadcrumb>
<Breadcrumb.Item className="Breadcrumb-Item-text">
Home
</Breadcrumb.Item>
<Breadcrumb.Item className="Breadcrumb-Item-text">
Service Select
</Breadcrumb.Item>
<Button
className="Result-Result-body-Breadcrumb-button"
type="link"
onClick={() => {
store.store.servers.changeHomeStatue(1);
}}
>
{" "}
Back
</Button>
</Breadcrumb>
</div>
<ServerHome />
</div>
);
case 3:
return (
<div className="submit-depart-pages">
<div className="Result-Result-body-Breadcrumb">
<Breadcrumb>
<Breadcrumb.Item className="Breadcrumb-Item-text">
Home
</Breadcrumb.Item>
<Breadcrumb.Item className="Breadcrumb-Item-text">
Publications
</Breadcrumb.Item>
<Button
className="Result-Result-body-Breadcrumb-button"
type="link"
onClick={() => {
store.store.servers.changeHomeStatue(1);
}}
>
{" "}
Back
</Button>
</Breadcrumb>
</div>
<Publications />
</div>
);
................
default:
break;
}
};
这是对页面中每一个界面的dict的声明阶段,然后通过对本dict的key进行遍历,不断去调用对应的页面。
然后通过antd的manu组件,对其中的不同dict根据全局状态中的homeStatus进行判断显示在用户面前的是什么界面,代码如下:
<Menu
theme="light"
mode="horizontal"
defaultSelectedKeys={["1"]}
className="Menu-header-home-item"
triggerSubMenuAction="click"
>
{new Array(6).fill(null).map((_, index) => {
const keyValue = index + 1;
return (
<Menu.Item
key={keyValue}
onClick={() => {
store.store.servers.changeHomeStatue(keyValue);
}}
className="commen-Menu-Item"
>
{headerCon[keyValue]}
</Menu.Item>
);
})}
</Menu>
以这种方式来构建但页面应用
另外我们在开发过程中,也将我们的BIO的界面更新迭代了Material-UI的UI框架,然后我逐步进行更深层次的代码迭代。
下面是我对这个框架的嵌入步骤:
Material-UI 组件无需任何额外的设置即可使用,并且不会影响全局变量。
import React from 'react';import { Button }
from '@material-ui/core';
function App() {
return <Button color="primary">Hello World</Button>;
}
因为Material-UI 组件是相互独立的,所以我们可以很快进行嵌入使用,工作时仅注入当前组件所需要的样式。这些Material-UI组件并依赖于任何全局的样式表。
import React from 'react';
import ReactDOM from 'react-dom';
import Button from '@material-ui/core/Button'; // 导入Button组件
function App() {
return (
<Button variant='contained' color='primary'>按钮</Button>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
对于组件的支持上,Materail-UI遵循实际的指导规范,支持所有主流的稳定的浏览器,支持IE11以上。Material-UI还支持node.js v6.x以上的服务端渲染。
其中我们使用了material-UI中的CssBaseline组件以建立统一的简单的样式基准。
import CssBaseline from '@material-ui/core/CssBaseline';
function App() {
return(
<CssBaseline> {/* 页面元素 */} </CssBaseline>
)
}
界面布局
Material-UI的布局设计基础
Material-UI布局,使用统一的组件和间距,实现了多平台、多环境和屏幕尺寸的统一性。
1、使用 Grid / Hidden / Breakpoints 这三类组件,实现响应式UI,适配各种尺寸的屏幕。
2、组件使用 z-index属性,实现 Z 轴上的空间层次排布。
在这一步我们频繁使用Grid的组件,从而实现了很好的flexbox模型
Grid 组件
Material-UI的响应式UI,是基于12列的栅格布局。Material-UI的栅格系统是由 Grid 组件实现的,它使用了 CSS 弹性盒模型,它有两种类型的布局,分别是 containers 和 items。item的宽度被设置为百分比,因此它们总是基于父元素而流动、动态地变换大小。items使用内边距padding生成元素之间的间距空间。Material-UI栅格系统支持五种断点模式,分别是 xs / sm / md / lg / xl 。
下面是我具体使用的代码部分的样例:
<Grid xs={12} sm={6}>
<Box
sx={{
width: "90%",
margin: "10px",
overflowX: "auto",
}}
>
<Box sx={{ width: "max-content", paddingLeft: "60px" }}>
{chipShowList &&
chipShowList.map((seq) => {
let selected = showSeq.includes(seq.value);
return (
<Chip
icon={selected ? <CheckRounded /> : <AddRounded />}
key={seq.value}
label={seq.label}
color={selected ? "primary" : "default"}
disabled={showSeq.length > 0 && !selected}
onClick={() => handleSeqChange(seq.value)}
sx={{ m: "3px 5px", float: "left" }}
/>
);
})}
</Box>
</Box>
</Grid>
这样可以很大程度上提高我们界面的布局管理,代码也具有很大的可读性。
最终我重构后的UI大致固定在如下图所示的状态:
3Dmol的使用:
在web使用3d查看器,很多时候我们会优先考虑是不是要用wegGL又或者Three.js
这里分享一个在生物和化学上比较简单的分子3D查看器 3Dmol.js
3D view 查看器 default pdb; can be pdb, sdf, xyz, mol2, or cube
官网教程地址:https://3dmol.org/doc/tutorial-code.html
先看看官网的内容,如果能看懂可以自己选择集成方式。
官网教程
创建 3DMol 实例
<script src = "http://3Dmol.csb.pitt.edu/build/3Dmol-min.js" "></script>
现在在 HTML 文档中创建一个容器标签来保存可视化。
<div id = "container-01" class = "mol-container"> </div>
注意:3Dmol 将采用容器的大小,因此我们需要确保已明确设置此大小(即使用 CSS 或内联style属性)。
<style>
.mol-container {
width: 60%;
height: 400px;
position: relative;
}
</style>
加载网页后,我们可以创建一个新的 3Dmol 实例。
为了确保一切正常,我们将添加一个球体,设置相机,渲染场景,然后添加缩放。
<script>
$(function() {
let element = $('#container-01');
let config = { backgroundColor: 'orange' };
let viewer = $3Dmol.createViewer( element, config );
viewer.addSphere({ center: {x:0, y:0, z:0}, radius: 10.0, color: 'green' });
viewer.zoomTo();
viewer.render();
viewer.zoom(0.8, 2000);
});
</script>
一个demo 代码是这样的:
let viewer = $3Dmol.createViewer( element, config );
let pdbUri = '/path/to/your/pdb/files/1ycr.pdb';
jQuery.ajax( pdbUri, {
success: function(data) {
let v = viewer;
v.addModel( data, "pdb" ); /* load data */
v.setStyle({}, {cartoon: {color: 'spectrum'}}); /* style all atoms */
v.zoomTo(); /* set camera */
v.render(); /* render scene */
v.zoom(1.2, 1000); /* slight zoom */
},
error: function(hdr, status, err) {
console.error( "Failed to load PDB " + pdbUri + ": " + err );
},
});
我自己做了个HTML将js和3D查看器属性作为一个独立的HTML当成一个查看工具再嵌到前端项目
比如我还可以通过js从访问地址中处理:
$(function(){
//https://XXX.com?uuid=XXX
var search = window.location.search;
if(search != ""){
loadView()
}
});
这样我就可以把 html 完全封装一个简易的3D查看器,上代码和注释,首先网页头部如下:
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
<meta http-equiv="Content-Security-Policy"
content="upgrade-insecure-requests">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://3Dmol.org/build/3Dmol-min.js"></script>
<!-- 方便大家自己本地测试 写一个文件选择器 -->
<input type="file" name="file" value="上传文件" onchange="loadView(this)" />
<!-- 3D view 查看器 -->
<div id="container-01" style="width: 50%;height: 50%;min-height: 10px;"
class='viewer_3Dmoljs' data-backgroundcolor='0xffffff'
data-style='stick'></div>
接下来就是js代码之 pdb :
function loadView(that){
var input = that;
var reader = new FileReader();
reader.readAsText(input.files[0]);
reader.onload = function() {
temp_str = reader.result;
var data = temp_str
console.log(data)
let element = $('#container-01');
let config = { backgroundColor: 'gray' };
let viewer = $3Dmol.createViewer(element, config);
viewer.addModel(data, "pdb").setStyle({}, {"cartoon": { color: '#17ac80'} });
viewer.addSurface($3Dmol.SurfaceType.VDW, {'opacity':0.5, color: 'white'});
viewer.zoomTo();
viewer.render();
viewer.zoom(1, 2000);
}
}
接下来就是js代码之 mol2:
function loadView(that){
var input = that;
var reader = new FileReader();
reader.readAsText(input.files[0]);
reader.onload = function() {
temp_str = reader.result;
var data = temp_str
console.log(data)
let element = $('#container-01');
let config = { backgroundColor: 'gray' };
let viewer = $3Dmol.createViewer(element, config);
viewer.addModel(data, "mol2").setStyle({},{stick:{color: 'spectrum',radius:0.5}});
viewer.addModel(data, "mol2").setStyle({}, {sphere: { color: 'spectrum', radius: 0.5}});
viewer.zoomTo();
viewer.render();
viewer.zoom(1, 2000);
}
}
viewer.setClickable({}, true, function(){
console.log(this)
});