irc_web/.svn/pristine/6b/6bfd904d63f7cf49f927ad1cbf8...

1059 lines
33 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div v-loading="loading" class="dicom-viewer-container">
<!-- 工具条 -->
<div class="dicom-tools">
<!-- 窗宽窗位 -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:wwwc')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='WindowLevel'?'tool_active':'']"
data-tool="Zoom"
>
<svg-icon icon-class="reverse" class="svg-icon" @click.prevent="setBasicToolActive('WindowLevel')" />
</div>
<!-- 调窗 -->
<div class="text">{{ $t('trials:reading:button:wwwc') }}</div>
</div>
</el-tooltip>
<!-- 缩放 -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:zoom')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Zoom'?'tool_active':'']"
data-tool="Zoom"
>
<svg-icon icon-class="magnifier" class="svg-icon" @click.prevent="setBasicToolActive('Zoom')" />
</div>
<!-- 缩放 -->
<div class="text">{{ $t('trials:reading:button:zoom') }}</div>
</div>
</el-tooltip>
<!-- 移动 -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:move')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Pan'?'tool_active':'']"
data-tool="Pan"
>
<svg-icon icon-class="move" class="svg-icon" @click.prevent="setBasicToolActive('Pan')" />
</div>
<!-- 移动 -->
<div class="text">{{ $t('trials:reading:button:move') }}</div>
</div>
</el-tooltip>
<!-- 旋转 -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:rotate')}`" placement="bottom">
<div class="tool-wrapper" @click.stop="showPanel($event)" @mouseleave="handleMouseout">
<div class="dropdown">
<div
class="icon"
:class="[activeTool==='Rotate'?'tool_active':'']"
data-tool="Pan"
>
<svg-icon icon-class="rotate" class="svg-icon" @click.prevent="setBasicToolActive('TrackballRotate')" />
<i class="el-icon-arrow-down" style="color:#fff;" />
</div>
<!-- 移动 -->
<div class="text">{{ $t('trials:reading:button:rotate') }}</div>
<div class="dropdown-content">
<ul style="width:100px;">
<li v-for="rotate in rotateArr" :key="rotate.label" style="text-align:left;">
<a href="#" @click.prevent="setDicomCanvasRotate(rotate.val)">{{ rotate.label }}</a>
</li>
</ul>
</div>
</div>
</div>
</el-tooltip>
<!-- 椭圆oval -->
<el-tooltip v-if="isCurrentTask" class="item" effect="dark" content="圆形测量" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='CircleROI'?'tool_active':'']"
data-tool="CircleROI"
>
<svg-icon icon-class="oval" class="svg-icon" @click.prevent="setBasicToolActive('CircleROI')" />
</div>
<!-- 移动 -->
<div class="text">圆形测量</div>
</div>
</el-tooltip>
<!-- <el-tooltip v-if="isCurrentTask" class="item" effect="dark" content="圆形测量" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Probe'?'tool_active':'']"
data-tool="Probe"
>
<svg-icon icon-class="oval" class="svg-icon" @click.prevent="setBasicToolActive('Probe')" />
</div>
<div class="text">探针</div>
</div>
</el-tooltip> -->
<!-- 重置 -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:reset')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="resetViewport"
>
<svg-icon icon-class="refresh" class="svg-icon" />
</div>
<div class="text">{{ $t('trials:reading:button:reset') }}</div>
</div>
</el-tooltip>
<!-- 截屏 -->
<!-- <el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:screenShot')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="saveImage"
>
<svg-icon icon-class="image" class="svg-icon" />
</div>
<div class="text">{{ $t('trials:reading:button:screenShot') }}</div>
</div>
</el-tooltip> -->
<!-- 椭圆oval -->
<div
class="icon"
style="margin-left: auto;cursor: pointer;padding: 5px;"
@click.prevent="closePetct"
>
<svg-icon icon-class="close" class="svg-icon" />
</div>
</div>
<div class="dicom-datas">
<!-- 影像 -->
<div class="dicom-container box box_2_2">
<Viewport
:index="1"
:active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:series-info="ctSeries"
:rendering-engine-id="renderingEngineId"
viewport-id="CT_AXIAL"
:is-render="isRender"
:volume="ctVolume"
/>
<Viewport
:index="2"
:active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:series-info="petSeries"
:rendering-engine-id="renderingEngineId"
viewport-id="PT_AXIAL"
:is-render="isRender"
:volume="ptVolume"
/>
<Viewport
:index="3"
:active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:series-info="petSeries"
:rendering-engine-id="renderingEngineId"
viewport-id="FUSION_AXIAL"
:is-render="isRender"
:volume="ptVolume"
/>
<Viewport
:index="4"
:active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:series-info="petSeries"
:rendering-engine-id="renderingEngineId"
viewport-id="PET_MIP_CORONAL"
:is-render="isRender"
/>
</div>
<!-- 表单 -->
<!-- <div class="form-container" style="overflow-y: auto;">
<div style="color:#fff">
1
</div>
</div> -->
</div>
</div>
</template>
<script>
import {
RenderingEngine,
Enums,
setVolumesForViewports,
volumeLoader,
getRenderingEngine,
eventTarget,
cache,
// metaData,
imageLoader
} from '@cornerstonejs/core'
import * as cornerstoneTools from '@cornerstonejs/tools'
import initLibraries from './js/initLibraries'
import { createImageIdsAndCacheMetaData } from './js/createImageIdsAndCacheMetaData'
import setCtTransferFunctionForVolumeActor from './js/setCtTransferFunctionForVolumeActor'
import setPetTransferFunctionForVolumeActor from './js/setPetTransferFunctionForVolumeActor'
import setPetColorMapTransferFunctionForVolumeActor from './js/setPetColorMapTransferFunctionForVolumeActor'
import store from '@/store'
import { changeURLStatic } from '@/utils/history.js'
import Viewport from './Viewport'
import CircleROITool from './tools/CircleROITool'
const {
ToolGroupManager,
Enums: csToolsEnums,
WindowLevelTool,
PanTool,
ZoomTool,
StackScrollMouseWheelTool,
synchronizers,
MIPJumpToClickTool,
VolumeRotateMouseWheelTool,
// SynchronizerManager,
// LengthTool,
EllipticalROITool,
// CircleROITool,
CrosshairsTool,
TrackballRotateTool,
ProbeTool,
ScaleOverlayTool,
// eslint-disable-next-line no-unused-vars
annotation
} = cornerstoneTools
const { MouseBindings } = csToolsEnums
const { ViewportType, BlendModes } = Enums
const { createCameraPositionSynchronizer, createVOISynchronizer } = synchronizers
let renderingEngine
const renderingEngineId = 'myRenderingEngine'
const volumeLoaderScheme = 'cornerstoneStreamingImageVolume' // Loader id which defines which volume loader to use
const ctVolumeName = 'CT_VOLUME_ID' // Id of the volume less loader prefix
const ctVolumeId = `${volumeLoaderScheme}:${ctVolumeName}` // VolumeId with loader id + volume id
const ptVolumeName = 'PT_VOLUME_ID'
const ptVolumeId = `${volumeLoaderScheme}:${ptVolumeName}`
const ctToolGroupId = 'CT_TOOLGROUP_ID'
const ptToolGroupId = 'PT_TOOLGROUP_ID'
const fusionToolGroupId = 'FUSION_TOOLGROUP_ID'
const mipToolGroupUID = 'MIP_TOOLGROUP_ID'
var axialCameraPositionSynchronizer
var ctVoiSynchronizer
var ptVoiSynchronizer
const viewportIds = {
CT: { AXIAL: 'CT_AXIAL', SAGITTAL: 'CT_SAGITTAL', CORONAL: 'CT_CORONAL' },
PT: { AXIAL: 'PT_AXIAL', SAGITTAL: 'PT_SAGITTAL', CORONAL: 'PT_CORONAL' },
FUSION: {
AXIAL: 'FUSION_AXIAL',
SAGITTAL: 'FUSION_SAGITTAL',
CORONAL: 'FUSION_CORONAL'
},
PETMIP: {
CORONAL: 'PET_MIP_CORONAL'
}
}
var element_ct
var element_pet
var element_fusion
var element_mip
var ctToolGroup
var ptToolGroup
var fusionToolGroup
var mipToolGroup
const axialCameraSynchronizerId = 'AXIAL_CAMERA_SYNCHRONIZER_ID'
const ctVoiSynchronizerId = 'CT_VOI_SYNCHRONIZER_ID'
const ptVoiSynchronizerId = 'PT_VOI_SYNCHRONIZER_ID'
export default {
name: 'Fusion',
components: { Viewport },
// props: {
// isReadingShowSubjectInfo: {
// type: Boolean,
// default: false
// }
// },
data() {
return {
activeIndex: 0,
activeTool: '',
loading: false,
fitType: 0,
rotateArr: [
// { label: this.$t('trials:reading:button:rotateDefault'), val: 1 }, // 默认值
{ label: this.$t('trials:reading:button:rotateVertical'), val: 2 }, // 垂直翻转
{ label: this.$t('trials:reading:button:rotateHorizontal'), val: 3 } // 水平翻转
// { label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4 }, // 左转90度
// { label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 }// 右转90度
],
isCurrentTask: false,
ctSeries: {},
petSeries: {},
isRender: false,
renderingEngineId: renderingEngineId,
ctVolumeId: `${volumeLoaderScheme}:${ctVolumeName}`,
ptVolumeId: `${volumeLoaderScheme}:${ptVolumeName}`,
ctVolume: null,
ptVolume: null,
isReadingShowSubjectInfo: false
}
},
computed: {
// ...mapGetters(['currentReadingTaskState'])
},
mounted() {
console.log(cornerstoneTools)
element_ct = document.getElementById('viewport1')
element_pet = document.getElementById('viewport2')
element_fusion = document.getElementById('viewport3')
element_mip = document.getElementById('viewport4')
if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '')
}
this.handleElemnetsClick()
this.initPage()
},
methods: {
initPage() {
const resizeObserver = new ResizeObserver(() => {
if (element_ct.style.width) {
console.log('Size changed')
renderingEngine = getRenderingEngine(renderingEngineId)
if (renderingEngine) {
this.$nextTick(() => {
renderingEngine.resize(true, false)
})
}
}
})
const elements = [
element_ct,
element_pet,
element_fusion
]
elements.forEach((element) => {
// element.style.width = '100%'
// element.style.height = '300px'
// Disable right click context menu so we can have right click tools
element.oncontextmenu = (e) => e.preventDefault()
resizeObserver.observe(element)
})
element_mip.oncontextmenu = (e) => e.preventDefault()
resizeObserver.observe(element_mip)
this.$nextTick(() => {
this.run()
})
},
async run() {
this.loading = true
// 初始化Cornerstone和相关库
await initLibraries()
renderingEngine = new RenderingEngine(renderingEngineId)
this.ctSeries = JSON.parse(sessionStorage.getItem('ctSeriesInfo'))
this.petSeries = JSON.parse(sessionStorage.getItem('petSeriesInfo'))
this.isCurrentTask = this.ctSeries.isCurrentTask
await this.getImages()
// 设置viewport
await this.setUpDisplay()
// 设置viewportTools and synchronizers
this.setUpToolGroups()
this.setUpSynchronizers()
// const axialCtViewport = renderingEngine.getViewport(viewportIds.CT.AXIAL)
// const { element } = axialCtViewport
eventTarget.addEventListener(cornerstoneTools.Enums.Events.ANNOTATION_ADDED, (e) => {
console.log('ADDED', e.detail.annotation)
// var annotations = annotation.state.getAnnotations('EllipticalROI', element)
// console.log(annotations)
})
this.isRender = true
this.loading = false
},
async getImages() {
const ctImageIds = await createImageIdsAndCacheMetaData({
modality: 'CT',
imageIds: this.ctSeries.imageIds
})
const ptImageIds = await createImageIdsAndCacheMetaData({
modality: 'PT',
imageIds: this.petSeries.imageIds
})
this.ctVolume = await volumeLoader.createAndCacheVolume(ctVolumeId, {
imageIds: ctImageIds
})
this.ptVolume = await volumeLoader.createAndCacheVolume(ptVolumeId, {
imageIds: ptImageIds
})
},
setUpToolGroups() {
cornerstoneTools.addTool(WindowLevelTool)
cornerstoneTools.addTool(ZoomTool)
cornerstoneTools.addTool(StackScrollMouseWheelTool)
cornerstoneTools.addTool(MIPJumpToClickTool)
cornerstoneTools.addTool(VolumeRotateMouseWheelTool)
cornerstoneTools.addTool(EllipticalROITool)
cornerstoneTools.addTool(CircleROITool)
cornerstoneTools.addTool(CrosshairsTool)
cornerstoneTools.addTool(TrackballRotateTool)
cornerstoneTools.addTool(ProbeTool)
cornerstoneTools.addTool(PanTool)
cornerstoneTools.addTool(ScaleOverlayTool)
ctToolGroup = ctToolGroup = ToolGroupManager.createToolGroup(ctToolGroupId)
ctToolGroup.addViewport(viewportIds.CT.AXIAL, renderingEngineId)
ptToolGroup = ToolGroupManager.createToolGroup(ptToolGroupId)
ptToolGroup.addViewport(viewportIds.PT.AXIAL, renderingEngineId)
fusionToolGroup = ToolGroupManager.createToolGroup(fusionToolGroupId)
fusionToolGroup.addViewport(viewportIds.FUSION.AXIAL, renderingEngineId)
const toolGroups = [ctToolGroup, ptToolGroup]
toolGroups.forEach((toolGroup) => {
toolGroup.addTool(PanTool.toolName)
toolGroup.addTool(ZoomTool.toolName)
toolGroup.addTool(StackScrollMouseWheelTool.toolName)
toolGroup.addTool(EllipticalROITool.toolName)
toolGroup.addTool(CircleROITool.toolName)
toolGroup.addTool(WindowLevelTool.toolName)
toolGroup.addTool(ProbeTool.toolName)
toolGroup.addTool(ScaleOverlayTool.toolName)
})
fusionToolGroup.addTool(PanTool.toolName)
fusionToolGroup.addTool(ZoomTool.toolName)
fusionToolGroup.addTool(StackScrollMouseWheelTool.toolName)
fusionToolGroup.addTool(EllipticalROITool.toolName, {
volumeId: ptVolumeId
})
fusionToolGroup.addTool(CircleROITool.toolName, {
volumeId: ptVolumeId
})
fusionToolGroup.addTool(ProbeTool.toolName)
fusionToolGroup.addTool(ScaleOverlayTool.toolName)
// Here is the difference in the toolGroups used, that we need to specify the
// volume to use for the WindowLevelTool for the fusion viewports
fusionToolGroup.addTool(WindowLevelTool.toolName, {
volumeId: ptVolumeId
});
[ctToolGroup, ptToolGroup, fusionToolGroup].forEach((toolGroup) => {
// toolGroup.setToolActive(ProbeTool.toolName, {
// bindings: [
// {
// mouseButton: MouseBindings.Primary // Left Click
// }
// ]
// })
toolGroup.setToolActive(PanTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Auxiliary // Middle Click
}
]
})
toolGroup.setToolActive(ZoomTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Secondary // Right Click
}
]
})
toolGroup.setToolActive(StackScrollMouseWheelTool.toolName)
// toolGroup.setToolPassive(EllipticalROITool.toolName)
// toolGroup.setToolPassive(CircleROITool.toolName)
// toolGroup.setToolPassive(ProbeTool.toolName)
// toolGroup.setToolPassive(WindowLevelTool.toolName)
// toolGroup.setToolEnabled(ScaleOverlayTool.toolName)
})
// MIP Tool Groups
mipToolGroup = null
if (!ToolGroupManager.getToolGroup(mipToolGroupUID)) {
mipToolGroup = ToolGroupManager.createToolGroup(mipToolGroupUID)
} else {
mipToolGroup = ToolGroupManager.getToolGroup(mipToolGroupUID)
}
mipToolGroup.addTool('VolumeRotateMouseWheel')
mipToolGroup.addTool('MIPJumpToClickTool', {
//
toolGroupId: ptToolGroupId
})
// Set the initial state of the tools, here we set one tool active on left click.
// This means left click will draw that tool.
mipToolGroup.setToolActive('MIPJumpToClickTool', {
bindings: [
{
mouseButton: MouseBindings.Primary // Left ClickR
}
]
})
// As the Stack Scroll mouse wheel is a tool using the `mouseWheelCallback`
// hook instead of mouse buttons, it does not need to assign any mouse button.
mipToolGroup.setToolActive('VolumeRotateMouseWheel')
mipToolGroup.addViewport(viewportIds.PETMIP.CORONAL, renderingEngineId)
},
// 设置测量工具启用(不会对输入作出反应)
setBasicToolActive(toolName) {
var toolGroupIds = [ctToolGroupId, ptToolGroupId, fusionToolGroupId]
toolGroupIds.forEach((toolGroupId) => {
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
if (this.activeTool === toolName) {
toolGroup.setToolPassive(toolName)
} else {
if (this.activeTool) {
toolGroup.setToolPassive(this.activeTool)
}
var bindings = []
if (toolName === 'Pan') {
bindings = [
{
mouseButton: MouseBindings.Auxiliary // Middle Click
},
{
mouseButton: MouseBindings.Primary // Left Click
}
]
} else if (toolName === 'Zoom') {
bindings = [
{
mouseButton: MouseBindings.Secondary // Right Click
},
{
mouseButton: MouseBindings.Primary // Left Click
}
]
} else {
bindings = [
{
mouseButton: MouseBindings.Primary // Left Click
}
]
}
toolGroup.setToolActive(toolName, {
bindings: bindings
})
}
})
if (this.activeTool === toolName) {
this.activeTool = ''
} else {
this.activeTool = toolName
}
},
// 截屏
saveImage() {
// const canvas = this.canvas.querySelector('canvas')
// var pictureBaseStr = canvas.toDataURL('image/png', 1)
// return pictureBaseStr
},
setUpSynchronizers() {
// const axialCameraSynchronizerId = 'AXIAL_CAMERA_SYNCHRONIZER_ID'
// const ctVoiSynchronizerId = 'CT_VOI_SYNCHRONIZER_ID'
// const ptVoiSynchronizerId = 'PT_VOI_SYNCHRONIZER_ID'
axialCameraPositionSynchronizer = createCameraPositionSynchronizer(
axialCameraSynchronizerId
)
ctVoiSynchronizer = createVOISynchronizer(ctVoiSynchronizerId)
ptVoiSynchronizer = createVOISynchronizer(ptVoiSynchronizerId);
// Add viewports to camera synchronizers
[
viewportIds.CT.AXIAL,
viewportIds.PT.AXIAL,
viewportIds.FUSION.AXIAL
].forEach((viewportId) => {
axialCameraPositionSynchronizer.add({
renderingEngineId,
viewportId
})
});
// Add viewports to VOI synchronizers
[
viewportIds.CT.AXIAL
].forEach((viewportId) => {
ctVoiSynchronizer.add({
renderingEngineId,
viewportId
})
});
[
viewportIds.FUSION.AXIAL
].forEach((viewportId) => {
// In this example, the fusion viewports are only targets for CT VOI
// synchronization, not sources
ctVoiSynchronizer.addTarget({
renderingEngineId,
viewportId
})
});
[
viewportIds.PT.AXIAL,
viewportIds.FUSION.AXIAL,
viewportIds.PETMIP.CORONAL
].forEach((viewportId) => {
ptVoiSynchronizer.add({
renderingEngineId,
viewportId
})
})
},
async setUpDisplay() {
// 创建 viewports
const viewportInputArray = [
{
viewportId: viewportIds.CT.AXIAL,
type: ViewportType.ORTHOGRAPHIC,
element: element_ct,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL
// background: [0, 0, 0]
}
},
{
viewportId: viewportIds.PT.AXIAL,
type: ViewportType.ORTHOGRAPHIC,
element: element_pet,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL,
background: [1, 1, 1]
}
},
{
viewportId: viewportIds.FUSION.AXIAL,
type: ViewportType.ORTHOGRAPHIC,
element: element_fusion,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL
// background: [0, 0, 0]
}
},
{
viewportId: viewportIds.PETMIP.CORONAL,
type: ViewportType.ORTHOGRAPHIC,
element: element_mip,
defaultOptions: {
orientation: Enums.OrientationAxis.CORONAL,
background: [1, 1, 1]
}
}
]
renderingEngine.setViewports(viewportInputArray)
// Set the volumes to load
this.ptVolume.load()
this.ctVolume.load()
// Set volumes on the viewports
await setVolumesForViewports(
renderingEngine,
[
{
volumeId: ctVolumeId,
callback: setCtTransferFunctionForVolumeActor
}
],
[viewportIds.CT.AXIAL]
)
await setVolumesForViewports(
renderingEngine,
[
{
volumeId: ptVolumeId,
callback: setPetTransferFunctionForVolumeActor
}
],
[viewportIds.PT.AXIAL]
)
await setVolumesForViewports(
renderingEngine,
[
{
volumeId: ctVolumeId,
callback: setCtTransferFunctionForVolumeActor
},
{
volumeId: ptVolumeId,
callback: setPetColorMapTransferFunctionForVolumeActor
}
],
[viewportIds.FUSION.AXIAL]
)
// Calculate size of fullBody pet mip
const ptVolumeDimensions = this.ptVolume.dimensions
// Only make the MIP as large as it needs to be.
const slabThickness = Math.sqrt(
ptVolumeDimensions[0] * ptVolumeDimensions[0] +
ptVolumeDimensions[1] * ptVolumeDimensions[1] +
ptVolumeDimensions[2] * ptVolumeDimensions[2]
)
setVolumesForViewports(
renderingEngine,
[
{
volumeId: ptVolumeId,
callback: setPetTransferFunctionForVolumeActor,
blendMode: BlendModes.MAXIMUM_INTENSITY_BLEND,
slabThickness
}
],
[viewportIds.PETMIP.CORONAL]
)
this.initializeCameraSync(renderingEngine)
// Render the viewports
renderingEngine.render()
},
initCameraSynchronization(sViewport, tViewport) {
// Initialise the sync as they viewports will have
// Different initial zoom levels for viewports of different sizes.
const camera = sViewport.getCamera()
tViewport.setCamera(camera)
},
initializeCameraSync(renderingEngine) {
// The fusion scene is the target as it is scaled to both volumes.
// TODO -> We should have a more generic way to do this,
// So that when all data is added we can synchronize zoom/position before interaction.
const axialCtViewport = renderingEngine.getViewport(viewportIds.CT.AXIAL)
const axialPtViewport = renderingEngine.getViewport(viewportIds.PT.AXIAL)
const axialFusionViewport = renderingEngine.getViewport(
viewportIds.FUSION.AXIAL
)
this.initCameraSynchronization(axialFusionViewport, axialCtViewport)
this.initCameraSynchronization(axialFusionViewport, axialPtViewport)
renderingEngine.render()
},
resetViewport() {
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewportIds = [
'CT_AXIAL',
'PT_AXIAL',
'FUSION_AXIAL'
]
viewportIds.forEach(viewportId => {
const viewport = renderingEngine.getViewport(viewportId)
viewport.resetCamera()
viewport.render()
})
},
showPanel(e) {
// console.log(e.currentTarget.parentNode.parentNode)
// e.currentTarget.parentNode.parentNode.lastChild.style.display = 'block'
e.currentTarget.firstChild.lastChild.style.display = 'block'
},
handleMouseout(e) {
e.currentTarget.firstChild.lastChild.style.display = 'none'
},
closePetct() {
cornerstoneTools.destroy()
eventTarget.reset()
cache.purgeCache()
renderingEngine.destroy()
// metaData.removeProvider(fakeMetaDataProvider)
imageLoader.unregisterAllImageLoaders()
ToolGroupManager.destroyToolGroup('stack')
this.$emit('close')
},
setDicomCanvasRotate(v) {
// rotateArr: [
// { label: this.$t('trials:reading:button:rotateDefault'), val: 1 }, // 默认值
// { label: this.$t('trials:reading:button:rotateVertical'), val: 2 }, // 垂直翻转
// { label: this.$t('trials:reading:button:rotateHorizontal'), val: 3 }, // 水平翻转
// { label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4 }, // 左转90度
// { label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 }// 右转90度
// ],
// Get the rendering engine
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewportIds = [
'CT_AXIAL',
'PT_AXIAL',
'FUSION_AXIAL'
]
viewportIds.forEach(viewportId => {
const viewport = renderingEngine.getViewport(viewportId)
console.log(viewport.getCamera())
const { flipHorizontal, flipVertical } = viewport.getCamera()
// Flip the viewport horizontally
if (v === 2) {
viewport.setCamera({ flipHorizontal: !flipHorizontal })
} else if (v === 3) {
viewport.setCamera({ flipVertical: !flipVertical })
} else if (v === 4) {
viewport.setCamera({ viewAngle: -90 })
} else if (v === 5) {
viewport.setCamera({ viewAngle: 90 })
}
viewport.render()
})
},
handleElemnetsClick() {
var elements = [element_ct, element_pet, element_fusion, element_mip]
elements.forEach((el, index) => {
el.addEventListener('click', () => {
this.activeIndex = index + 1
})
})
},
// 鼠标移入测量工具时,判断工具是否可激活
enter(e, toolName) {
}
}
}
</script>
<style lang="scss" scoped>
.dicom-viewer-container{
display:flex;
flex-direction: column;
height: 100%;
// padding: 5px;
background-color: #000;
}
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.dicom-tools{
box-sizing: border-box;
width: 100%;
height: 61px;
padding: 0 5px;
border: 1px solid #727272;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.tool-wrapper{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-right: 30px;
.icon{
padding: 5px;
border: 1px solid #404040;
cursor: pointer;
text-align: center;
.svg-icon{
font-size:20px;
color:#ddd;
}
}
.text{
position: relative;
font-size: 12px;
margin-top: 5px;
color: #d0d0d0;
display: none;
}
}
.tool_active{
background-color: #607d8b;
}
.tool_disabled{
cursor:not-allowed
}
.icon:hover{
background-color: #607d8b;
}
.dropdown {
position: relative;
display: inline-block;
.icon-content{
display: flex;
align-items: center;
border: 1px solid #404040;
}
.text{
text-align: center;
}
.tool-icon{
padding: 5px;
cursor: pointer;
text-align: center;
.svg-icon{
font-size:20px;
color:#ddd;
}
}
.arrow-icon{
cursor: pointer;
padding: 7px 2px 7px 0px;
}
.arrow-icon:hover{
background-color: #607d8b;
}
.icon-content-d:hover{
background-color: #607d8b;
}
.tool-icon-d{
padding: 5px;
.svg-icon{
font-size:20px;
color:#ddd;
}
}
}
.dropdown-content {
display: none;
position: absolute;
background-color: #383838;
color: #fff;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 9999;
font-size: 12px;
ul{
list-style: none;
margin: 0;
padding: 0;
text-align: center;
li{
a{
display: block;
padding: 5px;
}
}
}
ul li:hover{
background-color: #727272;
}
}
.layout-content ul li{
border-top:1px solid #ddd;
border-left:1px solid #ddd;
}
.layout-content ul .flex_row{
// border: 1px solid #ddd;
display: flex;
justify-content: space-between;
flex-direction: row;
align-items: center;
// padding: 2px;
margin-bottom: 2px;
}
.layout-content ul .flex_column{
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: center;
margin-bottom: 2px;
}
.layout_box_1_1{
flex:1;
// border: 1px solid #ddd;
line-height: 30px;
font-size: 12px;
text-align: center;
border-bottom:1px solid #ddd;
border-right:1px solid #ddd;
// padding: 0 5px;
}
.layout_box_1_2{
flex:1;
line-height: 15px;
font-size: 10px;
text-align: center;
border-bottom:1px solid #ddd;
border-right:1px solid #ddd;
}
.layout-content li .layout_box_1_1 :last-child{
color: red;
}
.layout-content li:hover {
cursor: pointer;
background-color: #727272;
}
}
.dicom-datas{
box-sizing: border-box;
flex: 1;
margin-top: 5px;
height: 100%;
display: flex;
flex-direction: row;
justify-content: flex-start;
overflow: hidden;
.form-container{
width: 350px;
height: 100%;
border: 1px solid #727272;
}
.dicom-container{
box-sizing: border-box;
flex: 1;
height: 100%;
border: 1px solid #727272;
}
.measurement-container{
overflow-y: auto;
}
.box{
display: grid;
box-sizing: border-box;
height: 100%;
padding: 0;
.item{
box-sizing: border-box;
position: relative;
border: 1px solid rgba(255, 255, 255, 0.21);
position: relative;
&_active{
// border: 2px solid #ffeb3b;fff
border: 1px dashed #428bca;
}
}
}
.box_2_2{
grid-template-columns: repeat(2, 50%); //1列占50%
grid-template-rows: repeat(2, 50%); //1行占50%
}
}
</style>