style
body{
margin: 0;
padding: 20px;
}
canvas{
background-color: #000;
}
.info{
position: fixed;
right: 50px;
top: 50%;
transform: translateY(-50%);
border-radius: 5px;
background-color: #333;
color: #fff;
padding: 16px;
max-width: 420px;
word-break: break-all;
max-height: 520px;
overflow: hidden auto;
}
.info p{
margin:5px 0;
}
.info span{
font-size: 18px;
}
.draw-data{
line-height: 1.6;
}
html
<p class="tools">
<button data-tool="Angle">角度</button>
<button data-tool="ArrowAnnotate">箭头</button>
<button data-tool="RectangleRoi">矩形</button>
<button data-tool="EllipticalRoi">椭圆形</button>
<button data-tool="CircleRoi">圆形</button>
<button data-tool="Bidirectional">双向测量</button>
<button data-tool="CobbAngle">Cobb角</button>
<button data-tool="FreehandRoi">手绘</button>
<button data-tool="Length">长度测量</button>
<button data-tool="Probe">探针</button>
<button data-tool="TextMarker">标注</button>
</p>
<div id="dicomImage" oncontextmenu="return false" onmousedown="return false"></div>
<div class="info">
<p>工具: <span class="tool"></span></p>
<div class="data-wrap">
<p>绘制数据:</p>
<p class="draw-data"></p>
</div>
<p>图像ID: <span class="imgId"></span></p>
<p>放大倍数: <span class="scale"></span></p>
<p>水平翻转: <span class="hflip"></span></p>
<p>垂直翻转: <span class="vflip"></span></p>
<p>位移: <span class="translate"></span></p>
<p>反白: <span class="invert"></span></p>
<p>旋转度数: <span class="rotate"></span></p>
<p>窗口中心: <span class="wc"></span></p>
<p>窗宽: <span class="ww"></span></p>
<p>voi : <span class="voi"></span></p>
</div>
<script src="https://unpkg.com/hammerjs@2.0.8/hammer.js"></script>
<script src="https://unpkg.com/cornerstone-core@2.3.0/dist/cornerstone.js"></script>
<script src="https://unpkg.com/cornerstone-math@0.1.9/dist/cornerstoneMath.min.js"></script>
<script src="https://unpkg.com/cornerstone-wado-image-loader@3.3.1/dist/cornerstoneWADOImageLoader.min.js"></script>
<script src="https://unpkg.com/cornerstone-web-image-loader@2.1.1/dist/cornerstoneWebImageLoader.min.js"></script>
<script src="https://unpkg.com/cornerstone-tools@5.1.4/dist/cornerstoneTools.js"></script>
<script src="https://unpkg.com/dicom-parser@1.8.7/dist/dicomParser.min.js"></script>
初始化内容
cornerstoneTools.external.cornerstone = cornerstone;
cornerstoneTools.external.Hammer = Hammer;
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneTools.init();
const $ = name => document.querySelector(name);
const dicomImage = $("#dicomImage");
const H = document.documentElement.clientHeight - 100;
const W = document.documentElement.clientWidth / 2;
const toolState = {};
dicomImage.style.width = W + "px";
dicomImage.style.height = H + "px";
let imageId = "wadouri:http://127.0.0.1/download/1.dcm";
cornerstone.enable(dicomImage);
cornerstone.loadAndCacheImage(imageId).then(img => {
cornerstone.displayImage(dicomImage, img);
});
let activeToolName = ""; // 激活工具名称
let prevToolName = ""; // 上一个激活工具名称
处理激活工具
$(".tools").onclick = function(e){
const target = e.target;
const tool = target.dataset.tool;
if(target.nodeName != "BUTTON" && !tool)return;
if(prevToolName){
cornerstoneTools.setToolPassive(prevToolName); // 把上一个激活工具冻结
}
activeToolName = tool + "Tool";
if(!toolState[activeToolName]){
// 不能重复 addTool
cornerstoneTools.addTool(cornerstoneTools[activeToolName], tool === "TextMarker" ? marker() : {});
toolState[activeToolName] = true;
}
prevToolName = tool;
// 激活工具
cornerstoneTools.setToolActive(tool, {
mouseButtonMask: 1
});
}
// 标注工具要有初始配置
function marker(){
return {
configuration: {
markers: ["F5", "F4", "F3", "F2", "F1"], //标记数组
current: 'F3', //要对应markers
loop: true, //是否循环
ascending: false, //true 降序 false 升序
changeTextCallback: function(data, eventData, doneChangingTextCallback) {
data.visible = true; //是否可见, 默认true
data.color = "#38f"; //文字颜色
data.text = "内容"; //修改内容 这里修改了也没有,因为默认使用第二个参数
doneChangingTextCallback(data, prompt('改变标注:'));
}
}
}
}
监听测量添加
dicomImage.addEventListener(cornerstoneTools.EVENTS.MEASUREMENT_ADDED, e=>{
// toolName 是当前使用的工具
activeToolName = e.detail.toolName + "Tool"
})
监听测量完成
dicomImage.addEventListener(cornerstoneTools.EVENTS.MEASUREMENT_COMPLETED,e=>{
console.log("绘制完成: ", activeToolName)
activeToolName = "";
})
监听鼠标抬起
dicomImage.addEventListener(cornerstoneTools.EVENTS.MOUSE_UP,e=>{
const detail = e.detail;
if(activeToolName || !prevToolName || detail.event.button != 2)return;
const imageId = detail.image.imageId; // 获取imageId
const viewport = detail.viewport; // 获取viewport属性
// 通过元素获取工具状态,状态在通过imageId获取使用过的工具,就是在这张图片上显示的绘制内容
const tools = cornerstoneTools.getElementToolStateManager(dicomImage).toolState[imageId];
for(let item of Object.keys(tools)){ // 遍历key值
const data = tools[item].data; // 通过key 拿到每个工具绘制的数据,多个绘制就会有多条数据
for(let i = 0, len = data.length; i < len; i++){
const tool = data[i];
if(tool.active){ // 如果工具激活,那么就为true,激活状态就是绘制内容高亮显示
$(".imgId").innerText = imageId;
$(".draw-data").innerText = JSON.stringify(tool);
$(".tool").innerText = item;
$(".wc").innerText = viewport.voi.windowCenter;
$(".ww").innerText = viewport.voi.windowWidth;
$(".rotate").innerText = viewport.rotation;
$(".scale").innerText = viewport.scale;
$(".translate").innerText = `x : ${viewport.translation.x},y : ${viewport.translation.y}`;
$(".vflip").innerText = viewport.vflip;
$(".hflip").innerText = viewport.hflip;
$(".invert").innerText = viewport.invert;
$(".voi").innerText = JSON.stringify(viewport.voi)
return
}
}
}
})
上述是使用 cornerstoneTools的事件获取信息,鼠标要在200毫秒后才能抬起,否则是不会触发事件。
也可以使用鼠标移动的方式,这个就要考虑防抖或节流了。
直接在元素身上用mousedown也可,只是没有 e.detail属性,要自己获取当前的图像。
使用 mousedown 获取
dicomImage.addEventListener("mousedown",e=>{
if(e.button != 2 || activeToolName || !prevToolName)return;
const img = cornerstone.getImage(dicomImage); // 获取当前激活图像
const viewport = cornerstone.getViewport(dicomImage); // 获取当前图像 viewport
const tools = cornerstoneTools.getElementToolStateManager(dicomImage).toolState[img.imageId];
for(let item of Object.keys(tools)){
const data = tools[item].data;
for(let i = 0, len = data.length; i < len; i++){
const tool = data[i];
if(tool.active){
$(".imgId").innerText = img.imageId;
$(".draw-data").innerText = JSON.stringify(tool);
$(".tool").innerText = item;
$(".wc").innerText = viewport.voi.windowCenter;
$(".ww").innerText = viewport.voi.windowWidth;
$(".rotate").innerText = viewport.rotation;
$(".scale").innerText = viewport.scale;
$(".translate").innerText = `x : ${viewport.translation.x},y : ${viewport.translation.y}`;
$(".vflip").innerText = viewport.vflip;
$(".hflip").innerText = viewport.hflip;
$(".invert").innerText = viewport.invert;
$(".voi").innerText = JSON.stringify(viewport.voi)
return
}
}
}
})
这是两种方案能获取工具信息。