Closed SnooHD closed 6 years ago
@SnooHD interesting use-case!
Unfortunately the input
need to be a String
or a Buffer
. A solution could be convert the Object intro <svg>
again, pass through outline-stroke
and the again svgson
.
If you want to share more info/code I am super happy to collaborate to find a cool solution that fits for your specific case.
I am working on a upload tool for svg shapes, these shapes afterwards will be free transformed by a user (selecting, dragging, rotate, scale, change colors etc.)
So if a shape is uploaded without a fill
, i want to change the stroke
to an outline so that the shape can be handled as any other shape. (its mainly to avoid confusion for the user, especially because for other shapes its NOT possible to set colors to 'none')
So i parse the file with svgson, loop through the objects and change certain attributes so they can work with my tool. The moment fill="none"
and stroke
is set, i want to convert it to an outline, and update the d
attribute in my svgson object.
each shape is an <svg>…</svg>
file?
It are not single shapes, the svg files can contain many paths, and all of these paths need to be checked individually, so at the end, its the path data from svgson that i end up with.
I just ran into this package: https://github.com/danmarshall/svg-path-outline
It seems to do the job perfectly for my use case!
@SnooHD came in mind a possible and probably elegant solution.
Let me know if you solved, otherwise will elaborate here or in a gist.
Hello, i managed to solve it! Thanks for thinking along ;)
awesome!
@SnooHD I am curious about two thing regarding the lib svg-path-outline
, in case you could reply based on the use you are doing:
path
data at the same position of the original, without offset?svg
s?I am thinking in start playing around with this library to implement some stuff here.
Thanks in advance
Hi @elrumordelaluz, sorry for my late response.
svg-path-outline
makes it possible to create an outer
or inner
outline and takes in account the different joints as well (but i guess you can simply read that on the package page anyways). It keeps the current offset, so the coordinates don't change :).
I have not tested the performance, for my use case it doesn't matter that much. But i don't notice any difference with or without this package.
Thank you @SnooHD Yes I wen a little deep in the lib and basically is bridge into maker.js library.
Since you are using it just, with
Is there a way to create the path data at the same position of the original, without offset? I wanted to know for example, if you could obtain the
rect
I am showing below, same appearance but filled instead of usingstroke
:
<svg viewbox="0 0 12 12">
<rect width=10 height=10 x=1 y=1 fill=none stroke=blue stroke-width=2 />
</svg>
Hmm im not sure if I am completely understanding what you want to achieve just yet.
Is this what you would want to end up with? <path d="M1,1 L11,1 L11,11 L1,11 z" fill="blue" />
The stroke always sets an inner AND outer offset, but x
& y
are not altered in any way.
So you could convert the rect
to a path
and position it on x
& y
. Then you could simply remove the stroke all together, and change it to a fill, right?
If you want to keep the outer stroke's position, you could just take half of the stroke-width
and use it to recalculate x
& y
. (for example: x =- stroke-width / 2).
In case you are wondering how you might position the shape (Though I think you know..?)
I first parse the path with parse-svg-path, then i normalized the path to bezier curves
with curvify-svg-path.
This way its a lot easier to manipulate the paths, because well, it's only using curves.
Now something like this would do the job:
export const movePath = (d, x, y) => {
for(let i=0;i<d.length;i++){
const points = d[i];
for(let j=0;j<points.length; j++){
//first value is always the type
if(j > 0){
if(j % 2 == 0){
//set all even values (y)
points[j] += y;
}else{
//set all uneven values (x)
points[j] += x;
}
}
}
}
return d;
}
Hope this helps. Snoo
Yes, the path
ed version of this rect
results in what you shows, but what I am looking for is to convert that d
into something more complex that represents that stroke
but without stroke
.
Sounds a bit confusing, but essentially this is what outline-stroke
solves in some way, the same result as if you have the square showed above opened in Illustrator and applied Outline stroke.
The result should be something like:
<svg viewBox="0 0 12 12">
<path fill="#f00" d="M12,12H0V0h12V12z M2,10h8V2H2V10z"/>
</svg>
See the last square here
Let me know if is clearer the point, and in case you were talking about the same I missed something.
Thanks for the codepen, it cleared things up a bit.
Typically speaking, this is exactly what i am actually doing as well haha.
So the difficult part would be making sure that joints
are taken in account.. this is the whole reason i decided to use svg-path-outline
.
But i guess, if i can ignore the joints
, you could simply take the rect, and change it to a path.
Then you scale the path * (stroke-width / 2)
. So now you have the outer stroke.
Then scale the original path again, but this time by / (stroke-width / 2)
.
So now we have the outer and inner paths, so by pushing them together in the same d
attribute, we can accomplish the result.
Dont forget to have a look at the fill-rule attribute :)
Is it possible to use a svgson path object instead of a string? I am looping through a object created with svgson, and I need to outline strokes when i run into them.
Thanks in advance!