我有一个带有圆圈的D3 SVG内容,右键单击它会打开一个上下文菜单,显示数组中的项目列表。 我想在上下文菜单中的每个元素旁边显示特定图像。
上下文菜单的代码在ContextMenu Example
var fruits = ["Apple", "Orange", "Banana", "Grape"];
var svgContainer = d3.select("body")
.append("svg")
.attr("width", 200)
.attr("height", 200);
var circle = svgContainer
.append("circle")
.attr("cx", 30)
.attr("cy", 30)
.attr("r", 20)
.on('contextmenu', function(d,i) {
// create the div element that will hold the context menu
d3.selectAll('.context-menu').data([1])
.enter()
.append('div')
.attr('class', 'context-menu');
// close menu
d3.select('body').on('click.context-menu', function() {
d3.select('.context-menu').style('display', 'none');
});
// this gets executed when a contextmenu event occurs
d3.selectAll('.context-menu')
.html('')
.append('ul')
.selectAll('li')
.data(fruits).enter()
.append('li')
.on('click' , function(d) { console.log(d); return d; })
.text(function(d) { return d; });
d3.select('.context-menu').style('display', 'none');
// show the context menu
d3.select('.context-menu')
.style('left', (d3.event.pageX - 2) + 'px')
.style('top', (d3.event.pageY - 2) + 'px')
.style('display', 'block');
d3.event.preventDefault();
});
.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;
}
.context-menu ul {
list-style-type: none;
margin: 4px 0px;
padding: 0px;
cursor: default;
}
.context-menu ul li {
padding: 4px 16px;
}
.context-menu ul li:hover {
background-color: #4677f8;
color: #fefefe;
}
<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.10/d3.min.js"></script>
是否可以在菜单项旁边显示图像?如果是,我该如何展示它。
答案 0 :(得分:3)
如果我们首先更改您的数据结构以将文本与图标相关联,那么我们有:
var data = [{
text: 'Apple',
icon: 'https://i.stack.imgur.com/5mrSI.jpg?s=32&g=1'
}, {
text: "Orange",
icon: 'https://i.stack.imgur.com/5mrSI.jpg?s=32&g=1',
}, {
text: "Banana",
icon: 'https://i.stack.imgur.com/5mrSI.jpg?s=32&g=1'
}, {
text: "Grape",
icon: 'https://i.stack.imgur.com/5mrSI.jpg?s=32&g=1'
}];
现在我们可以改变创建上下文菜单的方式:
d3.selectAll('.context-menu')
.html('')
.append('ul')
.selectAll('li')
.data(data)
.enter()
.append('li')
.append(function(d) {
// Create the image element.
const icon = document.createElement('img');
// Change its source to the icon.
icon.src = d.icon;
// Return the image element.
return icon;
})
// Go back up a node, so that we can append the span.
.select(function () {
return this.parentNode;
})
.append('span')
// Change the text of the span element to the current
// data's text property.
.text(function (d) {
return d.text;
});
上面代码段的下半部分是工作完成的地方。通过.append('li')
创建列表元素后,您需要附加一个图像元素,该图像元素表示与当前上下文菜单项关联的图标。附加图像元素后,应添加文本节点。由于刚刚附加了图像元素,因此当前节点引用此图像节点。我们想要向上移动一个节点,以便通过li
再次访问.select(function () { return this.parentNode; })
元素。最后,可以将span
元素的文本集附加到数据中的文本。这种方法为您的上下文菜单增加了更大的灵活性,因为您可以指定HTML的结构,而不是依赖于列表元素项目符号的样式。
答案 1 :(得分:1)
实现此目的的最简单方法可能是使用li
项的list-style-image
属性来设置每个项目前面的项目符号的样式。可以将此属性设置为您在添加列表项时要使用的任何图像。为了简单起见,我的代码引用了一堆示例图像:
.selectAll('li')
.data(fruits).enter()
.append('li')
.style('list-style-image', function(d,i) {
return 'url("http://loremflickr.com/48/48?i=' + i + '")';
})
我重新安排了你的代码片段以使生活更轻松,可能需要进一步改进,但以下代码应该足以让你开始:
var fruits = ["Apple", "Orange", "Banana", "Grape"];
var svgContainer = d3.select("body")
.append("svg")
.attr("width", 200)
.attr("height", 200);
var ctxMenu = d3.select("body")
.append('div')
.style('display', 'none')
.attr('class', 'context-menu');
d3.select('body').on('click.context-menu', function() {
ctxMenu.style('display', 'none');
});
var circle = svgContainer
.append("circle")
.attr("cx", 60)
.attr("cy", 60)
.attr("r", 20)
.on('contextmenu', function(d,i) {
ctxMenu.selectAll("ul").remove();
// create the div element that will hold the context menu
// this gets executed when a contextmenu event occurs
ctxMenu
.append('ul')
.selectAll('li')
.data(fruits).enter()
.append('li')
.style('list-style-image', function(d,i) {
return 'url("http://loremflickr.com/48/48?i=' + i + '")';
})
.on('click' , function(d) { console.log(d); return d; })
.text(function(d) { return d; });
// show the context menu
ctxMenu
.style('left', (d3.event.pageX - 2) + 'px')
.style('top', (d3.event.pageY - 2) + 'px')
.style('display', 'block');
d3.event.preventDefault();
});
.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;
}
.context-menu ul {
margin: 4px 0px;
padding: 0px;
cursor: default;
}
.context-menu ul li {
padding: 4px 12px;
margin-left: 65px;
}
.context-menu ul li:hover {
background-color: #4677f8;
color: #fefefe;
}
<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.10/d3.min.js"></script>