Properly overlapping the end-marker on the path - javascript

Updated picture including (c)
I am using the following code in Javascript to generate an end-marker (a triangular arrow) attached to a line:
edge.marker('end', 10, 10, function (add) {
add.path('M2,2 L2,11 L10,6 L2,2').fill('black');});
The above code generates an arrow that looks like (a) in the attached picture. However, the marker (triangle) extends the line. I would like to generate an arrow as shown in (b) with the pointed end of the marker aligned with the end of the line (and not extend it). Also, it should not look like a triangle as in (a), but an arrow as in (b).
I have tried several variations of the code shown in the description with different values, but they all extend the line, which is not desirable in the image I am generating.
Provided in the description.Picture of actual(a) and desired(b) image

This answer is the result of several comments I've exchanged with the OP. In order to place a marker where you need on a path you may use the refX and refY attributes to define the coordinates for the reference point of the marker.
svg{border:1px solid; width:45%}
path{fill:none; stroke:black; stroke-width:2}
<svg viewBox="0 0 100 50">
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="userSpaceOnUse"
fill="none" stroke="black">
<path d="M2,10 L10,6 L2,2" />
</marker>
<path d="M20,25 H80" marker-end="url(#arrow)" />
</svg>

fill ="none" remove the black color inside the arrow..
add stroke="black"
To prevent lines from changing their thickness, you can also use the
attribute path vector-effect="non-scaling-stroke"

Related

how to create d3 radial with dynamic radios

I created a radial with two tiers of options. I did in a way that isn't really dynamic and isn't really responsive to screen size. I now need it to be both of those things. Here is what it looks like when on the screen size I designed it for.
I created a working demo on sandbox that has the dimensions set how I need to use it on. This is what it looks like.
Here is link WORKING DEMO
any help is appreciated. Also keep in mind the outer tiers can have less or more options. it would be great if the blue toggle button would always align at the bottom of the radial like under the En of Energy Loss
I would consider using an SVG ViewBox in order to maintain consistency. What this basically does is create a consistent scalable SVG, mapping the size and coordinates of its container into a consistent range inside the SVG.
For example:
<div height="400px" width="400px">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="100%" height="100%" stroke="red" fill-opacity="0"/>
<circle r="4" cx="10" cy="10"/>
</svg>
</div>
So it basicalley creates a mapping from the 400x400 dimensions of the div, into the 100x100 of the svg, so the circle positioned at (10, 10) inside the svg will actually be in coordinates (40, 40) of the div

How to create a svg line with a filter

