cornerstone系列1 - cornerstoneTools的synchronize(同步化)
前言
由于工作接触影像项目,用到了cornerstone及其相关的库,网上感觉资料也挺少,于是用到啥记录啥吧。开始第一篇,cornerstoneTools的Synchronizer相关。
在Example页面中( https://tools.cornerstonejs.org/examples )可以看到有Synchronization这一列,就是同步的例子,比如扫描定位线、不同的图像同步修改调窗等。总之,运用的场景就是需要状态联动的地方。
关于Synchronizer
cornerstoneTools提供了一个同步化的功能,文档里找到相关内容,可以从Synchronizer源码看它的使用方法。
首先export一个Synchronizer的类,参数是event和handler。event是注册的事件名(可以是多个用空格分开),当事件触发时,该synchronization就会触发。handler是synchronization触发时,target element要执行的方法。
sourceElements和targetElements是Synchronizer的两个重要属性,分别存放了同步的源和目标对象,上面说到event触发,即是触发了源对象(sourceElements)上注册的事件,触发后目标对象(targetElements)会执行handler。
部分实例上的方法 :
addSource
:参数为element,添加到sourceElements,给该element注册事件(Synchronizer的event)
addTarget
:参数为element,添加到targetElements
add
:参数为element,调用了addSource和addTarget
(remove同理
getSourceElements
:获取源对象集合
getTargetElements
:获取目标对象集合
setViewport
:调用了cornerstone的setViewport
|
|
实际场景
我这边的场景是,要实现多个影像序列viewport的相对同步(如序列1调窗windowWidth和windowCenter各增加了100,那同步的序列2也要这两个属性在原本的基础上各加100酱紫,有点废话- -),那先想下大概要做的事:
- 自定义一个相对同步事件
- 实例化Synchronizer,添加好source和target
- 新建一个handler,用来处理target对象(也是Synchronizer的参数)
- 在操作的时候触发自定义事件
- …
1.自定义事件
|
|
从设想中可以感觉到,要统一控制所有的改变,肯定要对原本cornerstone的setViewport做手脚,所以这个文件就写一些对cornerstone-core使用的补充。
2.Synchronizer实例化
|
|
第一个参数就是上面定义的事件,第二个参数是handler,由于我这边在cornerstoneTools上做了很多扩展,所以直接加到cornerstoneTools上了。在开启同步的时候调用add方法,把elemen同时t加到source和target上(因为是同步功能,所以随便哪个都可以当源)
3.新建handler
从Synchronizer源码中可以看到handler在调用时传入的参数,实例本身、触发的源对象、当前目标对象、事件传过来的详情内容。这边主要要靠 eventData
来传递操作详情。
可见eventData
的源头是 onEvent
方法中的参数,即 addSource
时注册的事件。cornerstone这儿事件的触发调用 cornerstone.triggerEvent(el, type, detail)
方法,detail就是最终传过来的e.detail,这样就明了了,只要trigger的时候带上需要的数据即可。
|
|
下面就开始写handler,需求是所有的变化都是相对变化,所以在项目中其实有几种情况:
1.比如鼠标左键的拖动改变调窗、缩放、移动这种操作,需要计算相对位移,所以监听鼠标事件,记录mousedown时的viewport,作为 originViewport
在 eventData
中传过来
2.比如固定窗高窗位的设置,就不需要 originViewport
,只要直接把 targetElement
的对应属性设置成sourceElement viewport的属性值就行了
3.比如顺时针旋转这种操作,需要知道旋转的度数,所以传入 changeData
activeTool
是为了区别当前做的是什么操作
|
|
4.事件的触发
上面也提到了,就是在操作的时候调用 cornerstone.triggerEvent(el, type, detail)
方法,按设计调用的地方有两个。
1.鼠标操作处(3中的情况1),当mouseup的时候触发,传过去当前的tool和mousedown时存下的originViewport。
2.全部setViewport的地方(准确说是所有使得当前的source的图像改变的地方),由于原本修改viewport的地方都是调用的setViewport,所以要对这个方法扩展一下,重新定义一个 setViewportWithEvent
方法代替原本调用setViewport的地方。
|
|
最后
同步化这块儿把大体设计了解了后就比较容易了,的确对很多功能的实现很有帮助,比如上文的联动,还有扫描定位线、序列图像同步滚动等等场景。还有些没用过的属性、方法,用到的时候只能多读读源码了- -