如何在重叠时改变两个圆圈的颜色?

Cor*_*nno 9 html javascript css svg d3.js

您好我想知道两个圆圈重叠时是否可以改变颜色.优选地,重叠的部分将变为白色,因为其意图表示组.

var canvas = d3.select("canvas"),
    context = canvas.node().getContext("2d"),
    width = canvas.property("width"),
    height = canvas.property("height"),
    radius = 32;

var circles = d3.range(4).map(function(i) {
  return {
    index: i,
    x: Math.round(Math.random() * (width - radius * 2) + radius),
    y: Math.round(Math.random() * (height - radius * 2) + radius)
  };
});

var color = d3.scaleOrdinal()
    .range(d3.schemeCategory20);

render();

canvas.call(d3.drag()
    .subject(dragsubject)
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended)
    .on("start.render drag.render end.render", render));

function render() {
  context.clearRect(0, 0, width, height);
  for (var i = 0, n = circles.length, circle; i < n; ++i) {
    circle = circles[i];
    context.beginPath();
    context.moveTo(circle.x + radius, circle.y);
    context.arc(circle.x, circle.y, radius, 0, 2 * Math.PI);
    context.fillStyle = color(circle.index);
    context.fill();
    if (circle.active) {
      context.lineWidth = 2;
      context.stroke();
    }
  }
}

function dragsubject() {
  for (var i = circles.length - 1, circle, x, y; i >= 0; --i) {
    circle = circles[i];
    x = circle.x - d3.event.x;
    y = circle.y - d3.event.y;
    if (x * x + y * y < radius * radius) return circle;
  }
}

function dragstarted() {
  circles.splice(circles.indexOf(d3.event.subject), 1);
  circles.push(d3.event.subject);
  d3.event.subject.active = true;
}

function dragged() {
  d3.event.subject.x = d3.event.x;
  d3.event.subject.y = d3.event.y;
}

function dragended() {
  d3.event.subject.active = false;
}
Run Code Online (Sandbox Code Playgroud)
<canvas width="800" height="500"></canvas>
<script src="//d3js.org/d3.v4.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

我理想的解决方案是允许我将重叠部分的颜色更改为另一种颜色以表示两组之间的交集.

先感谢您

编辑:已经进行了一些更新,但我只发现了如何为静态元素着色而不是移动

var   x1 = 100,
      y1 = 100,
      x2 = 150,
      y2 = 150,
      r = 70;

    var svg = d3.select('svg')
      .append('svg')
      .attr('width', 500)
      .attr('height', 500);

    svg.append('circle')
      .attr('cx', x1)
      .attr('cy', y1)
      .attr('r', r)
      .style('fill', 'steelblue')
      .style("fill-opacity",0.5)
      .style("stroke","black");

    svg.append('circle')
      .attr('cx', x2)
      .attr('cy', y2)
      .attr('r', r)
      .style('fill', 'orange')
      .style("fill-opacity",0.5)
      .style("stroke","black");

    var interPoints = intersection(x1, y1, r, x2, y2, r);

    svg.append("g")
      .append("path")
      .attr("d", function() {
        return "M" + interPoints[0] + "," + interPoints[2] + "A" + r + "," + r +
          " 0 0,1 " + interPoints[1] + "," + interPoints[3]+ "A" + r + "," + r +
          " 0 0,1 " + interPoints[0] + "," + interPoints[2];
      })
      .style('fill', 'red')
      .style("fill-opacity",0.5)
      .style("stroke","black");


    function intersection(x0, y0, r0, x1, y1, r1) {
      var a, dx, dy, d, h, rx, ry;
      var x2, y2;

      /* dx and dy are the vertical and horizontal distances between
       * the circle centers.
       */
      dx = x1 - x0;
      dy = y1 - y0;

      /* Determine the straight-line distance between the centers. */
      d = Math.sqrt((dy * dy) + (dx * dx));

      /* Check for solvability. */
      if (d > (r0 + r1)) {
        /* no solution. circles do not intersect. */
        return false;
      }
      if (d < Math.abs(r0 - r1)) {
        /* no solution. one circle is contained in the other */
        return false;
      }

      /* 'point 2' is the point where the line through the circle
       * intersection points crosses the line between the circle
       * centers.  
       */

      /* Determine the distance from point 0 to point 2. */
      a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);

      /* Determine the coordinates of point 2. */
      x2 = x0 + (dx * a / d);
      y2 = y0 + (dy * a / d);

      /* Determine the distance from point 2 to either of the
       * intersection points.
       */
      h = Math.sqrt((r0 * r0) - (a * a));

      /* Now determine the offsets of the intersection points from
       * point 2.
       */
      rx = -dy * (h / d);
      ry = dx * (h / d);

      /* Determine the absolute intersection points. */
      var xi = x2 + rx;
      var xi_prime = x2 - rx;
      var yi = y2 + ry;
      var yi_prime = y2 - ry;

      return [xi, xi_prime, yi, yi_prime];
    }
Run Code Online (Sandbox Code Playgroud)
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<svg width="500" height="500"></svg>
Run Code Online (Sandbox Code Playgroud)

^这适用于静力学

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius = 32;

var circles = d3.range(4).map(function() {
  return {
    x: Math.round(Math.random() * (width - radius * 2) + radius),
    y: Math.round(Math.random() * (height - radius * 2) + radius)
  };
});

var color = d3.scaleOrdinal()
    .range(d3.schemeCategory20);

svg.selectAll("circle")
  .data(circles)
  .enter().append("circle")
  	.style("fill-opacity",0.3)
    .style("stroke","black")
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 60)
    .style("fill", function(d, i) { return color(i); })
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));

function dragstarted(d) {
  d3.select(this).raise().classed("active", true);
}

function dragged(d) {
  d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}

function dragended(d) {
  d3.select(this).classed("active", false);
}
Run Code Online (Sandbox Code Playgroud)
<svg width="500" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

^这是我想要添加效果的动圈.

有没有办法将两个代码结合起来实现这一目标?

再次感谢

Tom*_*Tom 0

SVG 混合混合模式

SVGmix-blend-mode悬停从screennormal

这并不完全是您想要的,因为它不允许您以编程方式控制相交线段的颜色,但 CSSmix-blend-mode是我在 d3 中使用的一个非常简单的解决方案。我试图完成同样的事情,但在计算动画大型数据集的交集时遇到了性能问题。如果需要在 IE/Edge 中工作,则兼容性可能是一个问题,但除此之外,大多数模式在 Chrome、Firefox 和 Safari(甚至移动设备)中都受支持。

这是一个很好的指南,其中还包含 d3 的示例和简化的Codepen 片段

否则,您似乎已经找到了D3.js - 检测交叉区域。为了使其能够与拖动一起使用,您需要编写计算以确定哪些圆重叠,然后计算它们的相交面积。