I am trying to do something similar to this post but can't get it to work in react js. I tried several different methods, but didn't really get any progress. If i use transform rotate (deg, cx, cy) it moves all over the place and is hidden. When I tried the transform3d as in the post, it doesn't move at all. please help, thanks.
import React, { useState, useRef } from "react";
// import SVGStyles from "./SVGStyles";
function SVGComponent() {
const svgRef = useRef(null);
const [rotate, setRotate] = useState(45);
const [viewBox, setviewBox] = useState("0 0 24 24");
function handleChange(event) {
setRotate(event.target.value);
}
function rotateSvg() {
if (svgRef.current) {
const bbox = svgRef.current.getBBox();
const cx = bbox.x + bbox.width / 2;
const cy = bbox.y + bbox.height / 2;
// setviewBox([bbox.x, bbox.y, bbox.width, bbox.height].join(" "));
svgRef.current.style.setProperty("--r", `${rotate}deg`);
// svgRef.current.setAttribute(
// "transform",
// `rotate(${rotate}), ${cx}, ${cy}`
// );
}
}
return (
<>
<svg ref={svgRef}>
<Triangle viewBox={viewBox} style={{ border: "1px solid red" }} />
</svg>
<br />
<br />
<br />
<br />
<label>
Angle:
<input
type="range"
min="0"
max="360"
value={rotate}
onChange={handleChange}
/>
{rotate}°
</label>
<button onClick={rotateSvg}>Rotate</button>
</>
);
}
const Triangle = (props) => (
<svg
height="100%"
viewBox={props.viewBox}
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={props.style}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="m13.789 1.578 9.764 19.528A2 2 0 0 1 21.763 24H2.237a2 2 0 0 1-1.789-2.894l9.764-19.528a2 2 0 0 1 3.578 0Z"
fill="#758CA3"
/>
</svg>
);
export default SVGComponent;
The css is verbatim from the post:
svg {
transform-origin: 50% 50%;
transform-box: fill-box;
transform: translate3d(25px, 25px, 0) rotate(var(--r, 0deg));
border: 1px dotted red;
}
Related
I am using Strapi as a backend, and in my frontend I am using Gatsby.
I am using the values from the backend to draw a circle inside a card. The number of cards are generated from the backend value.
For now I am hard coding the three first cards in css with n:th child values with the following css code:
.svgAssesment circle {
width: 100%;
height: 100%;
fill: none;
stroke-width: 10;
stroke: rgba(255, 255, 255, 0.05);
transform: translate(5px, 5px);
stroke-linecap: round;
}
.svgAssesment circle:nth-child(2) {
stroke: #fff;
stroke-dasharray: 440px;
}
.card:nth-child(1) .svgAssesment circle:nth-child(2) {
stroke-dashoffset: calc(440px - (440px * 9) / 10);
}
.card:nth-child(2) .svgAssesment circle:nth-child(2) {
stroke-dashoffset: calc(440px - (440px * 9) / 10);
}
.card:nth-child(3) .svgAssesment circle:nth-child(2) {
stroke-dashoffset: calc(440px - (440px * 8) / 10);
}
Instead of hard coding these values, is there a way to draw them dynamically so that each circle's stroke-dashoffset is based upon the prop {item.rate} I have in my frontend.
So in the example above the hard coded values are 9,9 and 8 should be replaced with the values of {item.rate} for each of the cards generated and not just the three I have in my nth:child code.
This is my frontend code:
import React from "react"
import Title from "./Title"
import { graphql, useStaticQuery } from "gatsby"
const query = graphql`
{
allStrapiAssessment {
nodes {
title
rating {
id
topic
rate
}
}
}
}
`
const SelfAssesment = () => {
const data = useStaticQuery(query)
//console.log(data)
const {
allStrapiAssessment: { nodes: assesments },
} = data
//console.log(assesments)
const [value] = React.useState(0)
const { title, rating } = assesments[value]
console.log(title, rating)
return (
<section className="section jobs">
<Title title={title} />
<section className="assesment">
<div className="container">
{rating.map(item => {
return (
<div key={item.id} className="card">
<div className="box">
<div>
<div class="percent">
<svg className="svgAssesment">
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>
{item.rate}
<span>/10</span>
</h2>
</div>
</div>
</div>
</div>
<div id="buttonColor" className="text">
{item.topic}
</div>
</div>
)
})}
</div>
</section>
</section>
)
}
export default SelfAssesment
You will need to use styled-components in order to use React props in the styling.
Alternatively, you can just use inline styles for stroke-dashoffset CSS rule and delegate the rest of the styling into your CSS stylesheet. Something like:
import React from "react"
import Title from "./Title"
import { graphql, useStaticQuery } from "gatsby"
const query = graphql`
{
allStrapiAssessment {
nodes {
title
rating {
id
topic
rate
}
}
}
}
`
const SelfAssesment = () => {
const data = useStaticQuery(query)
//console.log(data)
const {
allStrapiAssessment: { nodes: assesments },
} = data
//console.log(assesments)
const [value] = React.useState(0)
const { title, rating } = assesments[value]
console.log(title, rating)
return (
<section className="section jobs">
<Title title={title} />
<section className="assesment">
<div className="container">
{rating.map(item => {
return (
<div key={item.id} className="card">
<div className="box">
<div>
<div class="percent">
<svg className="svgAssesment">
<circle cx="70" cy="70" r="70"/>
<circle cx="70" cy="70" r="70" style={{
strokeDashoffset: `calc(440px - (440px * ${item.rate}) / 10)`
}}/>
</svg>
<div class="number">
<h2>
{item.rate}
<span>/10</span>
</h2>
</div>
</div>
</div>
</div>
<div id="buttonColor" className="text">
{item.topic}
</div>
</div>
)
})}
</div>
</section>
</section>
)
}
export default SelfAssesment
Note the:
<circle cx="70" cy="70" r="70" style={{
strokeDashoffset: `calc(440px - (440px * ${item.rate}) / 10)`
}}/>
In the snippet above you are just calculating the stroke-dashoffset rule with inline styles applying the dynamic item.rate value in the second circle.
I currently have a rating system that produces 5 stars that can show half values. I did this by using FontAwesome's Half Stars and did some CSS tricks to make them look like one star. But I was thinking of increasing my React and CSS knowledge by coming up with a way to show only half of an SVG icon. So instead of using the Half Stars, I could use whatever Icon the user wanted, and it would only show 50% of the Icon for example if you wanted to give a 3.5 rating.
Q: Can you show only half of an Icon and somehow know if the user is clicking on one side or the other?
Here is the code I have currently that uses the HalfStars for a little bit of reference
import React, { useState } from 'react'
import { FaRegStarHalf, FaStarHalf } from 'react-icons/fa'
import './styles/Rater.css'
const Rater = ({ iconCount }) => {
const [rating, setRating] = useState(null)
const [hover, setHover] = useState(null)
// check if user has set a rating by clicking a star and use rating to determine icons
const Star = rating ? FaStarHalf : FaRegStarHalf
return (
<div>
{[...Array(iconCount), ...Array(iconCount)].map((icon, i) => {
const value = (i + 1) / 2
return (
<label>
<input
type='radio'
name='rating'
value={value}
onClick={() => {
console.log(`value => `, value)
return setRating(value)
}}
/>
<div className='star-container'>
<div>
<Star
className={i % 2 ? 'star-left' : 'star'}
color={value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
onMouseEnter={() => setHover(value)}
onMouseLeave={() => setHover(null)}
/>
</div>
</div>
</label>
)
})}
</div>
)
}
export default Rater
I have written a code to get you the idea; If you click on the right side of the star, its color changes to blue and if you click on the left side, its color changes to gold. Also, it's better to not use stopPropagation and check e.target of the event.
const starIcon = document.getElementById("star");
const icon = document.getElementById("icon");
starIcon.onclick = e => {
starIcon.style.color = "blue";
e.stopPropagation();
};
icon.onclick = e => {
starIcon.style.color = "gold";
}
i {
clip-path: inset(0 0 0 50%);
color: gold;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" rel="stylesheet">
</head>
<body>
<span id="icon"><i id="star", class="fas fa-star"></i></span>
</body>
</html>
You can do it in ONE SVG
I ditched the Font-Awesome icon
searched for "star" in the 7000+ icons on https://iconmeister.github.io/ (first load takes a minute)
Picked the star icon with the best d-path (Clarity Iconset: cl-social-star-solid)
copied only the d-path
Edited the d-path in https://yqnn.github.io/svg-path-editor/ to a 100x100
viewBox/grid
made it an inverse star by prepending M0 0h100v100h-100v-100 to the path
Created a new SVG file in a 0 0 300 100 viewBox to fit 3 stars.. see below
Added a background rectangle setting gold color rating with width="50%"
Used 3 inverse stars, each at an x-offset
added 6 rectangles covering all half-stars
set inline events on every "half-star"
(the click works in this SO snippet, but SO adds a long delay)
Proof of Concept
<svg viewBox="0 0 300 100" width="500px">
<rect id="rating" width="50%" fill="gold" height="100%" />
<path id="star" fill="green"
d="M0 0h100v100h-100v-100m91 42a6 6 90 00-4-10l-22-1a1 1 90 01-1
0l-8-21a6 6 90 00-11 0l-8 21a1 1 90 01-1 1l-22 1a6 6 90 00-4
10l18 14a1 1 90 010 1l-6 22a6 6 90 008 6l19-13a1 1 90 011 0l19
13a6 6 90 006 0a6 6 90 002-6l-6-22a1 1 90 010-1z"/>
<use href="#star" x="100" />
<use href="#star" x="200" />
<rect id="c" width="16.66%" height="100%" fill="transparent" stroke="red"
onclick="console.log(this)" />
<use href="#c" x="50" />
<use href="#c" x="100" />
<use href="#c" x="150" />
<use href="#c" x="200" />
<use href="#c" x="250" />
</svg>
A Star Rating Component <star-rating stars=N >
You don't want to create all this SVG by hand... couple lines of JavaScript can create the SVG, for any number of stars
Using a W3C standard Web Component here, because it runs in this page and is not as complex as a React Component.
https://developer.mozilla.org/en-US/docs/Web/Web_Components
Not using <use>, just duplicate all paths and rects with a x offset
mouseover events set the background % color
click shows the index of the clicked halfstar (0+)
Rating can be set with values or percentage; document.querySelector('[stars="5"]').rating="90%" (4.5 stars)
needs extra work for your use case
All required HTML & JavaScript:
<star-rating stars=5 rating="3.5"
bgcolor="green" nocolor="grey" color="gold"></star-rating>
<star-rating stars=7 rating="50%"
bgcolor="rebeccapurple" nocolor="beige" color="goldenrod"></star-rating>
<script>
document.addEventListener("click", (evt) => console.log(evt.target.getAttribute("n")))
customElements.define("star-rating", class extends HTMLElement {
set rating( rate ) {
if (!String(rate).includes("%")) rate = Number(rate) / this.stars * 100 + "%";
this.querySelector("#rating").setAttribute("width", rate);
}
connectedCallback() {
let { bgcolor, stars, nocolor, color, rating } = this.attributes;
this.stars = ~~stars.value || 5;
this.innerHTML =
`<svg viewBox="0 0 ${this.stars*100} 100" style="cursor:pointer;width:300px">`
+ `<rect width="100%" height="100" fill="${nocolor.value}"/>`
+ `<rect id="rating" height="100" fill="${color.value}" />`
+ Array( this.stars ).fill()
.map((i, n) => `<path fill="${bgcolor.value}" d="M${ n*100 } 0h102v100h-102v-100m91 42a6 6 90 00-4-10l-22-1a1 1 90 01-1 0l-8-21a6 6 90 00-11 0l-8 21a1 1 90 01-1 1l-22 1a6 6 90 00-4 10l18 14a1 1 90 010 1l-6 22a6 6 90 008 6l19-13a1 1 90 011 0l19 13a6 6 90 006 0a6 6 90 002-6l-6-22a1 1 90 010-1z"/>`)
.join("")
+ Array( this.stars * 2 ).fill()
.map((i, n) => `<rect x="${ n*50 }" n="${n}" opacity="0" width="50" height="100"`
+ ` onclick="dispatchEvent(new Event('click'))" `
+ ` onmouseover="this.closest('star-rating').rating = ${(n+1)/2}"/>`)
.join("")
+ "</svg>";
this.rating = rating.value;
}
});
</script>
Notes:
This native <star-rating> Component (also called Custom Element because NO shadowDOM is involved) has ZERO dependencies
no libraries
no external SVG
native components are not self-closing tags and must contain a hyphen, so notation is: <star-rating></star-rating>
Changed the star to M0 0h102v100h-102v-100 (2 pixel overlap) to cover SVG rounding issues
Supported in all Frameworks... except...
React doesn't support this modern W3C Web Components Standard yet.
React scores just 71% on https://custom-elements-everywhere.com/
All other Frameworks (Angular, Vue, Svelte) have 100% support
You have to do some extra work to handle native DOM Elements and Events in React; but the Custom Element isn't complex.. it creates SVG; should be easy to replicate as a React Component.
Here is a different idea using 3D transformation:
i {
color: gold;
}
.container {
background: #fff;
transform-style: preserve-3d;
}
.half {
transform: rotateY(1deg);
}
i.fa-star:hover {
color:red;
}
<link href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" rel="stylesheet">
<div class="container">
<i id="star" class="fas fa-star fa-5x"></i>
<i id="star" class="fas fa-star fa-5x"></i>
<i id="star" class="fas fa-star fa-5x"></i>
<i id="star" class="fas fa-star fa-5x half"></i>
</div>
<div class="container">
<i id="star" class="fas fa-star fa-5x"></i>
<i id="star" class="fas fa-star fa-5x half"></i>
</div>
The simplest solution I can think of is to have a row of the svg icons and then use overflow:hidden to clip up to the user's selection.
Then using half the width of the icon, it can go by half increments.
$(document).ready(function()
{
$(document).on("mousemove", ".star-container.unvoted", function(e)
{
let width = $(this).find(".star").width() / 2;
e.clientX = Math.ceil(e.clientX /= (width)) * width;
$(this).find(".inner").css("width", e.clientX + "px");
});
$(".star-container.unvoted").click(function(e)
{
$(this).removeClass("unvoted");
});
});
.star-container .inner{
overflow: hidden;
width:100%;
height:100%;
}
.star-container .inner .star{
display:inline-block;
width:20px;
height:20px;
background-image:url('https://www.flaticon.com/svg/static/icons/svg/1828/1828884.svg');
background-size:contain;
}
.star-container .inner .inner-2{
width:10000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="star-container unvoted">
<div class="inner">
<div class="inner-2">
<div class="star"></div><div class="star"></div><div class="star"></div><div class="star"></div><div class="star"></div>
</div>
</div>
</div>
I want to create dashboard with lots of live icons. Live icons means icons content will change dynamically.
For example:- Let say i have an icon of a coffee cup, based upon number of coffee sold the coffee level in cup goes up.
I tried solving it using SVG & CSS. Below is the live code-sandbox DEMO example. (same code I am posting below)
https://codesandbox.io/s/fill-coffee-to-svg-1sfb0
what exactly I am doing is on top of SVG component i using div node and applying css on the div tag.
Issue is that, It is very difficult to manage path/points dynamically in SVG, also for different screen version it will be difficult.
Can anyone suggest any better approach for this.
import ReactDOM from "react-dom";
import React, { Component } from "react";
class Todo extends Component {
state = { height: 4 };
setHeight = (e, fillType) => {
e.preventDefault();
console.log(this.state.height);
if (this.state.height < 100) {
if (fillType === "fill") {
this.setState({
height: this.state.height + 2
});
}
}
if (this.state.height >= 2) {
if (fillType === "drink") {
this.setState({
height: this.state.height - 2
});
}
}
};
render() {
return (
<div>
<svg width="255" height="224" xmlns="http://www.w3.org/2000/svg">
<g>
<rect
fill="#fff"
id="canvas_background"
height="226"
width="257"
y="-1"
x="-1"
/>
<g
display="none"
overflow="visible"
y="0"
x="0"
height="100%"
width="100%"
id="canvasGrid"
>
<rect
fill="url(#gridpattern)"
stroke-width="0"
y="0"
x="0"
height="100%"
width="100%"
/>
</g>
</g>
<g>
<title>Layer 1</title>
<path
stroke="#000"
id="svg_1"
d="m78.82963,176.75921l97.93778,0c14.11708,-0.03733 23.74788,-17.00704 23.70086,-34.46505l0,-11.73873c27.94999,-0.03136 48.22814,-30.02253 48.21769,-64.99381c0.01045,-35.59398 -19.86965,-64.83701 -43.00946,-64.81162l-150.95938,0l0,141.54714c0.02194,19.22158 11.60543,34.42772 24.1125,34.46207zm121.63551,-149.38391l0,0l5.20823,0c19.14875,-0.04331 25.29102,25.83983 25.19908,38.38045c0.01881,20.24897 -10.47393,39.66916 -30.40731,37.78463l0,-76.16508zm-199.71514,158.00316c0.01776,26.16387 13.9729,38.29683 25.20535,38.37149l202.59351,0c13.39827,-0.07466 25.14161,-15.13147 25.20117,-38.37149l-253.00002,0z"
stroke-width="1.5"
fill="#fff"
/>
</g>
</svg>
<div
style={{
position: "absolute",
left: "63px",
top: "9px",
height: "175px",
width: "145px",
borderBottomLeftRadius: "25px",
borderBottomRightRadius: "25px",
overflow: "auto"
}}
>
<div
style={{
height: this.state.height + "%",
width: "100%",
position: "absolute",
bottom: "0",
zIndex: 1000,
background: "green",
transition: "all .4s"
}}
/>
</div>
<button onClick={e => this.setHeight(e, "fill")}>
fill more cofee +
</button>
<button onClick={e => this.setHeight(e, "drink")}>drink cofee -</button>
</div>
);
}
}
ReactDOM.render(<Todo />, document.getElementById("root"));
Have you tried using the react-spring library?
In the basics section of react-spring documentation (can be found here - https://www.react-spring.io/docs/hooks/basics) this code snippet is given:
const props = useSpring({ x: 100, from: { x: 0 } })
return (
<animated.svg strokeDashoffset={props.x}>
<path d="..." />
</animated.svg>
)
Using your example of your coffee mug, if you would render your mug separate to the coffee filling the mug, with the coffee stroke being upwards, then you could use this technique to animate the coffee height.
Edit:
As you are using a class component you will want to use the render props API for this - https://www.react-spring.io/docs/props/spring
<Spring
from={{ x: 100 }}
to={{ x: 0 }}>
{props => (
<svg strokeDashoffset={props.x}>
<path d="..." />
</svg>
)}
</Spring>
For a game I'm working on,
I would like to be able to draw a SVG rectangle; using a percentage value (50% would draw half the rectangle stroke).
I need to do this in Javascript since I'll update the value quite often.
<svg id="rectangle-timer" style="width:100%;height:100%;">
<rect width="100%" height="100%"/>
</svg>
I saw quite nice JS libraries like drawSVG or Vivus, but it seems that they work with paths, not with basic shapes like rectangles.
Can anyone help ?
Thanks.
The reason most libraries will use path elements is because of their inheritance from the SVGGeometryElement prototype, which gives you handy functions for computing the path length. So if we swap out this rectangle for a path like this:
<path d="M 0 0 L 1 0 L 1 1 L 0 1 z" />
We get exactly the same output, but its much more controllable. After that, we can just adjust the strokeDasharray value in the style to extend and remove some stroke. For this property we just need two values: initial dash size and initial empty space. So when our progress is 0, we want the first value to be 0 and the second to be the path length , and as we approach 1 we want the second value to 0 and the first one to increase to the path length.
function update( amount ){
const total = rect.getTotalLength();
const filled = total * amount;
const none = total - filled;
rect.style.strokeDasharray = `${filled} ${none}`;
}
const rect = document.getElementById( 'rectangle' );
const input = document.getElementById( 'input' );
input.addEventListener( 'mousemove', event => update( input.value ));
update( input.value );
<svg width="200px" height="200px" viewBox="0 0 200 200">
<path d="M 20 20 L 180 20 L 180 180 L 20 180 z" id="rectangle" fill="none" stroke="black" stroke-width="10" />
</svg>
<input id="input" type="range" min="0" max="1" step=".01" />
If you insist on using a rect, you could get a rectangle's path length by taking its width and height twice, which would look something like this:
function update( amount ){
const total = rect.width.baseVal.value * 2 + rect.height.baseVal.value * 2;
const filled = total * amount;
const none = total - filled;
rect.style.strokeDasharray = `${filled} ${none}`;
}
const rect = document.getElementById( 'rectangle' );
const input = document.getElementById( 'input' );
input.addEventListener( 'mousemove', event => update( input.value ));
update( input.value );
<svg width="200px" height="200px" viewBox="0 0 200 200">
<rect x="20" y="20" width="160" height="160" id="rectangle" fill="none" stroke="black" stroke-width="10" />
</svg>
<input id="input" type="range" min="0" max="1" step=".01" />
In the long run, however, this would mean less versatility, so I would suggest switching to path.
This is my solution: The SVG has preserveAspectRatio ="none" style="width:100%;height:100vh;" The total length of the path is 2*window.innerWidth + 2*window.innerHeight; Both stroke-dasharray and stroke-dashoffset are igual to the total length of the path.
I'm using an input type="range" to animate the stroke-dashoffset.
In order to preserve the stroke width and avoid stretching I'm using vector-effect="non-scaling-stroke"
I hope this is what you need.
function timer(){
let totalLength = 2*window.innerWidth + 2*window.innerHeight;
thePath.setAttributeNS(null, "style", `stroke-dashoffset:${totalLength * (1-range.value)}`)
}
timer()
range.addEventListener("input",timer);
setTimeout(function() {
timer()
addEventListener('resize', timer, false);
}, 15);
*{margin:0; padding:0;}
#thePath {
stroke-dasharray: calc(2 * 100vw + 2* 100vh);
stroke-dashoffset: calc(2 * 100vw + 2* 100vh);
}
#rectangle-timer{background:#dfdfdf}
[type="range"] {
position: absolute;
display: block;
width: 200px;
height: 20px;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
<svg id="rectangle-timer" viewBox="0 0 100 100" preserveAspectRatio ="none" style="width:100%;height:100vh;">
<path id="thePath" d="M0,0L100,0 100,100 0,100 0,0" fill="none" stroke="skyBlue" stroke-width="25" vector-effect="non-scaling-stroke" />
</svg>
<input type="range" id="range" value=".5" min="0" max="1" step=".01" />
Using Inkscape I created an svg file from png, then I tried to use its path's d (which was generated by Inkscape) in react-native-svg, but I failed. This is my code, but it renders only rectanagle with given fill color:
import React from 'react';
import styled from 'styled-components/native';
import { withTheme } from 'styled-components';
import Svg, { Path } from 'react-native-svg';
const StyledPart = styled.View`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.5;
`;
const StyledWaveBackground = styled.View`
width: 100%;
height: 100%;
position: relative;
`;
const Part = ({ width, height, fill, d }) => (
<StyledPart>
<Svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
<Path d={d} fill={fill} />
</Svg>
</StyledPart>
);
const WaveBackground = ({ width, height, theme }) => (
<StyledWaveBackground>
<Part
width={width}
height={height}
fill={theme.color.primary}
d="M 203.75,239.89934 C 142.14982,233.15571 74.42389,213.31632 19.88109,186.03745 L 0,176.09419 0,88.047087 0,0 256.25,0 512.5,0 l 0,87.952377 0,87.952383 -8.212,0.84135 c -19.97561,2.04655 -50.95386,8.64648 -74.52537,15.87764 -8.7243,2.6764 -30.4419,10.7209 -48.26133,17.87666 -49.04169,19.6937 -70.93005,25.94725 -103.01454,29.43144 -13.91836,1.51146 -60.81961,1.49106 -74.73676,-0.0325 z"
/>
<Part
width={width}
height={height}
fill={theme.color.primary}
d="M 120,254.17154 C 81.92867,250.44385 47.75997,241.17995 15.9375,225.95786 L 0,218.33426 0,109.16713 0,0 256.875,0 513.75,0 l 0,106.73949 0,106.73949 -2.82013,0.70781 c -1.55107,0.38928 -11.53545,1.66099 -22.1875,2.82599 -28.98642,3.17021 -64.58588,2.85335 -96.24237,-0.85663 -21.29589,-2.49576 -31.64353,-3.00549 -61.25,-3.01714 -32.18921,-0.0126 -36.98349,0.26131 -49.71091,2.84071 -14.16663,2.87109 -33.00602,9.07774 -66.53909,21.92134 -23.25836,8.90826 -36.6669,12.75144 -52.89669,15.16133 -11.77822,1.7489 -30.52554,2.24276 -42.10331,1.10915 z"
/>
</StyledWaveBackground>
);
export default withTheme(WaveBackground);
This is what it renders as a result (just colored recatngle)
current render result
But it should be like this (waved background)
correct render result
PS: I'm testing on real device(not emulator) Meizu M3E, if it is important
the most important part - the values for width and height you use and the resulting viewBox - are missing. This looks ok:
<svg width="200" height="100" viewBox="0 0 600 300">
<path fill="green"
d="M 203.75,239.89934 C 142.14982,233.15571 74.42389,213.31632 19.88109,186.03745 L 0,176.09419 0,88.047087 0,0 256.25,0 512.5,0 l 0,87.952377 0,87.952383 -8.212,0.84135 c -19.97561,2.04655 -50.95386,8.64648 -74.52537,15.87764 -8.7243,2.6764 -30.4419,10.7209 -48.26133,17.87666 -49.04169,19.6937 -70.93005,25.94725 -103.01454,29.43144 -13.91836,1.51146 -60.81961,1.49106 -74.73676,-0.0325 z"
/>
</svg>