Chrome now supports clickable circular canvas corners

I have a unique setup with two canvases. I've customized them to be circular by utilizing the border-radius property. The second canvas is positioned perfectly within the boundaries of the first one using absolute positioning.

This is where it gets exciting - I've added click events to both circles! If you happen to click within the inner canvas, the color at that exact point will magically appear on the outer canvas. Not only that, but the opacity of the color will smoothly transition from white to the picked color and eventually fade into black. On the other hand, if you decide to click on the outer canvas, the precise color value at that particular point will accurately display in the text-box located at the bottom.

Alright, here's the issue I'm facing: Unfortunately, for some reason unknown to me, I am restricted from clicking on certain areas in the outer canvas that are colored red (as shown in the accompanying figure). Strangely enough, this problem only occurs when using Chrome. Firefox, on the other hand, operates flawlessly without any issues whatsoever.

Keep this little tidbit in mind: You actually have the ability to drag the picker object around inside the outer circle. However, if you accidentally leave it in one of those pesky red zones, you won't be able to click it again in Chrome. The good news is that as long as you click within the green zone, you can regain control of the picker object once more. Phew!

If you're interested in checking out the code behind this mesmerizing experience, feel free to take a look at my JSFiddle:

The Unique Code within this JSFiddle

Edit

In order to simplify things and remove any unnecessary code, I've excluded portions that aren't relevant. Now, all you'll find is a container housing two canvases - each filled with its own distinct color. Here's where it gets interesting: Try opening the updated version of the fiddle in both Chrome and Firefox. Click on different areas within both circles and observe the intriguing differences between the two browsers. The ultimate goal here is to make them behave identically in Chrome as they do in Firefox.

Just a little side note: In the end, my plan is to create an awesome image within the inner canvas. Exciting stuff, right?

If you're up for even more excitement, feel free to check out the latest version of the JSFiddle:

The Updated Fiddle Link full of Uniqueness

-

Answer №1

The issue you are facing is due to the fact that canvases are always rectangular, even if they appear to have a different shape. The border radius creates transparent edges, but events can still occur in the corner areas of Chrome, which is why you are unable to click on the bottom circle in those areas.

I attempted to solve this problem by placing the canvas inside a container with a border radius, but the click event still passes through.

There are two possible solutions. First, you could modify your code to use only one canvas and redraw the background circle before drawing any other elements each time. This involves drawing a circle, then applying a black-to-white gradient using the "xor" operation to combine it with the previous circle, and repeating the process for the rainbow gradient. It's important to draw the background circle first because the canvas repaints over the previous layers every time.

Alternatively,

