当前位置: 首页 > news >正文

基于cornerstone3D的dicom影像浏览器 第二章,初始化页面结构

完整效果:

cornerstone3D的dicom影像浏览器

本章效果预览:
 

1.在views/home/index.vue中:

<template><div class="container flex-vertical" ref="view2d"><div class="header flex-horizontal"><div class="logo">logo</div><div class="study-list">study list</div></div><div class="main" :class="mainClass"><div :class="toolbarClass" :style="toolbarStyle"></div><div class="nav-display" :class="navDisplayClass"><div :class="navClass" :style="navbarStyle">series list</div><div class="display-area"><displayer-area ref="displayArea"></displayer-area></div></div></div><div class="footer">study bar</div></div>
</template>
<script setup name="View2d">
import { ref, onMounted, computed } from "vue";
import displayerArea from "@/components/displayerArea/index.vue";
const view2d = ref(null);
const navbarHW = ref(146);
const toolbarHW = ref(300);
const toolbarPos = ref("right"); // top or right
const navbarPos = ref("lef"); // bottom or leftconst mainClass = computed(() => {const vorh = toolbarPos.value === "top" ? "vertical" : "horizontal-reverse";return "flex-" + vorh;
});const toolbarClass = computed(() => {return "toolbar-" + toolbarPos.value;
});const toolbarStyle = computed(() => {if (toolbarPos.value === "top") {return {height: toolbarHW.value + "px",};} else {return {width: toolbarHW.value + "px",};}
});const navDisplayClass = computed(() => {const vorh = navbarPos.value === "bottom" ? "vertical-reverse" : "horizontal";return "flex-" + vorh;
});const navClass = computed(() => {return "nav-" + navbarPos.value;
});const navbarStyle = computed(() => {if (navbarPos.value === "bottom") {return {height: navbarHW.value + "px",};} else {return {width: navbarHW.value + "px",};}
});</script>
<style scoped lang="scss">
$bg-color: #333;
$main-color: lightblue;
// $header-color: #108ee9;
$header-color: #45b7ec;
$footer-color: #45b7ec;
$resizer-width: 2px;
$header-height: 50px;
$footer-height: 100px;.container {background-color: $bg-color;height: 100vh;width: 100vw;max-width: 100%;max-height: 100%;justify-content: center;// align-items: center;text-align: center;color: black;user-select: none;
}.flex-vertical {display: flex;flex-direction: column;
}.flex-vertical-reverse {display: flex;flex-direction: column-reverse;
}.flex-horizontal {display: flex;flex-direction: row;
}.flex-horizontal-reverse {display: flex;flex-direction: row-reverse;
}.resizer-vertical {cursor: ew-resize;width: $resizer-width;background-color: gray;z-index: 10;
}.resizer-horizontal {cursor: ns-resize;height: $resizer-width;background-color: gray;width: 100%;z-index: 10;
}.header {height: $header-height;background-color: $header-color;border-bottom: gray solid 1px;.logo {height: 100%;width: 200px;border-right: gray solid 1px;flex-shrink: 0;}.study-list {flex: 1;height: 100%;// background-color: lightblue;}
}.main {width: 100%;height: calc(100vh - $header-height - $footer-height);background-color: $main-color;.nav-display {flex: 1;}.toolbar-top {height: 200px;width: 100%;}.toolbar-right {width: 200px;height: 100%;}.nav-display {.display-area {flex: 1;flex-shrink: 0;}.nav-left {height: 100%;}.nav-bottom {width: 100%;}}
}.footer {background-color: $footer-color;height: $footer-height;border-top: gray solid 1px;
}
</style>

2.displayerArea组件:

<script lang="js" setup name="DisplayerArea">
import { ref, onMounted, computed, reactive, nextTick } from "vue";
import Displayer from "@/components/Displayer/index.vue";
import { useAppStore } from "@/store/appStore.js";
import config from "@/config/index.js"
const appStore = useAppStore();
const { layout, pageSize } = appStore.$stateconst dispRefs = reactive([]);
const selected = [];
const maxDisp = null;
const domWidth = ref(0);const containerStyle = computed(() => {let result = {display: 'gird','grid-template-columns': repeat(layout.row, "1fr"),height: '100%'};return result
});const repeat = (n, s) => {let dst = "";for (let i = 0; i < n; i++) {dst += s + " ";}return dst;
};const getDispRef = (el, pos) => {if (el) {dispRefs[pos] = el;}
};const setLayout = (row, col) => {appStore.setLayout(row, col)selected.length = 0;
};onMounted(() => {const { row, col } = config.defLayout setLayout(row, col);
});
</script><template><div class="displayarea" :style="containerStyle"><Displayerv-for="(v, idx) in pageSize":key="idx":ref="el => getDispRef(el, idx)":pos="idx"/></div>
</template><style lang="scss" scoped>
.displayarea{display: grid;grid-gap: 1px 1px;background-color: black;color: #fff;
}
</style>

3.Displayer

<script lang="js" setup name="Displayer">
import { ref, reactive, onMounted, computed, getCurrentInstance, onUnmounted } from "vue";
const IsSel = ref(false);const borderClass = computed(() => {let s = "selected";if (IsSel.value) {s = "selected";} else {if (IsHover.value) {s = "hovered";} else {s = "unselect";}}return s;});</script><template><divclass="displaybox":class="borderClass"><div class="displayer" ref="displayer"></div></div>
</template>
<style lang="scss" scoped>
.displaybox {position: relative;display: flex;flex-direction: row;background-color: black;.scroll-right {width: 20px;}
}
.displayer {flex: 1;text-align: left;cursor: default;user-select: none;$font-size: 14px;@mixin orient($text-align: left) {position: absolute;color: white;font-size: $font-size;text-align: $text-align;z-index: 10;}.orient_top {@include orient(center);top: 2px;left: calc(50% - 30px);width: 60px;}.orient_bottom {@include orient(center);bottom: 2px;left: calc(50% - 30px);width: 60px;}.orient_left {@include orient();top: calc(50% - 20px);left: 2px;}.orient_right {@include orient();top: calc(50% - 20px);right: 2px;}
}.selected {border: 1px solid red;
}
.hovered {border: 1px dashed yellow;
}
.unselect {border: 1px solid #fff;
}
</style>

4.app store

import { defineStore } from "pinia";
export const useAppStore = defineStore("app", {state: () => {return {layout: {col: 2,row: 2},pageSize: 4}},actions:{setLayout(row, col){this.layout.col = colthis.layout.row = row}}
})


文章转载自:
http://chary.zzgtdz.cn
http://caecostomy.zzgtdz.cn
http://aciform.zzgtdz.cn
http://allegiant.zzgtdz.cn
http://aim.zzgtdz.cn
http://ceiled.zzgtdz.cn
http://behold.zzgtdz.cn
http://apaprthotel.zzgtdz.cn
http://angel.zzgtdz.cn
http://acronically.zzgtdz.cn
http://antienzymatic.zzgtdz.cn
http://achalasia.zzgtdz.cn
http://beguin.zzgtdz.cn
http://centinewton.zzgtdz.cn
http://abn.zzgtdz.cn
http://balladry.zzgtdz.cn
http://catsup.zzgtdz.cn
http://anogenital.zzgtdz.cn
http://arginase.zzgtdz.cn
http://anectine.zzgtdz.cn
http://anticonvulsant.zzgtdz.cn
http://asthenope.zzgtdz.cn
http://campari.zzgtdz.cn
http://battalion.zzgtdz.cn
http://agatize.zzgtdz.cn
http://araneose.zzgtdz.cn
http://astonished.zzgtdz.cn
http://atrophic.zzgtdz.cn
http://antiperspirant.zzgtdz.cn
http://artiste.zzgtdz.cn
http://www.dtcms.com/a/281255.html

相关文章:

  • 航空发动机气膜冷却孔激光频率梳 3D 轮廓检测方法探究
  • 【Qt】QWidget核心属性
  • 【数据结构】单链表练习(有环)
  • MYSQL练习2
  • Java 集合 示例
  • python学智能算法(二十)|SVM基础概念-感知机算法及代码
  • SAP把运费加入到物料成本估算
  • 使用 Aerich 进行 FastAPI 数据库迁移指南
  • redis红锁
  • GitHub 上 Star 数量前 8 的开源 Web 应用项目
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘pandas’问题
  • centos8集群部署etcd
  • 【12】MFC入门到精通——MFC 消息对话框 MessageBox()和AfxMessageBox() 解析 示例 及 应用实例
  • 【目标追踪】MUTR3D: A Multi-camera Tracking Framework via 3D-to-2D Queries
  • MongoDB数据问题说明
  • css-css执行的三种方式和css选择器
  • AS32X601 系列 MCU 硬件最小系统设计与调试方案探析
  • Agentic AI 的威胁与缓解措施
  • 如何快速有效地在WordPress中添加Instagram动态
  • 【PTA数据结构 | C语言版】前序遍历二叉树
  • 零基础入门物联网-远程门禁开关:代码调试
  • 过滤数组中null、undefined、‘‘、等非真内容
  • AAAI-2025 | 同济大学面向嘈杂环境的音频视觉导航!BeDAViN:大规模音频-视觉数据集与多声源架构研究
  • OpenCSG QA:您的国产大模型与 Agent 管理平台
  • 变更缓冲池简介
  • 19.1 单元测试框架
  • ssm学习笔记day08mybatis
  • ESP32轻松实现UDP无线通信
  • 使用python的pillow模块将图片转化为灰度图,获取值和修改值
  • 雷军的 IP 革命:人格化力量如何重塑商业规则|创客匠人