What is the technique for adding a stroke to an SVG border?

I am in the process of creating a gauge component using SVG. I'm using two strokes to show two states simultaneously. Currently, my output looks like this: enter image description here

enter image description here

However, I would like it to look like this: To close off the end of the hatch part. enter image description here I'm not sure how to achieve closing this end... Can <filter> and :fill be used together?

 .circle-front {
      stroke-dasharray: 120;
      stroke: #333;
      stroke-width: 5.5px;
      transform: translate(2px, 5px) rotate(148deg);
      transform-origin: center;
    }

    .circle-back {
      stroke-dasharray: 120;
      stroke-dashoffset: 39;
      stroke: rgba(255, 255, 255, 0.2);
      transform: translate(2px, 5px) rotate(148deg);
      stroke-width: 5;
      transform-origin: center;   
    }

    .circle-oblique {
      stroke-dasharray: 120;
      /* stroke: #333; */
      stroke-linejoin: round;

      stroke-width: 4.5px;
      transform: translate(2px, 5px) rotate(148deg);
      transform-origin: center;
    }
<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <svg
          width="110"
          height="110"
          viewBox="0 0 60 54"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g filter="url(#filter0_d_711_531)">
            <circle cx="29.7727" cy="30.2273" r="19" className="circle-back" />
          </g>
          <circle
            cx="29.7727"
            cy="30.2273"
            r="19"
            stroke="url(#vertical-stripe-2)"
            className="circle-oblique"
            strokeDashoffset="90"
          />
          <defs>
            {" "}
            <pattern
              id="vertical-stripe-2"
              patternUnits="userSpaceOnUse"
              width="2"
              height="2"
            >
              {" "}
              <image
                xlinkHref="data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+CiAgPHJlY3Qgd2lkdGg9JzEwJyBoZWlnaHQ9JzEwJyBmaWxsPSd3aGl0ZScgLz4KICA8cmVjdCB4PScwJyB5PScwJyB3aWR0aD0nMicgaGVpZ2h0PScxMCcgZmlsbD0nYmxhY2snIC8+Cjwvc3ZnPg=="
                x="0"
                y="0"
                width="2"
                height="2"
              >
                {" "}
              </image>{" "}
            </pattern>{" "}
          </defs>
          <circle
            cx="29.7727"
            cy="30.2273"
            r="19"
            className="circle-front"
            strokeDashoffset="43"
          />
          <defs>
            <filter id="filter0_d_711_531">
              <feFlood floodOpacity="0" result="BackgroundImageFix" />
              <feColorMatrix
                in="SourceAlpha"
                type="matrix"
                values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0"
              />
              <feOffset />
              <feGaussianBlur stdDeviation="0.3" />
              <feComposite in2="hardAlpha" operator="out" />
              <feColorMatrix
                type="matrix"
                values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0"
              />
            </filter>
          </defs>
        </svg>
    </body>
    </html>

Answer №1

Using filters for pixel-oriented operations when they are not truly necessary can be confusing and performance-heavy. In this case, it appears that the sole purpose of the filter is to draw a border, which is actually a vector operation. A more efficient solution would be to utilize paths instead.

To achieve the desired effect, vector-based <pattern> content is employed rather than an image.

(The provided code example is not self-explanatory or functional, so I will disregard it.) Based on the images provided, it seems that the border should encompass the entire gauge area regardless of the displayed values. This suggests that the border can be drawn once without needing dynamic data. The dividing lines within the gauge area can then be represented as short perpendicular lines bisecting the space. Rotating them dynamically will place them correctly. The areas themselves should be drawn separately below the borders.

I have included the dynamic data as CSS variables in this example. However, integrating them via JavaScript scripting should be straightforward – simply replace the CSS properties referencing these variables with the appropriate method to insert values, likely through presentation attributes.

svg {
  height: 100vh;
  --val1: 0.4;
  --val2: 0.6;
}
symbol {
  overflow: visible;
}
.area {
  fill:none;
  stroke-width: 15;
}
.stroke {
  fill:none;
  stroke: #333;
  stroke-width: 2;
  stroke-linejoin: round;
}
#area-1 {
  stroke: #333;
  stroke-dasharray: calc(var(--val1) * 100px) 100px;
}
#limit-1 {
  transform: rotate(calc(45deg + var(--val1) * 270deg));
}
#area-2 {
  stroke: url(#hatch);
  stroke-dasharray: calc(var(--val2) * 100px) 100px;
}
#limit-2 {
  transform: rotate(calc(45deg + var(--val2) * 270deg));
}
<svg viewBox="-60 -60 120 120">
  <symbol id="limit">
    <path d="M 0,41 V 54" />
  </symbol>
  <pattern id="hatch" patternUnits="userSpaceOnUse" width="16" height="8">
    <path class="stroke" d="M -2,-6 18,4 M -2,2 18,12 M -2,10 18,20" />
  </pattern>
  <!-- data areas in reverse order -->
  <path id="area-2" class="area" d="M -33.588,33.587 A 47.5,47.5 0 1 1 33.588,33.588" pathLength="100" />
  <path id="area-1" class="area" d="M -33.588,33.587 A 47.5,47.5 0 1 1 33.588,33.588" pathLength="100" />
  <g class="stroke">
    <!-- static outer border -->
    <path d="M -38.184,38.184 A 54,54 0 1 1 38.184,38.184 L 28.991,28.991 A 41,41 0 1 0 -28.991,28.991 Z" />
    <!-- bisecting data lines, cited from a template -->
    <use id="limit-1" href="#limit" />
    <use id="limit-2" href="#limit" />
  </g>
