项目实训-智能生物序列分析平台-前端模块(6)

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)
            });

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值