Tips for altering the color of two circles when they overlap:

Hello, I am interested in creating an effect where two circles change color when they overlap. Specifically, I would like the overlapped section to become white to represent sets.

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>

Ideally, I want a solution that allows me to change the color of the overlapping section to another color, representing the intersection between two sets.

Thank you for your help

Edit: Some updates have been made. However, I have only managed to color static elements instead of moving ones.

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

    ...

    function intersection(x0, y0, r0, x1, y1, r1) {
      
      ...
      
      return [xi, xi_prime, yi, yi_prime];
    }
<script data-require="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8de9becdbea3b8a3be">[email protected]</a>" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<svg width="500" height="500"></svg>

Please note that the above code works for static elements.

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

...

<svg width="500" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>

This code snippet showcases my moving circles, and I am looking to add the aforementioned effect on them as well.

Is there any way to combine the two codes to achieve this effect?

Thank you once again

Answer №1

To implement the concept, utilize the intersection function from your static strategy (second snippet) within the dragged function of your dynamic approach (third snippet).

Begin by establishing 2 groups so that the path for "intersection" is consistently positioned in front of the circles:

var g1 = svg.append("g");
var g2 = svg.append("g");

Now onto the crucial steps.

Within the dragged function, determine the position of the other circle that is not being dragged:

var otherCircle = circles.filter(function(e, j) {
    return i !== j;
}).datum();

If there are more than two circles, it may require reorganization. However, the demonstration below features only two circles, so let's proceed.

Next, verify whether they overlap:

Math.hypot(d.x - otherCircle.x, d.y - otherCircle.y) < 2 * radius

If an overlap exists, invoke intersection and assign the path's d attribute:

var interPoints = intersection(d.x, d.y, radius, otherCircle.x, otherCircle.y, radius);
path.attr("d", function() {
  return "M" + interPoints[0] + "," + interPoints[2] + "A" + radius + "," + radius +
    " 0 0,1 " + interPoints[1] + "," + interPoints[3] + "A" + radius + "," + radius +
    " 0 0,1 " + interPoints[0] + "," + interPoints[2];
})

If there is no overlap, remove the path:

path.attr("d", null)

Here is a live demo that showcases the functionality:

// JavaScript code goes here
// CSS code goes here
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="600" height="300"></svg>

Answer №2

https://i.sstatic.net/CvUWL.gif

Discover the power of SVG mix-blend-mode hover transition from screen to normal

If you're seeking a way to programmatically manipulate intersecting segments' colors, CSS mix-blend-mode offers a simple solution that's been successfully employed with d3. While attempting a similar effect, performance issues arose when calculating intersections in animations involving large datasets. Take note of compatibility concerns, especially if IE/ Edge support is necessary — most modern browsers like Chrome, Firefox, and Safari (including mobile versions) offer robust support for various blend modes.

For comprehensive guidance on utilizing d3 for color blending in SVG illustrations, check out this informative guide with examples, along with a concise demonstration in this Codepen snippet.

If you've come across the thread discussing how to detect intersection areas in D3.js (D3.js - detect intersection area), you may need to develop the calculations to identify overlapping circles and compute their precise intersection areas when incorporating drag functionality.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Modifying the default hover color of a specific row in AgGridReact

How can I eliminate the row color changing behavior in AgGrid tables when a row is selected and hovered over using React? Currently, a default dark gray color is applied when I hover over certain elements of a selected row, which is not desired in my imple ...

When hovering over different <a> tabs, showcase various images in individual <div> sections

Here are the buttons I am working with - <div class="nav nav-tabs " id="nav-tab" role="tablist"> <a style="text-decoration:none" class="nav-item nav-link" data-toggle="tab& ...

Unexpected result produced by indexOf() function

When trying to display the index of the first element (violet) using an alert, I am getting -1 instead of the expected result. This unexpected outcome is hindering my progress in coding. As a newcomer to JavaScript, I'm facing this issue and seeking a ...

Creating a unique AngularJS custom directive that utilizes ng-options can be achieved by populating

I've encountered a major roadblock in my project, and despite my efforts to troubleshoot, I can't seem to find the solution. The issue revolves around populating options within an ng-options directive through a service. This directive is nested i ...

identical remarks appear on numerous php websites