</svg>

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

Enlarging the current division while reducing the size of the others when hovering

Currently, I am working on a school project that involves creating a slideshow on a webpage. However, I have reached a point where I am unsure of how to proceed. Here is the progress I have made so far: body { background-color: #252525; } #wrapper { ...

How to select a button within a table using Selenium and C#?

I'm struggling with a section of HTML code. My goal is to use the selenium chrome driver in C# to navigate a website and create a ticket. However, I've encountered an issue where I need to select a tab to check some checkboxes, but all the tabs h ...

require an array that contains an embedded object

When making a post request, I need to include an array with an object inside. I have observed that adding new properties inside an object works fine. However, when attempting to add properties while the object is inside an array, it does ...

Using a for loop within a ul tag in HTML

If I needed to display the numbers 0 to 4 on an HTML page, how should I modify this code snippet to achieve that? <ul> {% for i in range(5) %} <li><a>i</a></li> {% endfor %} </ul> ...

Confusion Arises When Joomla Buttons Clash

I am facing an issue with two modules on my website, each containing a button code. The code for the buttons is as follows: First Button <div onclick="parent.location='first-link'" data-mce-onclick=""><button class="button">First Bu ...

After inputting new values, the table is not allowing me to update it

Recently acquainted with Angular, I am in the process of inserting new values and displaying them in a table using three components. These components include one for listing user information user-list, one for creating information rows user-form, and one f ...

What are the steps to create a horizontal submenu in WordPress?

Is there a way to change the default vertical sub menu of my main menu to horizontal? The CSS for the sub menu in stylesheet.css is as follows: .main-nav>ul>li .sub-menu> li { padding:0 20px; } .main-nav>ul>li .sub-menu> li:first-ch ...

The wrapper refuses to display the background image, although it functions properly on other HTML elements

Currently, I am attempting to assign a background to a wrapper in order to create an infinite sidebar. Strangely enough, the background applies correctly when I use the same CSS rules on any other HTML element except for .wrapper. Below is the HTML code: ...

What is causing my background div to jerk around when I implement jQuery animate to adjust its height?

UPDATE: I have replicated my issue in jsFiddle: http://jsfiddle.net/leongaban/3v8vW/3/ I am dealing with 2 tabs - one should reduce the height of the form-background when clicked, while the other should increase it. I want a smooth animation without any a ...

Tips for expanding the dimensions of a text box within the filter menu

In my application, I am using a kendo grid with filterable set to true. The filtering functionality is working properly. However, when I click on the filter symbol, the filter menu opens and I noticed that the size of the text-box within the menu is too sm ...

What could be the reason for the compatibility issues between CSS/SASS modules and a third-party library?

I am puzzled by the fact that my sass modules do not affect the third-party component I am using, specifically react-horizontal-scrolling-menu <ScrollMenu selected={selected} scrollToSelected={true} data={items && items.map((item: any) ...

Styling images side by side with CSS in Internet Explorer

I've encountered a CSS dilemma. I have a collection of images that I want to present side by side using an unordered list within a fixed width container. The goal is to have 3 images per row before moving on to the next set of 3 images. Each list ite ...

Repositioning the li element at the beginning of the list

I'm working on a collapsible Material UI feature and I want to ensure that when a user clicks on an item, it stays at the top of the list. For example, let's say we have a default list with items First, Second, and Third. When the user expands t ...

Unusual sequence of JQuery Ajax calls

Within my website, there is a project div that is displayed using EJS. The data for the projects in EJS are rendered using a forEach loop, resulting in multiple similar divs appearing on the page. Each project div is assigned an id for identification pur ...

Three.js is failing to render within a specified div

My current project involves utilizing three.js to create a cube rendering. Despite the cube appearing on the screen, I am facing issues with getting it to display within the specified div element and in the desired style. HTML: <div id="render"> & ...

Why do certain HTML elements fail to display when using ngIf?

I am facing an issue with two buttons that should display differently based on the outcome of an ngIf condition. When the page is loaded for the first time, both buttons do not appear until the page is manually refreshed, even though they are supposed to w ...

What is causing the child table (toggle-table) to duplicate every time a row in the parent table is clicked?

After creating a table containing GDP data for country states, I've noticed that when a user clicks on a state row, the child table displaying district GDP appears. However, there seems to be an issue with the child table as it keeps repeating. I&apos ...

How can images be resized according to screen resolution without relying on javascript?

Looking to use a large banner image on my website with dimensions of 976X450. How can I make sure that the image stretches to fit higher resolution monitors without using multiple images for different resolutions? ...

Creating an HTML Table on the Fly

Is there a way to dynamically generate multiple HTML tables or ASP tables? I attempted the following code but it didn't work as expected. Table tb = new Table(); tb.ID = "tbl" + TBname; TableRow rowNew = new TableRow(); tb.Controls.Add(rowNew); for ( ...

Verify the validity of a form using JavaScript and by utilizing HTML5 validation, then proceed to save the form data in local storage

I'm fairly new to working with JavaScript and jQuery. Currently, I am attempting to validate the HTML5 validation of a form using JavaScript. When the form is valid, I want to save the data in localstorage WITHOUT having to reload the webpage. Here is ...