用于编辑形状位置和标签的弹出窗体?

时间:2017-11-25 00:42:13

标签: javascript d3.js

我想点击形状以使用弹出窗体编辑其文本标签和x,y坐标,当提交时,更新该形状的数据,然后形状移动到新的x,y坐标。我一直无法在网上或通常的书中找到这样的例子。

页面上所有形状的数据存储在JSON数组中。一些在线示例显示如何“就地”编辑文本或编辑单个值。这对我来说不起作用,因为只有标签应该显示在形状上,我想编辑多个通常在页面上看不到的形状参数。

如果可能,我想将解决方案保留为D3或基本JavaScript。

这里显示了一个显示三个可点击矩形的简单示例: https://jsfiddle.net/NovasTaylor/oyL0hj3d/

当前"click"事件将标签,x和y值写入控制台。此事件应触发可编辑表单的显示。

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)
  });

所有建议都非常感谢,并且更加努力地展示了这个例子!

1 个答案:

答案 0 :(得分:2)

在D3中,覆盖基准非常简单。在d是第一个参数的监听器内部,只需执行:

d.foo = bar;

在您的示例中,我们使用prompt来获取新值。这只是一个演示,向您展示如何做到这一点:您可以轻松地更改丑陋的弹出式div的提示。

所以,在听众中,我们得到了新的值......

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);

唯一的问题是获得标签。因为你必须在DOM中上下,我建议你给它们(独特的)ID ...

rects.append("text")
    .attr("id", function(d, i) {
        return "label" + i;
    })

......他们得到了他们:

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;
    });

以下是仅包含这些更改的代码:

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>

请记住,这是一个非常非常简单的演示:我既不检查输入的类型(字符串,整数,浮点...),也不检查它们的值。

PS:如果您使用的是D3 v4(根据您的代码,需要无需更改!),您可以避免新定位的矩形落后于其他的矩形{ {1}}。