SVG to top,mixing layers - svg

How i can make my object to be always on the top of the other objects? Cause when they are on the same position they are mixing
<g transform="translate(0,0)" id="line">
<path
fill="#F7931E"
stroke="white"
stroke-width="5"
style="fill:#fff;fill-opacity:1;"
d="M0,0 H3v0h50z" />
</g>
i have a lot layers like this. nd i want to have one with other color on top. But they are mixing. How i can move to top? Id ordering is not working for me
And is it possible to position a div element with the Svg object,or write around svg object?
InsertBefore is destroying the position

Related

Styling SVG elements with stroke and globally-positioned pattern

Goal
I am trying to replicate this effect algorithmically:
This is for a project I am working on where I need to make stylised visualisations of different kinds of pizza. The image shows a Margherita (tomato base, mozzarella and basil on top).
The rules I need to adhere to:
each ‘layer’ consists of uniformly positioned objects with a stroke and filled with a pattern (that shares coordinates)
the layers need to cover lower layers
Means
To achieve the uniform distribution, I use Poisson-Disc sampling.
I chose SVG because I need the result to be visible in the browser and generate this server-side.
For efficiency and simplicity – as the viewing size will be smaller – I decided to reference one object with <use> elements and vary it only with rotations, as opposed to the sample.
Attempts
Every approach I tried reached a dead end:
Creating a <clipPath> filled with <use> elements for clipping the background.
This does not allow me to add a stroke around the clipped area, which I need. A workaround would be to use a feMorphology filter, but that seems like it’s going to be needlessly costly on the client. A second workaround seemed to be:
Grouping the elements and using that group twice: once in a <clipPath> for clipping the pattern background, once directly on the canvas with an added stroke.
This does not work as <g> elements are unsupported in web browsers due to completely arbitrary reasons (it does work in Inkscape, however, which I used for the proof-of-concept). A workaround would be to use two copies of all the <use> elements, but that would essentially double the file size.
Grouping the elements and applying a fill with SVG patterns.
This does not work as since we create the distribution using <use> elements, the pattern looks identical in every instance. Moreover, I cannot rotate the objects, as the pattern would get rotated too. A workaround would be not to use <use>, but that would create the same problem as in point 2.
Those approaches won't work because patterns are affected by any transforms applied to the same shape.
In the solution below, we create a whole layer of an ingredient (id="basil-layer"). Then use that layer to first draw the ingredient outlines (strokes). Then afterwards we use a mask, created from that same layer, to draw hatching on top of the outlines.
You'll need to duplicate this process for each of the ingredients.
More documentation of what's happening inside the code.
<svg width="600" height="400">
<defs>
<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" viewBox="0 0 4 4" width="16" height="16">
<rect fill="black" width="4" height="4"/>
<path d="M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2"
style="stroke:green; stroke-width:0.5" />
</pattern>
<!-- Definition for a leaf of basil -->
<ellipse id="basil" cx="0" cy="0" rx="60" ry="30"/>
<!-- A layer of N pieces of basil -->
<g id="basil-layer">
<use xlink:href="#basil" transform="translate(300,200)"/>
<use xlink:href="#basil" transform="translate(400,150) rotate(45)"/>
<use xlink:href="#basil" transform="translate(450,200) rotate(110)"/>
</g>
<!-- A mask that consists of all the pieces of basil -->
<!-- The fill is white to keep the *insides* of the basil shape.
And we stroke with black so that this mask doesn't hide any of the
green stroke outline of the leaf, when use this mask to lay down
the hatch pattern on top of the drawn basil leaves. -->
<mask id="basil-layer-mask">
<use xlink:href="#basil-layer" fill="white" stroke="black" stroke-width="2"/>
</mask>
</defs>
<!-- Fill SVG with a black background -->
<rect width="100%" height="100%" fill="black"/>
<!-- Draw all the basil pieces with a black fill and a green outline -->
<use xlink:href="#basil-layer" fill="black" stroke="green" stroke-width="2"/>
<!-- Finally draw the basil layer hatching.
This is a whole-SVG sized rectangle of hatching masked by the basil layer mask -->
<rect width="100%" height="100%" fill="url(#diagonalHatch)" mask="url(#basil-layer-mask)"/>
</svg>

SVG viewBox scales some elements differently than others

The client asked to scale the drawing down so I added width/height and viewBox to the SVG element. The problem is that some elements are scaled differently than others. The structure of the svg is like this:
<svg width="100%" height="100%" viewBox="0 50 700 200">
<defs>...</defs>
<g id="group-ab">
Here are the boxes (drawn with polyline) that are scaled correctly, both in their own group (group-a, group-b)
</g>
<g id="group-a-id">
<text>A</text>
<circle id="group-a-id-bg-circle"></circle>
</g>
<g id="group-B-id">
<text>B</text>
<circle id="group-b-id-bg-circle"></circle>
</g>
<path id="group-a-pattern" d="..."></path>
<path id="group-b-pattern" d="..."></path>
</svg>
The path is the pattern for the pieces. It seems that everything that isn't under the group "group-ab" isn't scaled correctly, see the image below. Normally (when not using viewBox) the pattern fills up the boxes and the A/B are centered with the boxes (same translates are done to them).
Why is this happening? One would think that it doesn't matter if elements are within groups or not if svg is scaled.