I would like to create lines with the following effect :
The above was created with the following :
<svg id="svg_wrp" width="500" height="500">
<defs>
<filter id="crayon">
<feTurbulence
type="fractalNoise"
baseFrequency="1.001"
numOctaves="10"
result="noise">
</feTurbulence>
<feDisplacementMap
xChannelSelector="R"
yChannelSelector="G"
scale="50"
in="SourceGraphic"
result="newSource">
</feDisplacementMap>
<feGaussianBlur stdDeviation="1.1"/>
</filter>
</defs>
<polyline
points="200,100 100,200"
stroke="#000"
stroke-width="10"
fill="none"
filter=url(#crayon) ></polyline>
</svg>
Above in Fiddle
This method does not work for much of what I want to do.
The effect changes depending on the length and direction of the line.
The only way I can think of doing this is by replacing all the lines with polygons. Then it would be a straight forward use of filters. But then I would have to create a complex polygon with all the calculations for each corner and curve.
So before I do that I would like to know if there is a way to achieve the above with svg polylines or some other method.
Edit: Michael Mullany's answer solved the vertical and horizontal only line issue, but I still have problems with the effect differing on some lines, see below for an example. Notice effect is reduced in top left. Is there a way to have a consistent effect on all lines?
Default filter dimensions don't work on horizontal and vertical lines because they have a zero area bounding box. You need to change your filter units to:
<filter id="crayon" filterUnits="userSpaceOnUse" x="0" y="0" width="500" height="500">
Otherwise this filter is fine.
Update: there are some values for baseFrequency that cause anomalies/moire-like artifacts - apparently 1.001 is one of them for this case. If you tweak that baseFrequency down to 0.98, the problem disappears.

Changing the colour of regions on an SVG circle tiled world map when hovered

I am attempting to make a world map made from an svg comprising many circles. I based this from a codepen I found here: https://codepen.io/mvaneijgen/pen/NRzENO
E.g.
<svg viewBox="0 0 845.2 458">
<circle class="st0" cx="826.1" cy="110.3" r="1.9"/>
<circle class="st0" cx="819.3" cy="110.3" r="1.9"/>
<circle class="st0" cx="819.3" cy="117.1" r="1.9"/>
<circle class="st0" cx="812.6" cy="90" r="1.9"/>
The map is great. I have been dividing it up into coloured continent regions using classes. These change colour when hovered over. All good so far. Most of my functionality is there.
The issue is that you have to be hovering directly on a circle to make the colour change happen. I am using a javascript mouseover event to change the colour.
Is there any way of increasing the area of effect around the circle elements? Maybe putting an invisible square either behind or in front? I am still getting to grips with front-end stuff and any pointers here would be great.
That’s the right idea: transparent rects behind each circle. (Or transparent continent-shaped paths based on geo data, depending on what you’re going for.)
The trick is to use the SVG CSS property pointer-events. Setting it to fill or all should do the trick.

Svg polygon rounding

I am working on an application that is using svg move/rotate/zoom functionalities. I'm programming the back-end in Laravel and the front-end is using html/css/javascript. I've seen on the web that is possible for a polyline to have some sort of cubic-bezier to it.
Now my question is: is it possible for a polygon svg element to have the same cubic-bezier to it as the polyline like in this example?
The structure of the svg looks like is:
<svg>
<g data-type="track">
<polygon class="track" points="2588,851 2537,1157 1796,916 1117,723 0,382 40,80 816,314 1885,638 1887,634"></polygon>
<polygon class="track" points="114,19 73,0 17,497 46,485"></polygon>
</g>
</svg>
Is it possible to give the polygon element a cubic bezier so that it can create a fluid polygon instead of the square no-rounded polygon?
I think some of the responses here have been a little confusing.
(is it) possible for a polygon svg element to have the same cubic-bezier to it as the polyline
The short answer is no. <polygon> (and <polyline>) elements are always rendered as a sequence of straight line segments between the coordinates you provide. There is no way to automatically make the joins have a radius - like an HTML border-radius. If that is what you are asking.
If the line has a bigger stroke width, you can choose to round the outside corner of the line joins.
.track {
fill: none;
stroke: black;
stroke-width: 20;
}
.round {
stroke-linejoin: round;
}
<svg width="300" height="300">
<polygon class="track" points="20,20 290,20 290,130 20,130"></polygon>
<polygon class="track round" points="20,170 290,170 290,280 20,280"></polygon>
</svg>
If you want to include bezier curve segments in your "line", you will have to use the <path> element instead. As was used in the example you linked to.
I suggest to put one duplicated figure above another one with just smaller stroke-width. Profit! :)
<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<polygon points="50,30 55,50 70,50 60,60 65,75 50,65 35,75 40,60 30,50 45,50" stroke-linejoin="round" stroke-width="50" stroke="red"/>
<polygon points="50,30 55,50 70,50 60,60 65,75 50,65 35,75 40,60 30,50 45,50" stroke-linejoin="round" stroke-width="30" stroke="#fff"/>
</svg>
A polygon does not use cubic Bézier curves, a path does. The example linked does not use any polygons, but a path which includes such curves.
The difference between a polyline and a polygon is simply that the latter is closed, so you can simply create a path and close it (implicitly or explicitly).
Beyond that, I'm not sure what your actual issue is.

enclosing the nodes of a d3 force directed graph in a circle or a polygon or a cloud

I have built a d3 force directed graph with grouped nodes. I want to enclose the groups inside cloud like structure. How can I do this?
Js Fiddle link for the graph: http://jsfiddle.net/Cfq9J/5/
My result should look similar to this image:
This is a tricky problem, and I'm not wholly sure you can do it in a performative way. You can see my static implementation here: http://jsfiddle.net/nrabinowitz/yPfJH/
and the dynamic implementation here, though it's quite slow and jittery: http://jsfiddle.net/nrabinowitz/9a7yy/
Notes on the implementation:
This works by masking each circle with all of the other circles in its group. You might be able to speed this up with collision detection.
Because each circle is both rendered and used as a mask, there's heavy use of use elements to reference the circle for each node. The actual circle is defined in a def element, a non-rendered definition for reuse. When this is run, each node will be rendered like this:
<g class="node">
<defs>
<circle id="circlelanguages" r="46" transform="translate(388,458)" />
</defs>
<mask id="masklanguages">
<!-- show the circle itself, as a base -->
<use xlink:href="#circlelanguages"
fill="white"
stroke-width="2"
stroke="white"></use>
<!-- now hide all the other circles in the group -->
<use class="other" xlink:href="#circleenglish" fill="black"></use>
<use class="other" xlink:href="#circlereligion" fill="black">
<!-- ... -->
</mask>
<!-- now render the circle, with its custom mask -->
<use xlink:href="#circlelanguages"
mask="url(#masklanguages)"
style="fill: #ffffff; stroke: #1f77b4; " />
</g>
I put node circles, links, and text each in a different g container, to layer them appropriately.
You'd be better off including a data variable in your node data, rather than font size - I had to convert the fontSize property to an integer to use it for the circle radius. Even then, because the width of the text isn't tied to the data value, you'll get some text that's bigger than the circle beneath it.
Not sure why the circle for the first node isn't placed correctly in the static version - it works in the dynamic one. Mystery.

Categories

Resources