弹出表单来编辑形状位置和标签? [英] Popup form to edit shape position and label?
问题描述
我想单击一个形状以使用弹出表单编辑其文本标签和x,y坐标,该表单在提交后会更新该形状的数据,然后该形状移至新的x,y坐标.我一直无法在网上或普通书籍中找到类似的例子.
I want to click on a shape to edit its text label and x,y coordinates using a popup form that, when submitted, updates the data for that shape and the shape then moves to the new x, y coordinates. I've been unable to find any examples like this online or in the usual books.
页面上所有形状的数据都存储在JSON数组中.一些在线示例显示了如何就地"编辑文本或编辑单个值.这对我来说不起作用,因为只有标签应该显示在形状上,并且我想编辑通常在页面上不可见的多个形状参数.
Data for all shapes on the page is stored in a JSON array. Some online examples show how to edit text "in place" or edit a single value. This will not work for me, since only the label should be displayed on the shape and I want to edit multiple shape parameters not usually visible on the page.
如果可能的话,我想将解决方案保留为D3或基本的JavaScript.
I would like to keep the solution as D3 or basic JavaScript, if possible.
一个简单的示例显示了三个可单击的矩形: https://jsfiddle.net/NovasTaylor/oyL0hj3d/
A simple example showing three clickable rectangles is here: https://jsfiddle.net/NovasTaylor/oyL0hj3d/
当前"click"
事件将标签,x和y值写入控制台.此事件应触发可编辑表单的显示.
The current "click"
event writes the label, x and y values to the console. This event should trigger the display of the editable form.
rects.append("rect")
.attr("x", function (d) { return d.x; })
.attr("y", function (d) { return d.y; })
.attr("height", function (d) { return d.height; })
.attr("width", function (d) { return d.width; })
.style("fill", function(d) { return d.color; })
.on("click", function(d){
console.log("You clicked rectangle: " + d.label)
console.log ("X position: " + d.x)
console.log ("Y position: " + d.y)
});
所有建议都值得赞赏,工作示例更是如此!
All advice greatly appreciated and working example even more so!
推荐答案
在D3中,覆盖原点非常简单.在侦听器中,其中d
是第一个参数,只需执行以下操作:
In D3 it's quite simple to override the datum. Inside the listener where d
is the first parameter, just do:
d.foo = bar;
在您的示例中,让我们使用prompt
来获取新值.这只是一个演示如何演示的演示:您可以轻松地更改弹出式div的难看提示.
In your example, let's use prompt
to get the new values. This is just a demo to show you how to do it: you can easily change the ugly prompts for fancy popup divs.
因此,在侦听器内部,我们获得了新的值...
So, inside the listener, we get the new values...
var newLabel = prompt("Please enter the new label: ");
var newX = prompt("Please enter the new x position: ");
var newY = prompt("Please enter the new y position: ");
...并使用它们重新定位矩形,同时覆盖基准:
... and use them to reposition the rectangles, overriding the datum at the same time:
d3.select(this)
.attr("x", d.x = +newX)
.attr("y", d.y = +newY);
唯一的问题是获取标签.由于您必须在DOM中上下移动,因此建议您给他们提供(唯一的)ID ...
The only problem is getting the labels. As you have to go up and down in the DOM, I suggest you to give them (unique) ids...
rects.append("text")
.attr("id", function(d, i) {
return "label" + i;
})
...他们得到了他们:
... and them getting them:
d3.select(this.parentNode)
.select("#label" + i)
.text(newLabel)
.attr("x", function(d) {
return d.x + 10;
})
.attr("y", function(d) {
return d.y + 10;
});
这是您的代码,仅包含那些更改:
Here is your code with those changes only:
var rectData = [{
"label": "one",
"x": 100,
"y": 50,
"height": 100,
"width": 120,
"color": "green"
}, {
"label": "two",
"x": 250,
"y": 50,
"height": 100,
"width": 120,
"color": "purple"
}, {
"label": "three",
"x": 400,
"y": 50,
"height": 100,
"width": 120,
"color": "red"
}];
var svg = d3.select("body").append("svg")
.attr("width", 600)
.attr("height", 200);
var rects = svg.selectAll("rect")
.data(rectData)
.enter();
rects.append("rect")
.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
})
.attr("height", function(d) {
return d.height;
})
.attr("width", function(d) {
return d.width;
})
.style("fill", function(d) {
return d.color;
})
.on('mouseover', function(d) {
var rectSelection = d3.select(this)
.style({
opacity: '0.5'
})
})
.on('mouseout', function(d) {
var rectSelection = d3.select(this)
.style({
opacity: '1'
})
})
.on("click", function(d, i) {
var newLabel = prompt("Please enter the new label: ")
var newX = prompt("Please enter the new x position: ")
var newY = prompt("Please enter the new y position: ")
d3.select(this).attr("x", d.x = +newX).attr("y", d.y = +newY);
d3.select(this.parentNode).select("#label" + i).text(newLabel).attr("x", function(d) {
return d.x + 10;
})
.attr("y", function(d) {
return d.y + 10;
})
});
// Rectangle Label
rects.append("text")
.attr("id", function(d, i) {
return "label" + i;
})
.style("fill", "black")
.attr("dy", ".35em")
.attr("x", function(d) {
return d.x + 10;
})
.attr("y", function(d) {
return d.y + 10;
})
.text(function(d) {
return "Label: " + d.label
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
请记住,这是一个非常非常简单的演示:我既不检查输入的类型(字符串,整数,float ...)也不检查它们的值.
Have in mind that this is a very, very simple demo: I'm neither checking the type of the input (string, integer, float...) nor their values.
PS:如果您使用的是D3 v4(对您的代码来说,根本不需要更改!),则可以通过简单的selection.raise()
.
PS: If you were using D3 v4 (that, with your code, requires no change at all!), you could avoid the new-positioned rectangle going behind the other ones with a simple selection.raise()
.
这篇关于弹出表单来编辑形状位置和标签?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!