问题描述
前端有一个svg绘制的circle,我需要实现这样的效果:首先,在圆环上点击左键,然后拖动,最后抬起左键。这样可以选中圆环的一段区域(这段区域会加阴影),此时点击右键可以弹出自定义的菜单。
问题在于,右键菜单出现时,浏览器默认的右键菜单也会出现,因此需要禁用。
解决方案
// 右键点击事件
svg.addEventListener('contextmenu', (e) => {
// 阻止浏览器的默认右键菜单
event.preventDefault();
// 如果选中区域可见,显示右键菜单
// arcPath是我选中的区域,此时会出现阴影
if (arcPath.style.display === "block") {
// startSelectSeqPos, curSelectSeqPos是经过计算的起终位置
showContextMenu(e, startSelectSeqPos, curSelectSeqPos);
}
});
// 显示右键菜单
function showContextMenu(event, start, end) {
console.log(start);
event.preventDefault();
// 创建右键菜单
const menu = d3.select("body").append("div")
.attr("class", "context-menu")
.style("position", "absolute")
.style("left", `${event.pageX}px`)
.style("top", `${event.pageY}px`)
.html("<div id='copy-sequence'>复制</div>");
// 复制序列
menu.select("#copy-sequence").on("click", function() {
const selectedSequence = plasmidSequence.slice(start, end);
navigator.clipboard.writeText(selectedSequence);
menu.remove();
});
// 点击其他地方隐藏菜单
d3.select("body").on("click", function() {
menu.remove();
});
}
但是这个代码有个问题是,当你选中了序列,在其他地方右键的时候会出现好几个右键菜单。下面会做修改,同时使用bootstrap5。
使用bootstrap5
首先引入bootstrap5:
<!-- 地址省略 -->
<link href="/.../bootstrap.min.css" rel="stylesheet">
<!-- 引入 Bootstrap 5 JS(包括 Popper.js) -->
<script src="/.../bootstrap.bundle.min.js"></script>
在body里增加菜单:
<!-- 右键菜单 -->
<div id="contextMenu" class="dropdown-menu">
<button class="dropdown-item" id="copy-sequence">复制</button>
</div>
然后修改函数showContextMenu()
:
function showContextMenu(event, start, end) {
event.preventDefault(); // 禁止默认右键菜单
// 获取右键菜单元素
const contextMenu = document.getElementById("contextMenu");
// 设置菜单位置
contextMenu.style.display = "block";
contextMenu.style.position = "absolute";
contextMenu.style.left = `${event.pageX}px`;
contextMenu.style.top = `${event.pageY}px`;
// 复制序列
document.getElementById("copy-sequence").onclick = function() {
const selectedSequence = plasmidSequence.slice(start, end);
navigator.clipboard.writeText(selectedSequence);
contextMenu.style.display = "none"; // 隐藏菜单
};
// 点击其他地方隐藏菜单
document.addEventListener("click", function hideMenu() {
contextMenu.style.display = "none";
document.removeEventListener("click", hideMenu);
});
}