我正在创建基于具有回调函数的javascript数组的上下文菜单,但是有两个问题
无法隐藏子菜单(在删除部分上)。
无法在适当的层次结构中显示子菜单(移动到Sibling Section后无法返回子部分的子菜单)。
我的代码:
d3.contextMenu = function (menu, openCallback) {
// create the div element that will hold the context menu
d3.selectAll('.d3-context-menu').data([1])
.enter()
.append('div')
.attr('class', 'd3-context-menu');
// close menu
d3.select('body').on('click.d3-context-menu', function() {
d3.select('.d3-context-menu').style('display', 'none');
});
// this gets executed when a contextmenu event occurs
return function(data, index) {
var elm = this;
d3.selectAll('.d3-context-menu').html('');
var list = d3.selectAll('.d3-context-menu').append('ul');
list.selectAll('li').data(menu).enter()
.append('li')
.html(function(d) {
return d.title;
})
.on('click', function(d, i) {
d.onMouseClick(elm, data, index);
})
.on('mouseover',function(d,i){
d.onMouseOver(elm,data,index);
if(d.chidernItems.length>0 )
{
d3.select(this).selectAll("ul").remove();
d3.select(this)
.append("ul")
.selectAll("li")
.data(d.chidernItems)
.enter().append("li")
.text(function(d) { return d.title; })
.on("mouseover", function(d,i){
d.onMouseOver(elm,data,index);
})
.on('click', function(d, i) {
d.onMouseClick(elm, data, index);
})
.on('mouseout',function(d,i){
d3.select(this).remove();
});
}
else
return false;
})
.on('mouseout',function(d,i){
if(d.chidernItems.length==0 )
{
d3.select(this).selectAll("ul").remove();
}
});
// the openCallback allows an action to fire before the menu is displayed
// an example usage would be closing a tooltip
if (openCallback) openCallback(data, index);
// display context menu
d3.select('.d3-context-menu')
.style('left', (d3.event.pageX - 2) + 'px')
.style('top', (d3.event.pageY - 2) + 'px')
.style('display', 'block');
d3.event.preventDefault();
};
};
var menu = [
{
title: 'Create Child Section',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Create Child Section clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Create Child mouseover data = ' +d );
},
chidernItems: [
{
title: 'Vertical',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Vertical Create Child clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Vertical Create Child mouseover data = ' +d );
}
},
{
title: 'Horizontal',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Horizontal Create Child clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Horizontal Create Child mouseover data = ' +d );
}
}
]
},
{
title: 'Create Sibling Section',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Create Sibling Section clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Sibling Section mouseover data = ' +d );
},
chidernItems: [
{
title: 'Vertical',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Sibling Vertical clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Sibling Vertical mouseover data = ' +d );
}
},
{
title: 'Horizontal',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Horizontal clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Horizontal mouseover data = ' +d );
}
}
]
},
{
title: 'Delete Section',
// Exceute Action
onMouseClick: function(elm, d, i) {
console.log('Delete Section Section clicked!');
console.log('The data for this circle is: ' + d);
},
onMouseOver: function(elm,d,i){
console.log('Delete Section mouseover data = ' +d );
},
chidernItems: []
}]
var data = [1];
var g = d3.select('body').append('svg')
.attr('width', 200)
.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', d3.contextMenu(menu));

.d3-context-menu {
position: absolute;
display: none;
background-color: #f2f2f2;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
min-width: 150px;
border: 1px solid #d4d4d4;
z-index:1200;
}
.d3-context-menu ul {
list-style-type: none;
margin: 4px 0px;
padding: 0px;
cursor: default;
}
.d3-context-menu ul li {
padding: 4px 16px;
}
.d3-context-menu ul li:hover {
background-color: #4677f8;
color: #fefefe;
}
.d3-context-menu ul li > ul {
position: absolute;
background-color: #f2f2f2;
top: 0;
left: 175px;
z-index: -1;
}
.d3-context-menu ul li > ul li:hover
{
background-color: #4677f8;
color: #fefefe;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.0/d3.min.js"></script>
&#13;
我每次在鼠标悬停功能中删除和创建子菜单有没有更好的方法?
答案 0 :(得分:6)
通过'mouseover'
和'mouseout'
更改'mouseenter'
和'mouseleave'
函数并在mouseleave函数中引入d3.select(this).selectAll("ul").style('display', 'none');
来解决此问题。