Manipulating individual tiles in an SVG pattern

I'm trying to create an interactive grid for a web game (HTML, JS, etc.), in which every cell should change it's fill on hover/click. I need both a regular square grid, and a triangular grid. I want it to be vector based so that it will scale nicely to fit different screen sizes. I thought the easiest way would be to create a pattern and fill it on a rectangle. This is the code I have so far:
<pattern id="baseTile" width="10" height="10" patternUnits="userSpaceOnUse">
<path id="tile" d="M 0,0 L 0,10 10,10 10,0 Z" fill="none" stroke="gray" stroke-width="1"/>
</pattern>
For the square, and this for the triangular grid:
<pattern id="baseTile" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 5,0 L 10,2.5 10,7.5 5,10 0,7.5 0,2.5 Z" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 5,0 L 5,10" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 0,2.5 L 10,7.5" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 0,7.5 L 10,2.5" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 0,0 L 0,2.5 M 0,7.5 L 0,10" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 10,0 L 10,2.5 M 10,7.5 L 10,10" fill="none" stroke="gray" stroke-width=".1" />
</pattern>
They produce the grids I need, but I don't know how to target each cell individually. I'm guessing since I've found no information on this, it's just not possible, and some other solution other than should be used. Any ideas?
Edit:
I want to be able to cycle through different fills on mouse click. For the square grid, I'm using the code I found here: http://bl.ocks.org/bunkat/2605010 but for the triangular lattice, I have absolutely no idea where to begin. That's why I thought of .
PS: I should probably add I have no programming experience, I'm trying to make a nonogram game to teach myself some Javascript.
Patterns are purely decorative. Targetting a single tile within a pattern would be like targetting a single colour within a gradient. Better not to think about them as distinct "tiles", and instead think of it as a sheet of repeating wallpaper.
So what to do? Well, you are going to need a distinct element for each piece that you want to be able to manipulate. But since they are mostly the same, you'll want to use <use> elements to repeat the graphics. You'll need to do a bit of math to figure out how to position the triangles just right, but no worse than what you had to do to figure out that pattern. It will of course be easiest to create the elements with a loop in your JS script, although you could hard code the original elements in a <defs> section.
Moreover, you don't specify what you want to do with the individual cells. If you are going to be changing their appearance, it might help to remember that you can set styles on the <use> element and these will be inherited by the re-used graphics. So if you don't set fill/stroke directly, you can change them by styling the <use>, instead of having a separate, differently coloured template to swap in.

Better way to position svg:polygon

The SVG elements <line>, <circle>, <rect>, <text> and , <image> allow for positioning by x and y based off of the view port. Furthermore they can also be relatively positioned. Is there any way to accomplish this for <polygon> than to wrap it in an <svg>? The closest substitute for <polygon>, <path>, also has this... issue.
Based on the excellent comment by #Michael Mullany I was able to find a solution to the issue. By putting the polygon or path in side a <defs> tag it can be used later on in a <use> tag. The <use> tag allows for setting of x and y attributes that function the same as the attributes of other simple shapes like <line>, <circle>, <rect>, <text>
http://jsbin.com/iqEkAsE/2
<svg width="100%" height="100%">
<defs >
<path id="Triangle"
d="M 1 1 L 200 1 L 100 200 z"
fill="orange"
stroke="black"
stroke-width="3" />
</defs>
<use x="33%" y="33%" xlink:href="#Triangle"/>
<use transform="scale(-1)" x="-66%" y="-66%" xlink:href="#Triangle"/>
</svg>
It would be nice to be able to scale the shape dynamically by setting the width and height property of the <use> to a percent but it can still be scaled with a transform.
Use transformations (translation, rotation, scale), that is the correct way to do it.
The other shapes allow you to use a point defined by x,y coordinates because that's just a part of the shape definition (i.e. how do you define a circle, you need the center point and the radius).
In theory you could position an element using its bounding box, however the bounding box is not "settable" (there is no setBBox method), there is only getBBox()

SVG dilate/erode filter vs. Illustrator Offset Path

