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>
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.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200"> <linearGradient id="lg" x1="0.5" y1="1" x2="0.5" y2="0"> <stop offset="0%" stop-opacity="1" stop-color="royalblue"/> <stop offset="40%" stop-opacity="1" stop-color="royalblue"/> <stop offset="40%" stop-opacity="0" stop-color="royalblue"/> <stop offset="100%" stop-opacity="0" stop-color="royalblue"/> </linearGradient> <circle cx="50" cy="50" r="45" fill="url(#lg)" stroke="crimson" stroke-width="5"/></svg>
Related Topics
Fixed Sidebar Navigation in Fluid Twitter Bootstrap 2.0
How to Select All Children of an Element Except the Last Child
Google Chrome Extensions - Can't Load Local Images With Css
Sass - Use Variables Across Multiple Files
Display:Inline VS Display:Block
How to Create Div to Fill All Space Between Header and Footer Div
Draw Diagonal Lines in Div Background With Css
How to Include a Font Awesome Icon in My Svg
Height:100% VS Min-Height:100%
Is a Relative Path in a CSS File Relative to the CSS File
Css Best Practice About Id and Class
How to Have Css3 Animation to Loop Forever
How to Apply Multiple Background Colors With Css3