Whats the easiest and in terms of DOM elements most lightweight way to clip an SVGElement to itself in addition to an already existing clippath?
<path d="M 0 0 L 500 0 L 500 500 L 0 500 Z" clip-path="url(#existing-clippath)"/>
My current solution looks like this but seems quite cumbersome
<clippath id="element-itself">
<path d="M 0 0 L 500 0 L 500 500 L 0 500 Z"></path>
</clippath>
<g clip-path="url(#element-itself)">
<path d="M 0 0 L 500 0 L 500 500 L 0 500 Z" clip-path="url(#existing-clippath)"/>
</g>
Edit
Using a <use> element seems like a good choice, as pointed out by Robert Longson:
<clippath id="element-itself">
<use xlink:href="#element">
</clippath>
<g clip-path="url(#element-itself)">
<path id="element" d="M 0 0 L 500 0 L 500 500 L 0 500 Z"
clip-path="url(#existing-clippath)"/>
</g>
Is there any easier/shorter way to achieve this?
Related
I want to rotate the pointer around its axis of the following SVG component.
How could I achieve that. I have tried it with following method but it doesn't rotate around it.
<g id="Group 1" transform = "translate(100, 100) rotate(45 0 0)">
<path id="Point" fill-rule="evenodd" clip-rule="evenodd" d="M302.248 291.371L230.862 209.521L212.309 230.492L302.248 291.371Z" fill="#72A1E7"/>
</g>
It is easier to:
rotate something if it can be centered around 0,0.
calculate the angle of the needle if you know the angle at the starting point.
Therefor the you could draw the needle like this, with the middle of the short line at 0,0 (yes, it is off-canvas) and then pointing at 6 o'clock:
svg {
background-color: silver;
}
<svg width="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<g id="Group 1">
<path id="Point" fill-rule="evenodd" clip-rule="evenodd"
d="M -10 0 L 10 0 L 0 75 Z" fill="#72A1E7"/>
</g>
</svg>
Now the needle can be moved to the center (or where ever) of the image:
svg {
background-color: silver;
}
<svg width="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<g id="Group 1" transform="translate(100 100)">
<path id="Point" fill-rule="evenodd" clip-rule="evenodd"
d="M -10 0 L 10 0 L 0 75 Z" fill="#72A1E7"/>
</g>
</svg>
The rotation can be done in different ways, but here I rotate the needle/path <path> itself to the imagined zero point of the meter and then use the group element <g> to give the meter a "value". So, here the calculation is that the meter takes up 300 deg, the zero value is at 30 deg (from 6 o'clock) and the max value is then at 330 deg. Here the value is 1/3 = 100 deg.
svg {
background-color: silver;
}
<svg width="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<circle transform="rotate(120 100 100)" cx="100" cy="100" r="85"
stroke="blue" stroke-width="5" stroke-dasharray="300 360" pathLength="360"
fill="none" />
<g id="Group 1" transform="translate(100 100) rotate(100)">
<path id="Point" transform="rotate(30)" fill-rule="evenodd"
clip-rule="evenodd" d="M -10 0 L 10 0 L 0 75 Z" fill="#72A1E7"/>
</g>
</svg>
How can I draw half of ellipse in SVG? What I'm trying to do
<path d="M 198, 160 a 50,20 1 1,0 1,0" fill="pink" style="fill:pink;stroke:black;stroke-width:1;"/>
You already found the right command for your path; the elliptical arc curve.
In these examples I created half-ellipses with the same dimensions. You can see the two numbers after the A are all 10 and 2. 10 is the x radius and 2 the y radius. The two numbers after M are all stating points and the two numbers just before Z are the end points. The three numbers in between (0 0 0 and 0 0 1) are different flags. The only one I use here is the sweep-flag that indicates clockwise or anticlockwise.
A usefull tool that I use a lot for creating paths is this: SvgPathEditor.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 8">
<path transform="translate(0 0)" fill="blue" d="M 10 0 A 10 2 0 0 0 10 4 Z"/>
<path transform="translate(10 0)" fill="pink" d="M 0 0 A 10 2 0 0 1 0 4 Z"/>
<path transform="translate(0 4)" fill="orange" d="M 0 2 A 10 2 0 0 1 20 2 Z"/>
<path transform="translate(0 6)" fill="lime" d="M 0 0 A 10 2 0 0 0 20 0 Z"/>
</svg>
The following code assigns the colour green to all the three lines of the SVG path.
<svg height="210" width="400">
<path d="M 150 0
L 75 200
L 225 200
L 150 0"
fill ="none" stroke="green" stroke-width="3" />
</svg>
Can I know how I can assign separate styles to each line?
In this case the solution would be using 3 different lines:
<svg height="210" width="400">
<g stroke-linecap="round" stroke-width="3" >
<path d="M 150 0
L 75 200" stroke="green"/>
<path d="M75 200
L 225 200" stroke="gold"/>
<path d="M225 200
L 150 0" stroke="red"/>
</g>
</svg>
It is not possible to have multiple styles within a single SVG path.
Can someone please tell me, why the left arrow head in the following file shows correctly in the generated PNG, but not in the browser?
https://commons.wikimedia.org/wiki/File:SVG_double_arrow_with_marker-start_and_marker-end.svg
In Firefox it is just not there, and in Chrome I see it pointing to the bottom right instead of left.
These are the two markers:
<marker id="arrowend" viewBox="0 0 13 10" refX="2" refY="5" markerWidth="3.5" markerHeight="3.5" orient="auto">
<path d="M 0 0 C 0 0, 3 5, 0 10 L 0 10 L 13 5" fill="red"/>
</marker>
<marker id="arrowstart" viewBox="0 0 -13 -10" refX="-2" refY="-5" markerWidth="-3.5" markerHeight="-3.5" orient="auto">
<path d="M 0 0 C 0 0, -3 -5, 0 -10 L 0 -10 L -13 -5" fill="red"/>
</marker>
My solution based on the hint below:
<marker id="arrowstart" viewBox="0 0 13 10" refX="11" refY="5" markerWidth="3.5" markerHeight="3.5" orient="auto">
<path d="M 13 0 C 13 0, 10 5, 13 10 L 13 10 L 0 5" fill="red"/>
</marker>
So I changed the actual path. All my attempts to just mirror it failed, so for me this was the best solution.
This is where I put it in action, BTW: https://commons.wikimedia.org/wiki/Category:Full_octahedral_group;_single_elements;_signed_perm_mat,_perm_mat_and_cube
A viewBox with negative width and height is invalid. The contents of invalid viewBoxes do not render.
If Chrome renders arrowstart in any way, that's a Chrome bug. Whatever png generator you're using is clearly also buggy.
Here's one way to get the arrows on both ends, at least on browsers that support orient="auto-start-reverse"
<svg width="500" height="300" viewBox="0 0 200 50">
<defs>
<marker id="arrow" viewBox="0 0 13 10" refX="2" refY="5" markerWidth="3.5" markerHeight="3.5" orient="auto-start-reverse">
<path d="M 0 0 C 0 0, 3 5, 0 10 L 0 10 L 13 5" fill="red"/>
</marker>
</defs>
<line x1="25" y1="25" x2="175" y2="25" stroke="red" stroke-width="5" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
</svg>
Is there a way to generate new, stand alone path out of a path with multiple masks applied to it?
I have a <path> with multiple masks applied via wrapping <g> parents, like so:
Here is the final graphic without masks visible:
DEMO on CodePen
Source code:
<svg>
<defs>
<mask id="primMask">
<path d="M 0 0 L 300 0 300 300 0 300 Z
M 100 0 A 50,50 0 0,0 100,100 A 50,50 0 0,0 100,0" fill-rule="evenodd" fill="white" />
</mask>
<mask id="anotherMask">
<path d="M 0 0 L 300 0 300 300 0 300 Z
M 30 0 A 10,10 0 0,0 30,60 A 10,10 0 0,0 30,0" fill-rule="evenodd" fill="white" />
</mask>
</defs>
<!-- These are just the circles with same paths
as masks to help visualize the masks shape/position -->
<g>
<path d="M 100 0 A 50,50 0 0,0 100,100 A 50,50 0 0,0 100,0" class="maskCopy" />
<path d="M 30 0 A 10,10 0 0,0 30,60 A 10,10 0 0,0 30,0" class="maskCopy" />
</g>
<!-- This is the main shape with masks -->
<g mask="url(#primMask)">
<g mask="url(#anotherMask)">
<path d="M 10 10 L 90 10 70 90 10 90 Z" class="myShape" />
</g>
</g>
</svg>
Here is why I'm asking: I need to apply different styles to myShape on mouse hovering it's visible part only. Currently, as you can test in DEMO, styles are changed when mouse hovers the original path, masks are not taken into count.
Besides, I think having stand-alone path provides more flexibility in more complex requirements and also is more performant when more masks are being added.