我无法在任何地方找到直接的答案。如何在单击svg圈时显示下拉菜单?在点击形状之前我不希望它显示。有谁可以帮助我吗?
答案 0 :(得分:6)
下载此内容并加入您的html:https://github.com/patorjk/d3-context-menu
点击一个圆圈即可使用
circle.on('contextmenu', d3.contextMenu(menu)); // attach menu to element
如果你想要插件,那就是:)
修改
没有插件
如果您不想要插件只需创建要显示的内容列表,请阻止默认行为,右键单击显示创建的列表,然后单击其他任何位置隐藏它。
这是一个小提琴(不是我的):http://jsfiddle.net/thatoneguy/u2kJq/727/
他创建的列表:
<ul class='custom-menu'>
<li data-action = "first">First thing</li>
<li data-action = "second">Second thing</li>
<li data-action = "third">Third thing</li>
</ul>
这将在右键单击时显示。现在要使用D3实现此功能,您可以像上面的小提琴一样使用event.preventDefault();
,您必须使用d3.event.preventDefault();
。您还必须定位菜单,因此将css顶部和左侧更改为鼠标位置的位置:
css({
top: d3.event.pageY + "px",
left: d3.event.pageX + "px"
});
以下是我所描述的简单实现:
var w = 500;
var h = 50;
var dataset = [5, 10, 15, 20, 25];
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})
.attr("cy", h / 2)
.attr("r", function(d) {
return d;
})
.on("contextmenu", function(event) {
// Avoid the real one
d3.event.preventDefault();
// Show contextmenu
$(".custom-menu").finish().toggle(100).
// In the right position (the mouse)
css({
top: d3.event.pageY + "px",
left: d3.event.pageX + "px"
});
});;
//$(document).bind
// If the document is clicked somewhere
$(document).bind("mousedown", function(e) {
// If the clicked element is not the menu
if (!$(e.target).parents(".custom-menu").length > 0) {
// Hide it
$(".custom-menu").hide(100);
}
});
// If the menu element is clicked
$(".custom-menu li").click(function() {
// This is the triggered action name
switch ($(this).attr("data-action")) {
// A case for each action. Your actions here
case "first":
alert("first");
break;
case "second":
alert("second");
break;
case "third":
alert("third");
break;
}
// Hide it AFTER the action was triggered
$(".custom-menu").hide(100);
});
.custom-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
font-family: sans-serif;
background: #FFF;
color: #333;
border-radius: 5px;
}
.custom-menu li {
padding: 8px 12px;
cursor: pointer;
}
.custom-menu li:hover {
background-color: #DEF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
<ul class='custom-menu'>
<li data-action = "first">First thing</li>
<li data-action = "second">Second thing</li>
<li data-action = "third">Third thing</li>
</ul>
</body>
如果您想在点击其中一个菜单项时执行某些操作,可以在html中使用onclick
,如下所示:
<li onclick='doSomething()' data-action = "third">Third thing</li>
或者你可以给个别项目一个这样的id:
<li id='listItemOne' data-action = "third">Third thing</li>
然后添加事件监听器:
document.getElementById('listItemOne').addEventListener('click', doSomething)
答案 1 :(得分:5)
@thisOneGuy给出了一个很好的答案,但是因为我已经编码了,所以这是一个用svg
构建上下文菜单的解决方案:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.4.6" data-semver="3.4.6" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.6/d3.min.js"></script>
<style>
svg {
font: 12px sans-serif;
}
</style>
</head>
<body>
<script>
var menu = [{
title: 'A really, really long item',
action: function(elem, d, i) {
console.log('Item #1 clicked!');
console.log('The data for this circle is: ' + d);
}
}, {
title: 'Item #2',
action: function(elem, d, i) {
console.log('You have clicked the second item!');
console.log('The data for this circle is: ' + d);
}
}]
var data = [1, 2, 3];
var g = d3.select('body').append('svg')
.on('click', function(){
m.style('display', 'none');
})
.attr('width', 500)
.attr('height', 400)
.append('g');
g.selectAll('circles')
.data(data)
.enter()
.append('circle')
.attr('r', 30)
.attr('fill', 'steelblue')
.attr('cx', function(d) {
return 100;
})
.attr('cy', function(d) {
return d * 100;
})
.on('contextmenu', function(d) {
var coors = d3.mouse(this);
m.attr('transform', 'translate(' + coors[0] + ',' + coors[1] + ')');
m.style('display', 'block');
m.datum(d);
d3.event.preventDefault();
});
/* build context menu */
var m = g.append("g")
m.style('display', 'none');
var r = m.append('rect')
.attr('height', menu.length * 25)
.style('fill', "#eee");
var t = m.selectAll('menu_item')
.data(menu)
.enter()
.append('g')
.attr('transform', function(d, i) {
return 'translate(' + 10 + ',' + ((i + 1) * 20) + ')';
})
.on('mouseover', function(d){
d3.select(this).style('fill', 'steelblue');
})
.on('mouseout', function(d){
d3.select(this).style('fill', 'black');
})
.on('click', function(d,i){
d.action(d, d3.select(this.parentNode).datum(), i);
})
.append('text')
.text(function(d) {
return d.title;
});
var w = 0;
t.each(function(d){
var l = this.getComputedTextLength();
if (l > w) w = l;
})
r.attr('width', w + 20);
</script>
</body>
</html>