Skip to content

ekroon/tech-radar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

Copilot chat assisted development

Chat

ekroon: I want to create animations in a browser + javascript. What woud be better d3 or p5js?

GitHub Copilot: Both d3.js and p5.js are great libraries for creating animations in a browser with JavaScript. However, they have different strengths and use cases.

d3.js is primarily used for data visualization and creating interactive charts and graphs. It has a steep learning curve and requires a good understanding of SVG and data manipulation. If your goal is to create complex data visualizations, d3.js might be the better choice.

p5.js, on the other hand, is a library for creative coding and interactive graphics. It is easier to learn and has a more intuitive API. If you want to create interactive animations and graphics, p5.js might be the better choice.

Ultimately, the choice between d3.js and p5.js depends on your specific needs and goals. If you are unsure, I suggest trying out both libraries and seeing which one fits your needs better.

ekroon: I want to create a tech radar with d3

GitHub Copilot: Creating a tech radar with d3.js can be a great way to visualize and communicate your organization's technology landscape. Here's a plan in pseudocode for how you could approach this:

  1. Define the data structure for your tech radar. This could include categories (e.g. languages, frameworks, tools), items within each category (e.g. Java, Python, React), and a ranking or maturity level for each item (e.g. adopt, trial, assess, hold).

  2. Create an SVG element in your HTML file to hold the tech radar visualization.

  3. Use d3.js to read in your data and create a series of concentric circles to represent the different maturity levels.

  4. Use d3.js to create a series of lines radiating out from the center of the radar to the edge, representing the different categories.

  5. Use d3.js to create a series of dots or shapes along each line to represent the items within each category.

  6. Use d3.js to color-code the dots or shapes based on their maturity level.

  7. Add interactivity to the tech radar, such as tooltips that display more information about each item when the user hovers over it.

  8. Style the tech radar with CSS to make it visually appealing and easy to read.

Here's an example of how you could create the concentric circles using d3.js:

const radarData = [
  { level: 'adopt', radius: 100 },
  { level: 'trial', radius: 200 },
  { level: 'assess', radius: 300 },
  { level: 'hold', radius: 400 }
];

const svg = d3.select('svg');

svg.selectAll('circle')
  .data(radarData)
  .enter()
  .append('circle')
  .attr('cx', 500)
  .attr('cy', 500)
  .attr('r', d => d.radius)
  .attr('fill', 'none')
  .attr('stroke', 'black');

This code creates four circles with radii of 100, 200, 300, and 400, respectively, and positions them at the center of the SVG element. The fill attribute is set to none to make the circles transparent, and the stroke attribute is set to black to give them a black outline.

ekroon: How do I add this to my HTML file?

GitHub Copilot: To add the tech radar to your HTML file, you can follow these steps:

  1. Copy the code I provided earlier for creating the concentric circles using d3.js.

  2. Paste the code inside a <script> tag in your HTML file, either in the <head> or <body> section.

  3. Make sure to include a reference to the d3.js library in your HTML file, either by downloading it and linking to it locally, or by using a CDN. Here's an example of how to include the d3.js library from a CDN:

<!DOCTYPE html>
<html>
    <head>
        <title>Tech Radar</title>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    <body>
        <svg width="1000" height="1000"></svg>
        <script>
            // Paste the code for creating the concentric circles here
        </script>
    </body>
</html>

In this example, I've included a reference to the d3.js library from the official CDN. I've also added an SVG element to the <body> section with a width and height of 1000 pixels, and I've included the script for creating the concentric circles inside a <script> tag.

You can adjust the width and height of the SVG element to fit your needs, and you can modify the code for creating the concentric circles to match your data structure and styling preferences.

ekroon: /explain

GitHub Copilot: The code above is an example of how to create concentric circles using d3.js. The first line selects an SVG element in the HTML file using the d3.select() method. This method takes a CSS selector as an argument and returns a selection object that represents the first element in the document that matches the selector.

The next line uses the selectAll() method to select all circle elements inside the SVG element. Since there are no circle elements yet, this selection is empty.

The data() method is then called on the selection object, passing in an array of data called radarData. This array contains objects with two properties: level and radius. The level property represents the maturity level of the circle, and the radius property represents the radius of the circle.