I have a collection of article webpages, each with a comment section below where readers can share their thoughts. However, I'm facing an issue where comments made on one article are showing up on others as well. It's creating confusion for my r ...

Issue with executing Mongoose's .save() method

I am facing an issue with a piece of code that is not functioning as expected. My goal is to save a user document after modifying it with an ObjectId by adding it to an array. However, the user.save() function does not seem to execute, as the document rema ...

The variables are filled with HTML tags that will render the display in

I am facing an issue with displaying HTML tags in my website. When I try to print a variable containing HTML tags in the tpl file, it shows the tags along with the content. This is how it looks in the PHP file: $content = "<h1>Header</h1>< ...

"The variables in the .env file are not reflecting the latest updates. What is the best way

Currently, I am in the process of developing an application using Quasar (Vue) where I have stored my database keys in a .env file. Recently, I encountered an issue when attempting to switch to another instance and updating the keys in the env file. Despit ...

Send a Javascript variable to a Python controller using AJAX

Programming is still new to me and I find myself in unfamiliar territory... I am working on creating an app that relies on button clicks to gather information and provide data analysis based on those interactions. While this functionality works using pure ...

Passing variables in Redirect() without exposing them in the URL; a methodical approach

After scouring the depths of the internet, I have been on a quest to figure out how to seamlessly redirect to a new page on my site while discreetly passing a variable without exposing it in the URL like so: www.test.com/?variable=dont.want.this.here I a ...

The style attribute transforms the background-image url quotation to become &quot;

I'm currently working on creating a catalog component that will allow me to display images, titles, and descriptions multiple times. Below is the code for this component: import React from "react"; import '../pages/UI.css'; import ...

What's the best way to get rid of the one-pixel gap between these elements on high-resolution displays like

http://jsfiddle.net/36ykrp9x/5/ HTML <div class="container"> <button>O</button><button>O</button> </div> CSS .container { width: 100%; background-color: rgb(120, 200, 200); text-align: center; } butt ...

Issue with AnimeJS Motion Path causing element to deviate from desired SVG path

I'm attempting to use an SVG element and the AnimeJS library to make the orange marker follow the course of this RC car race track. https://i.stack.imgur.com/8FKHC.png Despite my efforts, I am encountering strange and undesirable outcomes. At times ...

Can menus in Vue.js be customized differently for various "pages"?

I am new to Vue and facing a challenge with a common component - menu - that needs to be styled differently on the "TOP page" compared to all other "pages". <template> <div> <menu></menu> <transition name="fade" mode="o ...

Eclipse now features automatic CSS class suggestions to help streamline your coding

After using NetBeans for a while, I am now considering making the switch to Eclipse. Everything seems fine, but one thing that is bothering me is that Eclipse does not provide CSS class proposals like NetBeans does. In NetBeans, whenever I use or create a ...

What is the best way to choose a file path for the saveAs() function in JavaScript or TypeScript?

Q1: What is the method for defining the path when using the saveAs() function in JavaScript? After downloading a file, I want to be able to specify a path like: C:\Users\file-\projectName\src\assets\i18n\en.json const b ...

Transitioning to Firebase Authentication

I made the decision to transition away from firebase authentication. To accomplish this, I exported all firebase users along with their email addresses, hashed passwords, salt keys, and other necessary information. Next, I transferred them to a database a ...

What is the best approach to dynamically bind a style property in Vue.js 3?

I am currently working with vue3 and I am trying to apply dynamic styles. This is how my vue3 template looks: <ul> <li v-for="(question, q_index) in questions" :key="q_index" v-show="question.visible" :style="{ ...

Alter the language settings of the Datepicker feature in Material Angular 4

Need help changing the language of Datepicker in Material Angular. Struggling to locate this information in the Angular material 2 documentation. Check out this plunkr https://plnkr.co/edit/unzlijtsHf3CPW4oL7bl?p=preview <md-input-container> < ...

Having trouble with Angular2's Maximum Call Stack Exceeded error when trying to display images?

I am facing an issue in my Angular2 application where I am trying to display an image in Uint8Array format. The problem arises when the image size exceeds ~300Kb, resulting in a 'Maximum Call Stack Exceeded' error. Currently, I have been able to ...