Creating a series of neighboring rectangles with D3 that unintentionally produce a distracting shimmering effect

I've created a musical waveform using D3 by positioning rectangles next to each other. Check out the code here: http://jsfiddle.net/s4dML/

var data = [ 0.0534973, /* ...lots and lots of data... */ 0.290771];
data = data.filter(function(datum, index){
    return index % 3 == 0;
});

var width      = 340,
    height     = 70,
    svg        = d3
        .select('body')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

svg
    .selectAll('rect')
    .data(data.map(function(datum){
        return (datum * height)/2;
    }))
    // .data(dataset)
    .enter()
    .append('rect')
    .attr('x', function(d, i){
        return i * (width / data.length);
    })
    .attr('y', function(d){
        return (height /2) - d ;
    })
    .attr('width', function(d, i){
        return width / data.length;
    })
    .attr('height', function(d){
        return d*2;
    })
    .attr('fill', 'teal');

Can anyone explain why my waveform isn't a uniform color as I expected? It seems to have a shimmering effect which may be intentional, but I'd like to understand how it happened and how to remove it if needed.

Answer №1

When dealing with SVG rendering, or any type of vector graphics rendering, it's important to consider how shapes overlap within a pixel. For example, if two rectangles meet 40% into a pixel, the first rectangle will cover the pixel with 40% opacity and the second with 60% opacity. This results in the pixel only being 76% colored, even though it is technically fully covered by shapes.

To address this issue, one solution is to create a single <path> object that outlines the top and bottom edges without leaving any gaps between shapes.

While I am not very familiar with D3, a potential fix using regular JavaScript could involve defining a path that traces out the shape:

var path = "M 0," + (height / 2);

for(var i = 0; i < data.length; i++) {
  var x = (i + 1) * (width / data.length);
  var y = height / 2 - (data[i] * height)/2;
  path += " V " + y + " H " + x;
}

for(var i = data.length - 1; i >= 0; i--) {
  var x = i * (width / data.length);
  var y = height / 2 + (data[i] * height)/2;
  path += " V " + y + " H " + x;
}

path += " Z";

Answer №2

Russell has provided a valuable solution, although it may result in a lengthy path. However, this issue should not pose significant challenges.

I recently faced a similar issue while trying to create a bar chart with approximately 500 data points using very slim bars. The benefit of using thin bars is the ease of implementing a mouseover effect to highlight individual bars. In such scenarios, it is advisable to use integer values for the widths and x positions.

In your case, adjusting the width and interval to 1 can effectively resolve the problem, albeit making it slightly shorter by about 10 percent:

http://jsfiddle.net/s4dML/1/

.attr('x', function(d, i){
    return i;// * (width / data.length);
})
.attr('y', function(d){
    return (height /2) - d ;
})
.attr('width', function(d, i){
    return 1;
})

It's important to note that this might not be a scalable solution—it largely depends on the specific requirements of your widget. I have included a mouseover feature in the example above for demonstration purposes.

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

Executing the beforeRouteLeave navigation guard on a vue component for testing purposes

I am facing a challenge with unit testing the routing behavior of a vue component using jest. Specifically, when navigating away from the component, the 'beforeRouteLeave' guard in Vue-router is not triggering during testing, even though it works ...

When an `angularjs select` is used with a filter, the first line may appear empty at first. However

I'm feeling a bit confused about why my ng-options is once again giving me an empty line with a filter applied. Could you please take a look at this plunker to see the issue? The goal is to show an org chart in a dropdown list that is based on a tre ...

How to assign a preset value to a text area in AngularJS

While working with PHP and AngularJS, I have a requirement to specify the default value for a textarea. I prefer not to utilize ng-init="textarea = ''" as the data to populate is extensive. Similarly, I want to avoid using AJAX to prevent additi ...

Serve up a 400 error response via the express server when hitting a

