2017-12-13 100 views
6

Xin chào Tôi muốn biết làm thế nào nó có thể hai làm cho nó mà hai vòng tròn thay đổi màu sắc khi chúng chồng lên nhau. Tốt hơn là phần được chồng chéo sẽ trở thành màu trắng vì nó có nghĩa là đại diện cho các bộ.Làm thế nào để thay đổi màu sắc của hai vòng tròn khi chồng lên nhau bằng cách sử dụng thư viện D3

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; 
 
}
<canvas width="800" height="500"></canvas> 
 
<script src="//d3js.org/d3.v4.min.js"></script>

giải pháp lý tưởng của tôi sẽ là một cái gì đó cho phép tôi thay đổi màu sắc của phần chồng chéo màu khác để đại diện cho giao nhau giữa 2 bộ.

Cảm ơn bạn trước

Edit: một số cập nhật đã được thực hiện tuy nhiên Ive chỉ được tìm thấy làm thế nào để làm màu cho các yếu tố tĩnh thay vì di chuyển

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]; 
 
    }
<script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> 
 
<svg width="500" height="500"></svg>

^Điều này phù hợp với số liệu thống kê

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") 
 
    \t .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); 
 
}
<svg width="500" height="500"></svg> 
 
<script src="//d3js.org/d3.v4.min.js"></script>

^Đây là vòng tròn di chuyển của tôi mà tôi muốn nói thêm nói ảnh hưởng đến.

Có cách nào để kết hợp hai mã này để đạt được điều này không?

Cảm ơn một lần nữa

+0

Có thể một cách để đạt được điều đó có thể là thuộc tính 'context.globalCompositeOperation' (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation). Nhưng tôi không chắc chắn rằng bạn có thể tùy chỉnh màu sắc của riêng bạn cho phần chồng chéo. – JulCh

+0

Nó dường như không hoạt động với các vòng tròn chuyển động và tôi cũng sử dụng svg như trái ngược với canvas. Tôi đã kinda tìm thấy một cách để nó làm việc trong khi tĩnh nhưng không phải trong khi di chuyển. – Cormanno

Trả lời

0

SVG mix-blend-mode

SVG mix-blend-mode di chuột từ screen để normal

Đây không phải là chính xác những gì bạn đang tìm kiếm vì nó không cho phép bạn lập trình điều khiển màu sắc của giao nhau phân đoạn, nhưng CSS mix-blend-mode là một giải pháp rất đơn giản mà tôi đã sử dụng với d3. Tôi đã cố gắng để thực hiện cùng một điều nhưng chạy vào các vấn đề hiệu suất tính toán giao lộ trên animating bộ dữ liệu lớn. Compatibility có thể là một mối quan tâm nếu điều này cần phải làm việc trong IE/Edge, nhưng nếu không hầu hết các chế độ được hỗ trợ trong Chrome, Firefox và Safari (thậm chí cả điện thoại di động).

Đây cũng là một số tốt guide with examples trên d3 và đơn giản là Codepen snippet.

Nếu không, có vẻ như bạn đã tìm thấy D3.js - detect intersection area. Để làm việc đó với thao tác kéo, bạn cần viết các phép tính để xác định trong đó các vòng kết nối chồng chéo, sau đó tính khu vực giao lộ của chúng.

Các vấn đề liên quan