Closed vladyslavNiemtsev closed 2 years ago
With plain SVG it could be implemented with following code:
<Defs> <LinearGradient id={
gradient`}
x1="0"
x2="0"
y1="0"
y2="100%"
`
When I tried to implement something similar
I get:
I suppose that for me I will need to create slightly different shape to give it just the same shape of my figure that I want to paint. (the shape under my path line)
I suppose that for me I will need to create slightly different shape to give it just the same shape of my figure that I want to paint. (the shape under my path line)
I can send a solution in an hour, or meanwhile you can check the generateGraph function in the fork I created
The idea is that for filling the path with gradient it should be closed and the current path isn't
It will be so great, thanks! @DDushkin
In D3 it solves with areas: https://github.com/d3/d3-shape/blob/v3.1.0/README.md#areas
So, I could just walk throw my data array and specify the same curve function as it was for my Path creating, the example is here:
So, in this case the D3 will understand the algorithm for curve function and could understand the correct area for this Path.
But in case of Skia Path creation, I don't understand yet how I could do this.
It will be very helpful if you'll provide your solution!
So Skia creates SVG path with commands the same way as you would create an SVG path manually with flags like M 0 100 L 100,100 z
and etc.
So here looking to your screenshot imagine the first and last point of your path and think how to make that path looped.
//./src/CreateGraphPath.ts
const path = Skia.Path.Make(); // -> initialize SVG path
for (let i = 0; i < points.length; i++) {
const point = points[i]!;
// first point needs to start the path
if (i === 0) path.moveTo(point.x, point.y); //-> start point
const prev = points[i - 1];
const prevPrev = points[i - 2];
if (prev == null) continue;
const p0 = prevPrev ?? prev;
const p1 = prev;
const cp1x = (2 * p0.x + p1.x) / 3;
const cp1y = (2 * p0.y + p1.y) / 3;
const cp2x = (p0.x + 2 * p1.x) / 3;
const cp2y = (p0.y + 2 * p1.y) / 3;
const cp3x = (p0.x + 4 * p1.x + point.x) / 6;
const cp3y = (p0.y + 4 * p1.y + point.y) / 6;
path.cubicTo(cp1x, cp1y, cp2x, cp2y, cp3x, cp3y);
if (i === points.length - 1) {
path.cubicTo(point.x, point.y, point.x, point.y, 4 * point.x, point.y); //-> end point
}
}
/*
At this point, we generated LineGraph,
but to build the Gradient we need to connect the first and last points
*/
path.lineTo(width + graphPadding, height + graphPadding); //-> go to right bottom corner
path.lineTo(0 + graphPadding, height + graphPadding); //-> go to left bottom corner
/*
Now we kinda have the correct shape of our gradient
*/
return path;
Then in the render method, we add another Path with fill near our current Path with stroke
<Path
path={path}
strokeWidth={lineThickness}
color={color}
style="stroke"
strokeJoin="round"
strokeCap="round"
/>
{gradientColors && ( //-> New one
<Path path={path}>
<LinearGradient
start={vec(0, 0)}
end={vec(0, height)}
colors={gradientColors} //as Color[]
/>
</Path>
)}
This is how I solved the issue, maybe @mrousavy has a better solution?
@DDushkin Yeah, got it, thanks for your solution - it works for me!
Ah yea the solution isn't that difficult, you just need to reverse the Path then it works 😄
Hey @mrousavy, what do you mean by reverse the Path?
This was implemented in #41 and is available now in versions above 0.3.0
Hi! I tried to implement LinearGradient to fill out all area under Path line.
Wanted to get something like this:
Do you know how it could be implemented with
react-native-skia
LinearGradient component?I can't get the needed behaviour.. :(