I need help serving a 400 error for specific files within the /assets directory that contain .map in their names. For example: /assets/foo-huh4hv45gvfcdfg.map.js. Here's the code I tried, but it didn't work as expected: app.get('/assets&bs ...

Node.js does not allow for the usage of `.on` to monitor events until the client has been

I'm currently working on developing a WhatsApp chatbot using the whatsapp-web-js package. However, I am facing some difficulties with implementing it due to my limited knowledge in node JavaScript and async code. let client; //To establish connection ...

Basic PHP code converted into a JavaScript function for an onSubmit event within an HTML form

I have been trying to figure this out for hours. The goal is to submit a form only if one of the inputs matches a PHP echo. To simplify the script, it looks something like this: <head> </head> <body> <?php $A = rand(0,10); $B = r ...

Use multer-ftp to change the name of a file

I've been working on uploading a file to an FTP server using multer-ftp. The file is successfully uploaded, but I need to change the name of the file. Is there a way to accomplish this? var upload = multer({ storage: new FTPStorage({ basepath: ...

The Response.Write function is not functioning properly in the production environment

I have created a C# WebService (ASMX) with the code snippet below: if (!SomeValidation()) { //context.Response.ContentType = "application/json"; //context.Response.ContentType = "text/plain"; context.Response.ContentType = "application/text"; ...

Obtaining a file using capybara independently of rails

Case Study: Attempting to access an external URL using Capybara for downloading a file. It is necessary to use Selenium or Webkit as the driver, since Rack-test does not allow visiting external URLs. This website utilizes iframes. The prompt for file dow ...

What is the best way to execute NPM commands within the terminal of Visual Studio Code?

I recently installed npm in VSCode from extensions, but I am having trouble activating it. When I try to run the command 'npm init' in the terminal, I receive the following error message: "The term 'npm' is not recognized as the name of ...

What is the reason behind shadow dom concealing HTML elements when viewed in inspect mode?

https://i.stack.imgur.com/UZM7f.png Monday.com has implemented Shadow Dom to protect its source code. How can I work around this limitation? ...

Is it better to throw an exception before doing any filtering?

Checking for the existence of removeId in the items before filtering to avoid exceptions. Is there a more efficient way to handle this without using two loops? This code may not be optimized due to the double looping process. const items = ...

Attempting to incorporate icons into a Material UI table design

Hello, I've incorporated a Material UI table into one of my projects with a design concept similar to this - https://i.stack.imgur.com/i6Fsj.png I'm aiming to include icons within the tables. Here's the code I've worked on so far - ...

How to display content in separate divs using jQuery hover functionality

I'm in the process of creating my online portfolio by using bootstrap and jquery. I have a series of images arranged side by side with each other, and I want to make the description for each image appear when that specific image is hovered over. Each ...

Stopping the execution of jQuery().load()

The .load() feature in the jQuery library allows users to selectively load elements from another page, based on specific criteria. I am curious to know if it's feasible to stop or cancel the loading process once initiated. In our program, users can e ...

Issue with FusionCharts rendering correctly arises when the <base> tag is present in the HTML head section

Combining AngularJS and FusionCharts in my web application has led to a unique issue. The upcoming release of AngularJS v1.3.0 will require the presence of a <base> tag in the HTML head to resolve all relative links, regardless of the app's loca ...

ReactJS experiencing issue with the functionality of the all-the-cities library

Encountering an issue where importing the library all-the-cities causes reactjs to malfunction and display the following error: TypeError: fs.readFileSync is not a function (anonymous function) C:myproject/node_modules/all-the-cities/index.js:6 3 | cons ...

Tips for minimizing padding in X-Range graphs

Is there a way to reduce the overall height of my X-Range chart by adjusting the padding on the Y axis around each series? I have experimented with different properties, such as adding groupPadding: 0, pointPadding: 0, and other parameters using this jsfi ...

Perform a JSON query using JavaScript

Is there a way to query JSON using JavaScript? In my JavaScript code, I have a JSON stored in a variable called 'json'. This JSON is an array of data, each containing 3 attributes: 'name', 'city', and 'age'. I am in ...

Initiate a click on a radio button while also retaining the selected option when the page is

This is a unique question. In my scenario, there are two radio buttons: "radio1" and "radio2." I have successfully implemented the following actions individually: Automatically triggering a click on "radio1" upon page load. This ensures that the button ...