You can use JavaScript to detect clicks only within the circular area, which requires some basic math calculations (: This solution is explained further below

In the future, CSS Shapes might allow non-rectangular canvases to be used as elements, though this capability is not currently available.

Edit

Upon reviewing your code, I found some points that should be addressed before providing a solution:

  • Declare all finite variables outside functions that run repeatedly, such as the click function. These variables (e.g., radii, offsets) do not change and thus should not be included within those functions.
  • Your "radii" are actually diameters. In the .rect format, it should be
    .rect(x, y, width (circle's diameter), height (circle's diameter))
  • In most cases, when overlaying canvases like you're doing, it's advisable to make them equal in dimensions and starting position to avoid calculation errors. You can achieve relative positioning using JavaScript instead of mixing it with CSS. However, in this case, given that you're using border-radius instead of arc to create a circle, it's fine to leave it as is and adjust the position using JavaScript...
  • For something as simple as this, you don't really need jQuery. If you're concerned about load speed, I recommend implementing it in vanilla JavaScript by changing the .click() functions to .onclick functions. For now, I'll keep jQuery.
  • You can declare multiple variables at once without using var repeatedly. The following format can be used:
  • var name1 = value1,
        name2 = value2;
  • Variables with the same value can be declared like this:
  • var name1 = name2 = sameValue;
  • When children have position:absolute and their position is relative to the parent, the parent container should have either position:relative, position:fixed, or position:absolute. In this case, position:relative should suffice.
  • If you fail to use var when declaring a variable, it becomes global (unless chained with a comma, as shown above). For further clarification, you can read this question on Stack Overflow: [link to the question]

Now, let's move on to the solution.

After discussing with a friend, I realized that calculating the math for this situation was easier than I initially thought. We can calculate the centers of the circles, consider their radii, and use if statements to ensure that clicks fall within the bounds.

Here's the demo

Once everything is set up correctly, you can use the following code to determine whether the click falls within the desired bounds:

function clickHandler(e, r) {
    var ex = e.pageX,
        ey = e.pageY,
        // Distance from click to center
        l = Math.sqrt(Math.pow(cx - ex, 2) + Math.pow(cy - ey, 2));

    if(l > r) { // If the distance is greater than the radius
        if(r === LARGE_RADIUS) { // Outside of the large circle
            // Do nothing
        } else { // In the problematic corner area
            clickHandler(e, LARGE_RADIUS);
        }
    } else {
        if(r === LARGE_RADIUS) { // Inside the large circle
            alert('Outer canvas clicked x:' + ex + ',y:' + ey);
        } else { // Inside the small circle
            alert('Inner canvas clicked x:' + ex + ',y:' + ey);
        }
    }
}

// Simply call the function with the appropriate radius on click
$(img_canvas).click(function(e) { clickHandler(e, SMALL_RADIUS); });    
$(wheel_canvas).click(function(e) { clickHandler(e, LARGE_RADIUS); });

I hope the comments and code above are clear enough. I tried to improve them as much as possible. If you have any questions, feel free to ask!

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

Flattening an array of Map in Typescript involves combining all the

I am working with an array containing entries of type Map<string, number> Is there a way to flatten this array into a single map? Map<string, number>[] converted to Map<string, number> Appreciate any help on this matter. ...

The TextField is currently unable to be edited because of an Uncaught TypeError stating it is not iterable

Currently, I am fetching data from an API and updating TextFields with it for display. My goal is to allow users to edit the data shown in these TextFields, but I keep encountering a Uncaught TypeError: prev.fields is not iterable error whenever I attempt ...

Mastering the art of customizing classes and styles in material-ui (React)

I am facing a challenge with version 1.2.1 of material-ui. My goal is to make the AppBar component transparent by overriding its styles as per the documentation here. This is the code snippet I have been working on: import React, { Component } from ' ...

Creating a text shadow effect with text that has a transparent color

I am attempting to replicate the design shown below using the CSS text-shadow property, but I keep getting a solid color outcome. I have tried using an rgba value of 255,0,0,0.0 for the font-color and text-shadow like this: text-shadow: -1px -1px 0 #0 ...

Why doesn't Material-UI seem to understand the theme.spacing function?

Issue with Material-UI's theme.spacing function I've encountered a problem while using Material-UI's theme.spacing function in a React application. It seems that the spacing function is not being recognized. The Javascript error message st ...

Transfer all image files from Node.js to the frontend

What is the best way to send all image files from my backend nodejs server folder to my Reactjs client? I have set up a website where users can sign in and upload their files. However, I am facing an issue where only one file is visible on the client side, ...

Could the comments within a NodeJS script be causing memory problems?

I specialize in creating NodeJS libraries, and my coding practice includes adding JSDoc comments for documentation purposes. Here is an example of how my code usually looks: /** * Sum * Calculates the sum of two numbers. * * @name Sum * @function * ...

What is the best way to use toggleClass on a specific element that has been extended

I have been experimenting with this code snippet for a while. The idea is that when I hover my mouse over the black box, a red box should appear. However, it doesn't seem to be working as expected. Could someone please review this script and let me k ...

Ways to apply CSS to a changing div ID

I am looking to apply CSS to a dynamically generated div ID. var status = var status = item.down().next().innerHtml(); if(status == "test") { var c = 'item_'+i ; c.style.backgroundColor = 'rgb(255, 125, 115)'; //'ite ...

Adjust the background color of a non-selected Material-UI checkbox

Currently, I am working with a combination of React-Redux and Material-UI to style my project. Within this setup, I have a checkbox component that is placed on a toolbar with a blue background color (#295ED9). So far, I have successfully altered the color ...

Tips on adding to Jquery html code while maintaining the current CSS styling

My JavaScript function looks like this: function appendAllQna(qnaList, num){ for (var i in qnaList){ var qnaCom = ""; qnaCom += "<div class='scomment scommentLine'>"; if(qnaList[i].sellerYn == "Y"){ ...

Shifting the final child to the front position proves unsuccessful with jQuery

I have attempted to move the last element in my list to the first position upon clicking, but unfortunately, it is not working as expected. I followed the advice provided in response to a question on the following page: Move last child to first position. W ...

The vertical scrolling feature seems to be malfunctioning within my angular 10 application

I'm having an issue with the scrollbar not working on this Angular 10 template, even after adding the CSS style overflow: auto; to the main container. Although I've included the overflow property in the main container "cont" as shown in the HTML ...

Struggling to make EJS button functional on the template

I am currently facing an issue with a loop that populates a webpage with multiple items, each containing an image, text, button, and a unique ID associated with it. Although I have written a function to retrieve the ID and plan name when the button is clic ...

Is it viable to create an onClick event for the text content within a text area?

I'm working on a project that involves displaying XML data in a textarea and creating an onClick event for the content within the textarea. For example: <textarea>Hello Web, This is a simple HTML page.</textarea> My goal here is to create an ...

Transmit messages from server (via Expressjs routing) to the client

I am looking for guidance on how to effectively send messages from the server to the client and incorporate this functionality into routes/index.js within my mean stack project. Can anyone provide insights on using socket.io in this context?: router.post( ...

What is the complete list of features that ColorTranslator.FromHtml() supports and what are the reasons behind its departure from traditional CSS color interpretation guidelines

I'm looking to enhance an API by providing users with the ability to specify the color of something. I want it to accept various representations of colors, such as hex codes and CSS colors. Initially, I thought that ColorTranslator.FromHtml() would fu ...

Margin and padding have the ability to increase the size of an image

Is there a technique to position the logo.png so that it appears approximately one-third of the way across the page without affecting its size? I've attempted to use padding or margin adjustments, but it seems to distort the image despite having limit ...

Encountering issues with importing a module from a .ts file

Although I have experience building reactJS projects in the past, this time I decided to use Node for a specific task that required running a command from the command line. However, I am currently facing difficulties with importing functions from other fil ...

Guide on displaying multiple views along with their respective models fetched through AJAX in Backbone

Hey there! I'm currently working on painting a screen with multiple models and associated views in backbone. To achieve this, I have separate ajax calls to fetch data for these views. Initially, I thought using the jQuery function $when(ajaxcall1, aja ...