选择弧上的区域

时间:2014-10-22 03:24:38

标签: javascript svg d3.js event-handling geometry

我试图通过点击一个圆弧并拖动来进行选择。下面的例子显示了一个非常相似的概念,但选择是从一个随机位置开始,而我想从暗蓝色弧上的一个位置开始,点击鼠标并拖动它。 http://jsfiddle.net/bno009s5/

var dataset = {
  apples: [532, 284],
};

var degree = Math.PI / 180;

var width = 460,
  height = 300,
  radius = Math.min(width, height) / 2;

var color = d3.scale.category20();

var pie = d3.layout.pie().startAngle(-90 * degree).endAngle(90 * degree)
  .sort(null);

var arc = d3.svg.arc()
  .innerRadius(50)
  .outerRadius(100);

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var path = svg.selectAll("path")
  .data(pie(dataset.apples))
  .enter().append("path")
  .attr("fill", function(d, i) {
    return color(i);
  })
  .attr("d", arc)
  .each(function(d) {
    this._current = d;
  }); // store the initial values;


window.setInterval(dummyData, 2000);

// Store the displayed angles in _current.
// Then, interpolate from _current to the new angles.
// During the transition, _current is updated in-place by d3.interpolate.
function arcTween(a) {
  var i = d3.interpolate(this._current, a);
  this._current = i(0);
  return function(t) {
    return arc(i(t));
  };
}

function dummyData() {
  var num = Math.floor(Math.random() * 100);
  var key = Math.floor(Math.random() * dataset.apples.length);

  dataset.apples[key] = num;

  draw();
};

function draw() {
  svg.selectAll("path")
    .data(pie(dataset.apples))
    .transition()
    .attrTween("d", arcTween);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.4/d3.min.js"></script>

1 个答案:

答案 0 :(得分:1)

这里是jsfiddle,可见蓝线。您可以单击圆圈内外,也可以尝试单击两个端点下方。

绿色圆圈仅用于美学(即:用喜欢的宠物图片替换它:-) 测试工作在IE9,最新的Chrome和FF(2014年10月)。

修改:添加了拖动功能。下面的代码是最初的小提琴。

&#13;
&#13;
var s = Snap(400,400);
var circleX = 100, circleY = 100, circleRadius = 57; 
var stroke_width = 20;
var blueCircle = s.circle(circleX, circleY, circleRadius);
var hcp = Math.Pi*circleRadius; // half circle perimeter = 179.0

//Arc Path
var d='M 43,100 A 57,57 0 0 1 43,100';
var arcPath = s.path(d);
arcPath.attr({
    fill: "none",
    stroke: "red",
    "stroke-width": stroke_width
});

// Line Path
var L1 = s.path("M "+circleX+" "+circleY +"L 0 0");
blueCircle.attr({
    fill: "none",
    stroke: "skyblue",
    "stroke-width": stroke_width,
    "stroke-dasharray": "0,179,179"
});
var c1 = s.circle(0,0,5).attr({ fill: "none",stroke: "green" });

function OnMouseDown(evt) {
    var mouseY = Math.min(evt.clientY,100); // limit mouseY to 100
   
    L1.attr({ d: "M "+circleX+" "+circleY +"L "+evt.clientX+" "+mouseY });
    var totalLength = L1.getTotalLength();
    if (totalLength < circleRadius) { // smaller, extend line
        var ratio = circleRadius/totalLength;
        var x_len = evt.clientX + (evt.clientX - circleX)*ratio;
        var y_len = mouseY + (mouseY - circleY)*ratio;
        L1.attr({ d: "M "+circleX+" "+circleY +"L "+x_len+" "+y_len });
    } 
    var PAL = L1.getPointAtLength(circleRadius);
    c1.attr({ cx: PAL.x , cy: PAL.y });
    draw_arc(PAL.x,PAL.y);
}

function draw_arc(endX,endY) { // Draw SVG arc
    // point starts on left at 43,100, 
    // Arc Box height is 57,57 (radius)
    // Ends at (endX,endY)
   
    var newArc ='M 43,100 A 57,57 0 0 1 '+endX+','+endY;
    arcPath.attr({ 'd': newArc });
}
document.onmousedown = OnMouseDown;
&#13;
<script src='//cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js'></script>
&#13;
&#13;
&#13;