Below is a screen capture of SVG image which is rendered on Chrome 22.0.1229.79 Mac. The original svg is on jsfiddle:
http://jsfiddle.net/LGBk5/
The left image is made using SVG:s dilate and erode filters. The right one is made using Illustrator's Offset Path effect.
The left one has problems: the border at the bottom is distorted and curves are not as smooth. Meanwhile the thick black border is the same in both.
Has my SVG some parameter wrong or are the dilate and erode filters so seemingly buggy?
EDIT: The purpose is to make paths thinner or thicker in SVG, but according to this example, the erode/dilate is not stable enough to rely.
Filter effects are done on pixel data (the rasterized path), while the path offset operation in Illustrator (similar in Inkscape) is done using the original path data (or vector data if you wish).
The former is like using photoshop filters, the latter is creating new paths by using the existing path. They're both stable, but they're not the same operation.
Illustrator's path offset and SVG filters erode/dilate are different operations.
This erode filter is working as designed - there is no bug here. For every pixel in the input image, the filter looks at the maximum RGBA values in a rectangle around it (the radius). In a normal image this tends to generate "rectangular highlights" for want of a better term. And results in weird artifacts when applied to curved draw paths. From the spec:
The dilation (or erosion) kernel is a rectangle with a width of
2*x-radius and a height of 2*y-radius. In dilation, the output pixel
is the individual component-wise maximum of the corresponding R,G,B,A
values in the input image's kernel rectangle. In erosion, the output
pixel is the individual component-wise minimum of the corresponding
R,G,B,A values in the input image's kernel rectangle.
So, imagine that that single pixel at the pointy end of your shape. With a 10 pixel "radius" in your filter (and remember that radius is an incredibly misleading term because it's using a rectangle not a circle!). Let's say it's at 100,100, for arguments sake. When the filter processes values for pixels in the range 90,110 to 110,110, its dilation radius is going to detect that pixel at 100,100 and paint all pixels in that range black. And just like that, your nice pointy end has been dilated into a straight line.
Note that you can achieve most offset path effects using nested strokes (some of which have masks to trim the inside or outside of the path.
For example, here is the OP's path reimplemented this way:
<!-- Left drawing is made using erode and dilate -->
<!-- Right one is made by Illustrator's Offset Path -->
<svg width="612" height="792" viewBox="0 0 612 792" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="curve" d="M21.552,74.438c2.531-28.879,73.668-52.734,102.629-53.971
c32.164-1.373,74.764,23.746,61.766,53.197c-32,72.5-84.236-59.594-109.5-29.5c-23.367,27.833,55.4,142.969,55.4,142.969
S18.109,113.708,21.552,74.438z"/>
<mask id="inner">
<use xlink:href="#curve" fill="white"/>
</mask>
</defs>
<!-- this black outermost line -->
<use x="10" y="10" xlink:href="#curve" style="stroke:black;stroke-width:26;stroke-linejoin:miter;stroke-miterlimit:10"></use>
<!-- thick red outer line -->
<use x="10" y="10" xlink:href="#curve" style="stroke:#f00;stroke-width:24;stroke-linejoin:miter;stroke-miterlimit:10"></use>
<!-- innermost black thin line, with green fill -->
<use x="10" y="10" xlink:href="#curve" style="fill:#1CFF00;stroke:black;stroke-width:32;stroke-linejoin:miter;stroke-miterlimit:10" mask="url(#inner)"></use>
<!-- blue inner stroke -->
<use x="10" y="10" xlink:href="#curve" style="fill:none;stroke:#5555FF;stroke-width:30;stroke-linejoin:miter;stroke-miterlimit:10" mask="url(#inner)"></use>
<!-- lastly, the black line -->
<use x="10" y="10" xlink:href="#curve" style="fill:none;stroke:black;stroke-width:10;stroke-linejoin:miter;stroke-miterlimit:10"></use>
<g transform="translate(210,10)">
<path fill="#FF0000" stroke="#231F20" d="M126.273,201.917c-1.188-0.766-29.407-19.044-57.679-42.532c-41.739-34.676-60.31-60.754-58.441-82.068
c1.575-17.974,18.042-34.105,48.943-47.945c21.673-9.707,48.782-16.997,65.925-17.729c1.023-0.043,2.057-0.065,3.096-0.065
c26.722,0,55.103,13.789,67.484,32.787c7.866,12.07,9.101,25.736,3.476,38.482c-8.697,19.704-20.608,29.697-35.403,29.702
c-0.002,0-0.007,0-0.01,0C144.382,112.551,127.62,95,111.407,78.028c-7.054-7.385-18.575-19.446-23.912-21.338
c-1.086,2.002-6.186,15.821,20.666,67.477c16.226,31.214,35.475,59.438,35.668,59.72l35.977,52.589L126.273,201.917z"/>
<path fill="#5555FF" stroke="#231F20" stroke-width="10" stroke-miterlimit="10" d="M22.939,78.438
c2.531-28.879,73.668-52.734,102.629-53.971c32.164-1.373,74.764,23.746,61.766,53.197c-32,72.5-84.237-59.594-109.5-29.5
c-23.366,27.833,55.401,142.969,55.401,142.969S19.497,117.709,22.939,78.438z"/>
<path fill="#00FF00" stroke="#231F20" d="M79.986,131.678C38.498,95.796,38.41,81.397,38.549,79.807c0.289-3.29,5.843-10.151,19.371-17.933
C57.676,78.899,64.972,101.816,79.986,131.678L79.986,131.678z M163.665,84.044c-7.09,0-22.461-16.091-31.646-25.706
c-5.867-6.143-11.433-11.969-16.966-16.846c4.324-0.776,8.128-1.238,11.184-1.368c0.621-0.027,1.249-0.04,1.88-0.04
c16.911,0,36.471,8.903,43.603,19.846c3.317,5.089,2.508,8.623,1.278,11.408C168.884,80.659,165.163,84.043,163.665,84.044
L163.665,84.044z"/>
</g>
</svg>

Resources