Outlining and Partially Filling an Svg Shape

Outlining and partially filling an SVG Shape

You can alternatively do this with a filter. Here is one that animates the fill:

<svg height="210" width="500">  <defs>    <filter id="fillpartial" primitiveUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">      <feFlood x="0%" y="0%" width="100%" height="100%" flood-color="red" />      <feOffset dy="0.5">        <animate attributeName="dy" from="1" to=".5" dur="3s" />      </feOffset>      <feComposite operator="in" in2="SourceGraphic" />      <feComposite operator="over" in2="SourceGraphic" />    </filter>  </defs>  <polygon filter="url(#fillpartial)" points="165.000, 185.000, 188.511, 197.361, 184.021, 171.180, 203.042, 152.639, 176.756, 148.820, 165.000, 125.000, 153.244, 148.820, 126.958, 152.639, 145.979, 171.180, 141.489, 197.361, 165.000, 185.000" style="fill:white;stroke:red;" /></svg>

svg outline and fill

Rather than trying to fill in what you have which is currently a path that makes up only the "stroke" (which in this case is actually the entire SVG), it would be much easier to use a heart shape that is solid and then change the attributes with a simple classList.toggle javascript. This way, you could control the stroke and the fill independently.

let svg = document.getElementById("heart");
svg.addEventListener('click', function() {
svg.classList.toggle("filled");
})
body {
background-color: lightgrey;
}

#heart {
fill: transparent;
stroke: red;
stroke-width: 20px;
transition: all 0.6s linear;
}

#heart.filled {
fill: red;
stroke: red;
stroke-width: 20px;
transition: all 0.6s linear;
}
<svg id="heart" xmlns="http://www.w3.org/2000/svg" height="200px" width="200px" viewBox="0 0 612 792">
<path d="M611.721,288.299c-2.258-42.176-20.114-81.782-50.287-111.524c-30.557-30.119-70.43-46.708-112.27-46.708
c-62.267,0-107.396,49.233-131.641,75.684c-3.743,4.085-8.13,8.87-11.183,11.79c-2.444-2.529-5.756-6.3-8.803-9.768
c-22.142-25.222-68.223-77.704-134.688-77.704c-41.84,0-81.711,16.588-112.268,46.708C20.408,206.517,2.547,246.121,0.29,288.299
c-2.248,42.107,8.521,78.746,34.92,118.803c20.888,31.701,75.961,93.605,133.927,150.543c29.856,29.326,57.336,54.18,79.466,71.873
c35.936,28.729,49.7,32.413,57.674,32.413c7.476,0,21.614-3.352,57.895-32.332c22.079-17.637,49.463-42.451,79.194-71.76
c57.445-56.63,112.318-118.617,133.443-150.743C594.576,380.072,614.6,342.151,611.721,288.299z"/>
</svg>

Fill partially an SVG image with react using CSS

I'd use a linear gradient. You can vary the offset attribute using react as you want to fill the star.

<svg id="Livello_1" data-name="Livello 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96.26 91.88">
<defs>
<linearGradient id="fill">
<stop offset="30%" stop-color="#ff8d1e"></stop>
<stop offset="30%" stop-color="white"></stop>
<style>
.cls-1 {
fill: none;
stroke: #ff8d1e;
stroke-miterlimit: 10;
stroke-width: 4px;
fill-rule: evenodd;
fill: url("#fill");
}
</style>
</defs>
<title>stella vuota</title>
<path class="cls-1" d="M38.91,36.22a1.26,1.26,0,0,0,1.43-1c1.23-3.94,9.34-29.69,9.34-29.69A2.42,2.42,0,0,1,50.52,4a1.82,1.82,0,0,1,2.78,1.1l9.49,30.15a1.13,1.13,0,0,0,1.3,1l31.33,0a2.1,2.1,0,0,1,1.94.85,1.65,1.65,0,0,1-.56,2.45L71.39,57.32a1.61,1.61,0,0,0-.73,2.22L80.32,88.3c.34,1,.81,2.08-.32,2.91s-2,.08-2.86-.57L53.51,73.16c-2-1.45-1.94-1.46-3.85,0L25.81,90.79a5.6,5.6,0,0,1-1.07.66A1.59,1.59,0,0,1,23,91.12a1.54,1.54,0,0,1-.56-1.73L32.56,59c.18-.53.25-.92-.32-1.32L6.68,39.78C5.61,39,5.25,38.3,5.52,37.46s.92-1.26,2.25-1.26Z" transform="translate(-3.43 -1.7)"/>
</svg>