The enter() method is called on the selection object to create a new set of elements based on the data. Since there are no circle elements yet, this method creates a new set of elements with a length equal to the length of the radarData array.

The append() method is then called on the new set of elements to append a circle element to each one. The attr() method is used to set the cx, cy, and r attributes of each circle based on the data. The fill attribute is set to none to make the circles transparent, and the stroke attribute is set to black to give them a black outline.

Overall, this code creates a set of concentric circles with different radii based on the radarData array. The circles are positioned at the center of the SVG element and have a black outline. This is just one example of how d3.js can be used to create visualizations in a web browser.

ekroon: What do the cx and cy attributes represent?

GitHub Copilot: The cx and cy attributes in SVG represent the center point of a circle. The cx attribute specifies the x-coordinate of the center point, and the cy attribute specifies the y-coordinate of the center point.

In the code excerpt you provided, the cx and cy attributes are both set to 500, which means that the center point of each circle is positioned at (500, 500) in the SVG element. This is the center of the SVG element, which has a width and height of 1000 pixels.

By setting the cx and cy attributes to the same value, the circles are positioned at the same point and are concentric. If you wanted to create circles that were not concentric, you could set the cx and cy attributes to different values for each circle.

ekroon: I would like the circles to be filled with gray colors, darker on the inside

GitHub Copilot: To fill the circles with gray colors that are darker on the inside, you can use a radial gradient. Here's an updated version of the code that uses a radial gradient to fill the circles:

<!DOCTYPE html>
<html>
    <head>
        <title>Tech Radar</title>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    <body>
        <svg width="1000" height="1000"></svg>
        <script>
            const radarData = [
              { level: 'adopt', radius: 100 },
              { level: 'trial', radius: 200 },
              { level: 'assess', radius: 300 },
              { level: 'hold', radius: 400 }
            ];

            const svg = d3.select('svg');

            const gradient = svg.append('defs')
              .append('radialGradient')
              .attr('id', 'gradient')
              .attr('cx', '50%')
              .attr('cy', '50%')
              .attr('r', '50%')
              .attr('fx', '50%')
              .attr('fy', '50%');

            gradient.append('stop')
              .attr('offset', '0%')
              .attr('stop-color', '#555')
              .attr('stop-opacity', 1);

            gradient.append('stop')
              .attr('offset', '100%')
              .attr('stop-color', '#000')
              .attr('stop-opacity', 1);

            svg.selectAll('circle')
              .data(radarData)
              .enter()
              .append('circle')
              .attr('cx', 500)
              .attr('cy', 500)
             

ekroon: Add a gray color to the radarData and use it to fill the circles with color.

GitHub Copilot: To add a gray color to the `radarData` and use it to fill the circles with color, you can modify the code for creating the circles as follows:

```javascript
const radarData = [
  { level: 'adopt', radius: 100, color: '#cccccc' },
  { level: 'trial', radius: 200, color: '#999999' },
  { level: 'assess', radius: 300, color: '#666666' },
  { level: 'hold', radius: 400, color: '#333333' }
];

const svg = d3.select('svg');

svg.selectAll('circle')
  .data(radarData)
  .enter()
  .append('circle')
  .attr('cx', 500)
  .attr('cy', 500)
  .attr('r', d => d.radius)
  .attr('fill', d => d.color)
  .attr('stroke', 'black');

In this modified code, each object in the radarData array now has a color property that specifies a gray color for the circle. The fill attribute of each circle is set to the corresponding color property using the d3 data binding syntax. This will fill each circle with the appropriate gray color based on its maturity level.

You can adjust the hex codes for the gray colors to match your desired color scheme.

ekroon: I had to reverse the circles in the radarData to not have the biggest circle overlap everything.

GitHub Copilot: To reverse the order of the circles in the radarData array, you can modify the array as follows:

const radarData = [
  { level: 'adopt', radius: 100, color: '#cccccc' },
  { level: 'trial', radius: 200, color: '#999999' },
  { level: 'assess', radius: 300, color: '#666666' },
  { level: 'hold', radius: 400, color: '#333333' }
];

In this modified array, the order of the objects has been reversed so that the smallest circle is first and the largest circle is last. This will ensure that the largest circle does not overlap with the other circles.

You can use this modified radarData array in the existing code for creating the circles, and the circles will be drawn in the new order.

ekroon: Instead of full circles I want circles that are split up in quarters and a bit apart.

GitHub Copilot: To create circles that are split up in quarters and spaced apart, you can modify the code for creating the circles as follows:

const radarData = [
  { level: 'adopt', radius: 100, color: '#cccccc' },
  { level: 'trial', radius: 200, color: '#999999' },
  { level: 'assess', radius: 300, color: '#666666' },
  { level: 'hold', radius: 400, color: '#333333' }
];

const svg = d3.select('svg');

svg.selectAll('g')
  .data(radarData)
  .enter()
  .append('g')
  .attr('transform', 'translate(500, 500)')
  .selectAll('path')
  .data(d => [
    { startAngle: 0, endAngle: Math.PI / 2 },
    { startAngle: Math.PI / 2, endAngle: Math.PI },
    { startAngle: Math.PI, endAngle: Math.PI * 1.5 },
    { startAngle: Math.PI * 1.5, endAngle: Math.PI * 2 }
  ])
  .enter()
  .append('path')
  .attr('d', d3.arc()
    .innerRadius(d => d.startAngle === 0 ? 0 : d3.scaleLinear()
      .domain([0, 3])
      .range([d3.max(radarData, d => d.radius) / 3, d3.max(radarData, d => d.radius)])
      (Math.floor(d.startAngle / (Math.PI / 2)))))
  .attr('fill', d => d3.color(d3.rgb(d.color)).darker(0.5 * (d.startAngle + d.endAngle) / Math.PI))
  .attr('stroke', 'black');

In this modified code, each circle is represented by a group (<g>) element that contains four quarter-circle segments (<path> elements). The transform attribute of each group element is set to translate(500, 500) to position the circles at the center of the SVG element.

The data() method is called on the selection of group elements to bind the radarData array to the elements. The selectAll() method is then called on the group elements to select all <path> elements inside each group.

The data() method is called again on the selection of <path> elements to bind an array of four objects to each element. Each object represents a quarter-circle segment and has startAngle and endAngle properties that define the start and end angles of the segment.

The enter() method is called on the selection of <path> elements to create a new set of elements based on the data. The append() method is then called on the new set of elements to append a <path> element to each one.

The attr() method is used to set the d attribute of each <path> element using the d3.arc() generator. The innerRadius of each arc is set based on the startAngle property of the quarter-circle segment, using a linear scale to map the segment to a range of radii from one-third to the maximum radius of the circles.

The fill attribute of each <path> element is set to a darker shade of the circle's color, based on the startAngle and endAngle properties of the quarter-circle segment. This creates a gradient effect that makes the circle look like it is split up into quarters.

The stroke attribute of each <path> element is set to black to give the segments a black outline.

Overall, this modified code creates circles that are split up into quarters and spaced apart, with a gradient effect that makes them look like they are made up of separate segments. You can adjust the colors and spacing of the circles by modifying the radarData array and the parameters of the d3.arc() generator.

ekroon: The screen is white

GitHub Copilot: If the screen is white, it's possible that the circles are being drawn outside of the visible area of the SVG element. You can try adjusting the translate attribute of the <g> element to move the circles into the visible area.

For example, you can try changing the translate attribute to translate(400, 400) to move the circles closer to the center of the SVG element:

const svg = d3.select('svg');

svg.selectAll('g')
  .data(radarData)
  .enter()
  .append('g')
  .attr('transform', 'translate(400, 400)')
  .selectAll('path')
  .data(d => [
    { startAngle: 0, endAngle: Math.PI / 2 },
    { startAngle: Math.PI / 2, endAngle: Math.PI },
    { startAngle: Math.PI, endAngle: Math.PI * 1.5 },
    { startAngle: Math.PI * 1.5, endAngle: Math.PI * 2 }
  ])
  .enter()
  .append('path')
  .attr('d', d3.arc()
    .innerRadius(d => d.startAngle === 0 ? 0 : d3.scaleLinear()
      .domain([0, 3])
      .range([d3.max(radarData, d => d.radius) / 3, d3.max(radarData, d => d.radius)])
      (Math.floor(d.startAngle / (Math.PI / 2)))))
  .attr('fill', d => d3.color(d3.rgb(d.color)).darker(0.5 * (d.startAngle + d.endAngle) / Math.PI))
  .attr('stroke', 'black');

You can also try adjusting the width and height attributes of the SVG element to make it larger, so that the circles are not cut off. For example, you can try changing the width and height attributes to 1200:

<svg width="1200" height="1200"></svg>

These changes should help ensure that the circles are visible within the SVG element.

ekroon: Still white screen

GitHub Copilot: If the screen is still white, there may be an issue with the SVG element itself. You can try adding a background color to the SVG element to see if it is visible. For example, you can add the following CSS rule to the <style> section of your HTML file:

svg {
  background-color: lightgray;
}

This will set the background color of the SVG element to light gray, which should be visible even if the circles are not.

If the background color is visible but the circles are not, there may be an issue with the data or the code that is generating the circles. You can try adding console.log statements to the code to see if it is being executed correctly and to check the values of the variables.

For example, you can add the following console.log statement after the svg variable is defined to check if it is being correctly selected:

console.log(svg);

You can also add console.log statements inside the data binding and element creation functions to check if they are being executed correctly and to check the values of the data and variables.

For example, you can add the following console.log statement inside the data() method to check the value of the radarData array:

console.log(radarData);

These console.log statements should help you identify any issues with the code or data that may be causing the circles to not be visible.

ekroon: I removed all the code for this statement: Instead of full circles I want circles that are split up in quarters and a bit apart.

GitHub Copilot: If you removed all the code for the statement "Instead of full circles I want circles that are split up in quarters and a bit apart", then the code should look like this:

<!DOCTYPE html>
<html>
    <head>
        <title>Tech Radar</title>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    <body>
        <svg width="1200" height="1200"></svg>
        <script>
            const radarData = [
                { level: 'hold', radius: 400, color: '#333333' },
                { level: 'assess', radius: 300, color: '#666666' },
                { level: 'trial', radius: 200, color: '#999999' },
                { level: 'adopt', radius: 100, color: '#cccccc' }
            ];

            const svg = d3.select('svg');

            svg.selectAll('circle')
              .data(radarData)
              .enter()
              .append('circle')
              .attr('cx', 500)
              .attr('cy', 500)
              .attr('r', d => d.radius)
              .attr('fill', d => d.color)
              .attr('stroke', 'black');
        </script>
    </body>
</html>

This code creates four full circles with different radii and colors, using the radarData array to set the radius and color of each circle. The circles are positioned at the center of the SVG element using the cx and cy attributes, and have a black stroke to outline them.

If you want to add the code back to create circles that are split up in quarters and spaced apart, you can copy and paste the modified code from my previous response into the <script> section of your HTML file.

ekroon: I want 2 half circles instead of a full circle

GitHub Copilot: To create two half circles instead of a full circle, you can modify the code to create two <path> elements instead of one <circle> element. Each <path> element will represent a half circle, and will be created using the d3.arc() generator.

Here's an example of how you can modify the code to create two half circles:

<!DOCTYPE html>
<html>
    <head>
        <title>Tech Radar</title>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    <body>
        <svg width="1200" height="1200"></svg>
        <script>
            const radarData = [
                { level: 'hold', radius: 400, color: '#333333' },
                { level: 'assess', radius: 300, color: '#666666' },
                { level: 'trial', radius: 200, color: '#999999' },
                { level: 'adopt', radius: 100, color: '#cccccc' }
            ];

            const svg = d3.select('svg');

            svg.selectAll('path')
              .data(radarData.slice(0, 2))
              .enter()
              .append('path')
              .attr('transform', 'translate(500, 500)')
              .attr('d', d3.arc()
                .innerRadius(0)
                .outerRadius(d => d.radius)
                .startAngle(d => d.level === 'hold' ? Math.PI : 0)
                .endAngle(d => d.level === 'hold' ? Math.PI * 2 : Math.PI))
              .attr('fill', d => d.color)
              .attr('stroke', 'black');
        </script>
    </body>
</html>

In this modified code, the selectAll() method is called on the SVG element to select all <path> elements. The data() method is then called on the selection to bind the first two objects in the radarData array to the elements. These objects represent the "hold" and "assess" levels, which will be used to create the two half circles.

The enter() method is called on the selection to create a new set of elements based on the data. The append() method is then called on the new set of elements to append a <path> element to each one.

The attr() method is used to set the transform attribute of each <path> element to translate(500, 500) to position the half circles at the center of the SVG element.

The d attribute of each <path> element is set using the d3.arc() generator. The innerRadius of each arc is set to 0 to create a half circle. The outerRadius of each arc is set based on the radius property of the corresponding object in the radarData array.

The startAngle and endAngle of each arc are set based on the level property of the corresponding object in the radarData array. The "hold" level creates a half circle that starts at Math.PI and ends at Math.PI * 2, while the "assess" level creates a half circle that starts at 0 and ends at Math.PI.

The fill attribute of each <path> element is set to the color property of the corresponding object in the radarData array. The stroke attribute is set to black to give the half circles a black outline.

Overall, this modified code creates two half circles instead of a full circle, using the radarData array to set the radius and color of each half circle.

ekroon: Both halves should have all the elements of radarData and be 20 pixels apart.

GitHub Copilot: To create two half circles that have all the elements of radarData and are 20 pixels apart, you can modify the code to create two sets of <g> elements, each containing a <path> element and a set of <circle> elements. The <path> element will represent the half circle, and the <circle> elements will be positioned around the half circle to represent the elements of radarData.

Here's an example of how you can modify the code to create two half circles with all the elements of radarData:

<!DOCTYPE html>
<html>
    <head>
        <title>Tech Radar</title>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    <body>
        <svg width="1200" height="1200"></svg>
        <script>
            const radarData = [
                { level: 'hold', radius: 400, color: '#333333' },
                { level: 'assess', radius: 300, color: '#666666' },
                { level: 'trial', radius: 200, color: '#999999' },
                { level: 'adopt', radius: 100, color: '#cccccc' }
            ];

            const svg = d3.select('svg');

            const halfCircleData = radarData.slice(0, 2);

            const halfCircleGroups = svg.selectAll('g')
              .data(halfCircleData)
              .enter()
              .append('g')
              .attr('transform', (d, i) => `translate(${i * 520 + 20}, 500)`);

            halfCircleGroups.append('path')
              .attr('d', d3.arc()
                .innerRadius(0)
                .outerRadius(d => d.radius)
                .startAngle(d => d.level === 'hold' ? Math.PI : 0)
                .endAngle(d => d.level === 'hold' ? Math.PI * 2 : Math.PI))
              .attr('fill', d => d.color)
              .attr('stroke', 'black');

            const circleData = radarData.slice(2);

            const circleGroups = halfCircleGroups.selectAll('g')
              .data(circleData)
              .enter()
              .append('g')
              .attr('transform', (d, i) => `rotate(${i * 90}) translate(${d.radius + 20}, 0)`);

            circleGroups.append('circle')
              .attr('r', 10)
              .attr('fill', d => d.color)
              .attr('stroke', 'black');
        </script>
    </body>
</html>

In this modified code, the radarData array is defined as before, and the svg variable is defined to select the SVG element.

The halfCircleData variable is defined to contain the first two objects in the radarData array, which represent the "hold" and "assess" levels.

The halfCircleGroups variable is defined to select all <g> elements in the SVG element, and bind the halfCircleData array to them using the data() method. The enter() method is then called on the selection to create a new set of elements based on the data. The append() method is called on the new set of elements to append a <g> element to each one.

The attr() method is used to set the transform attribute of each <g> element to position it at the center of the SVG element, with a 20 pixel gap between the two half circles.

The append() method is called on each <g> element to append a <path> element to represent the half circle. The d attribute of each <path> element is set using the d3.arc() generator, as before.

The fill and stroke attributes of each <path> element are set to the color property of the corresponding object in the radarData array.

The circleData variable is defined to contain the last two objects in the radarData array, which represent the "trial" and "adopt" levels.

The circleGroups variable is defined to select all <g> elements within the halfCircleGroups selection, and bind the circleData array to them using the data() method. The enter() method is then called on the selection to create a new set of elements based on the data. The append() method is called on the new set of elements to append a <g> element to each one.

The attr() method is used to set the transform attribute of each <g> element to position it around the corresponding half

ekroon: I retract this statement: Both halves should have all the elements of radarData and be 20 pixels apart.

GitHub Copilot: Understood, let me know if you have any other questions or if there's anything else I can help you with!.

Releases

No releases published

Packages

No packages published

Languages