如何在OpenSeadragon的DZI图像上按像素坐标放置标记?
```
我可以在图像正中心(归一化坐标`0.5,0.5`)放置图片标记:
```javascript
var point = new OpenSeadragon.Point(0.5,0.5)
console.log("point ", point);
var img = document.createElement("img");
img.src = "balls/orange.gif";
viewer.addOverlay(img, point);
```
但当我尝试将**图像像素坐标**转换为视口坐标来放置标记时,转换无效,标记无法显示在屏幕上:
```javascript
var point = viewer.viewport.imageToViewportCoordinates(92060,40504);
```
控制台输出的坐标仍是输入的像素值,导致标记出现在视口外。
需要解决的问题:
- 如何正确将图像像素坐标转换为视口坐标?
- 如何实现标记的显示/隐藏切换?
- 如何给标记添加悬停弹出注释?
- 有没有OpenSeadragon内置标记相关的建议?
解决方案
一、图像像素坐标转视口坐标的正确方式
你之前的错误在于:viewer.viewport.imageToViewportCoordinates()接收的是图像归一化坐标(范围0-1,相对于图像宽高),而非原始像素坐标。另外必须确保图像加载完成后再进行转换,否则无法获取图像的实际尺寸。
方法1:通过归一化坐标转换
viewer.addHandler('open', function() { // 获取加载的图像实例 var imageItem = viewer.world.getItemAt(0); // 获取图像的实际像素尺寸 var imageSize = imageItem.source.dimensions; // 目标像素坐标 var pixelX = 92060; var pixelY = 40504; // 转为图像归一化坐标(x/宽,y/高) var normalizedPoint = new OpenSeadragon.Point(pixelX / imageSize.x, pixelY / imageSize.y); // 转为视口坐标 var viewportPoint = viewer.viewport.imageToViewportPoint(normalizedPoint); // 添加标记 var img = document.createElement("img"); img.src = "balls/orange.gif"; viewer.addOverlay(img, viewportPoint); });
方法2:直接使用图像项的转换方法
每个图像实例提供了imageToViewportCoordinates()方法,可直接传入像素坐标完成转换:
viewer.addHandler('open', function() { var imageItem = viewer.world.getItemAt(0); var pixelPoint = new OpenSeadragon.Point(92060, 40504); // 直接将像素坐标转为视口坐标 var viewportPoint = imageItem.imageToViewportCoordinates(pixelPoint); // 添加标记 var img = document.createElement("img"); img.src = "balls/orange.gif"; viewer.addOverlay(img, viewportPoint); });
二、标记的显示/隐藏切换
将所有标记元素存入数组,通过控制元素的display属性实现批量切换:
// 存储所有标记(含注释弹窗) var markers = []; // 封装添加标记的函数 function addMarker(pixelX, pixelY) { var imageItem = viewer.world.getItemAt(0); var viewportPoint = imageItem.imageToViewportCoordinates(new OpenSeadragon.Point(pixelX, pixelY)); var img = document.createElement("img"); img.src = "balls/orange.gif"; viewer.addOverlay(img, viewportPoint); markers.push(img); return img; } // 切换标记显示状态 function toggleMarkers(isShow) { markers.forEach(marker => { marker.style.display = isShow ? 'block' : 'none'; }); } // 调用示例 toggleMarkers(true); // 显示所有标记 toggleMarkers(false); // 隐藏所有标记
三、添加悬停弹出注释
给标记元素绑定鼠标事件,动态创建并定位注释弹窗:
function addMarkerWithTooltip(pixelX, pixelY, tooltipText) { var imageItem = viewer.world.getItemAt(0); var viewportPoint = imageItem.imageToViewportCoordinates(new OpenSeadragon.Point(pixelX, pixelY)); // 创建标记图片 var img = document.createElement("img"); img.src = "balls/orange.gif"; viewer.addOverlay(img, viewportPoint); // 创建注释弹窗 var tooltip = document.createElement('div'); tooltip.style.position = 'absolute'; tooltip.style.background = '#fff'; tooltip.style.padding = '4px 8px'; tooltip.style.border = '1px solid #ccc'; tooltip.style.borderRadius = '4px'; tooltip.style.display = 'none'; tooltip.style.zIndex = 999; tooltip.textContent = tooltipText; document.body.appendChild(tooltip); // 鼠标悬停显示弹窗 img.addEventListener('mouseover', function() { var rect = img.getBoundingClientRect(); // 弹窗定位在标记右侧 tooltip.style.left = `${rect.right + 5}px`; tooltip.style.top = `${rect.top}px`; tooltip.style.display = 'block'; }); // 鼠标移出隐藏弹窗 img.addEventListener('mouseout', function() { tooltip.style.display = 'none'; }); // 存入数组管理 markers.push({img, tooltip}); } // 调用示例 addMarkerWithTooltip(92060, 40504, '这是一个自定义注释内容');
四、OpenSeadragon标记扩展建议
OpenSeadragon本身没有内置的标记组件,但可以通过Overlay API实现灵活扩展:
- 使用SVG作为Overlay:相比图片标记,SVG图形(圆形、箭头、文本)缩放时不会模糊,适合绘制自定义形状标记
- 封装标记类:将坐标转换、事件绑定、显示隐藏逻辑封装成统一的
Marker类,方便批量管理大量标记 - 利用官方示例:参考OpenSeadragon官方提供的Overlay相关示例,实现更复杂的交互效果
内容的提问来源于stack exchange,提问作者anthony
相关产品推荐
相关产品推荐