How to fill an SVG element half portion by a pattern

What you could do is create two circles and apply mask on one with fill

<svg width="105px" height="105px">  <mask x="0" y="0" id="half">    <rect y="50%" fill="white" width="100%" height="50%" />  </mask>    <circle fill="transparent" stroke="black" stroke-width="3px" cx="50%" cy="50%" r="50"/>  <circle fill="#C04C4C" mask="url(#half)" stroke="black" stroke-width="3px" cx="50%" cy="50%" r="50"/></svg>

Outline a group of touching shapes with SVG

Like this:

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="biggerbwcopy">
<feColorMatrix values="0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0"/>
<feMorphology operator="dilate" radius="2"/>
</filter>
</defs>
<rect id="r" x="10" y="10" width="20" height="20" fill="blue" onclick="biggerbw()"/>
<script>

function biggerbw() {
document.getElementById("r").style.filter="url(#biggerbwcopy)";
}
</script>
</svg>

http://jsfiddle.net/longsonr/LrDHT/1/ click on the rectangle and it becomes black and bigger.

You could extend the filter to put the original shape on top using feMerge

Segemented SVG Outlined Circle

Instead of all Math, let a native Web Component <svg-segments> do the work.

The important part in the created SVG <path> are the pathLength and stroke-dasharray values

All you specify, is a string of colors defining how many and what color segments are drawn.

A none color will create an empty segment:

<svg-segments parts="red,,blue"></svg-segments>

Sample Image

In the SO snippet below; click the circles to add more segments

<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:10px;background:grey">
<svg-segments parts="red,green,blue"></svg-segments>
<svg-segments parts="red,,blue"></svg-segments>
<svg-segments parts=",,red"></svg-segments>
<svg-segments parts="red,green,blue,purple" width="5"></svg-segments>
<svg-segments parts="red,,,green,,blue,,red,red" width="50"></svg-segments>
</div>
<script>
customElements.define("svg-segments", class extends HTMLElement {
static get observedAttributes() {
return ["parts", "size"]; // svg is redrawn at *every* attribute update!
}
attributeChangedCallback() {
this.parts = this.getAttribute("parts").split(",");
let vb = 200; // viewPort size; might need to tweak this
let width = this.getAttribute("width") || 25; // stroke-width
let a = vb / 2 - width/2; // calculate circle arcs
let b = vb - width;
this.innerHTML = `<svg viewBox='0 0 ${vb} ${vb}'>` +
this.parts.map((col, idx) => {
if (col)
return `<path d='M${width/2},${vb/2}a${a},${a} 0 1,0 ${b},0a${a},${a} 0 1,0 -${b},0'
fill='none' stroke-width='${width}' pathLength='${this.parts.length}'
stroke='${col}' stroke-dashoffset='${idx}'
stroke-dasharray='1 ${this.parts.length-1}'/>`;
else return ``;
}) + `</svg>`;
}
connectedCallback() {// for StackOverflow Snippet demo purpose only
this.onclick = (evt) => {
let moreparts = this.parts.join(",") + ",red";
this.setAttribute("parts", moreparts);
}
}
})
</script>

is it possible to make SVG circle fill color from bottom to top based on percentage?

you could use a gradient with stop-opacity to do this.
you would add two "middle" stops with opacity 0 and 1 respectively an set the offset of both to the percentage you need.