I don't know why those two svg icons don't have exactly the same size when I'm checking it in the browser.
The first one is:
<svg viewBox="0 0 60 60">
<path
d='M10.3333333,16.7141667 L14.88,25.8333333 L51.6666667,25.8333333 L51.6666667,46.5 L10.3333333,46.5 L10.3333333,16.7141667 Z M56.8333333,10.3333333 L46.5,10.3333333 L51.6666667,20.6666667 L43.9166667,20.6666667 L38.75,10.3333333 L33.5833333,10.3333333 L38.75,20.6666667 L31,20.6666667 L25.8333333,10.3333333 L20.6666667,10.3333333 L25.8333333,20.6666667 L18.0833333,20.6666667 L12.9166667,10.3333333 L10.3333333,10.3333333 C7.49166667,10.3333333 5.1925,12.6583333 5.1925,15.5 L5.16666667,46.5 C5.16666667,49.3416667 7.49166667,51.6666667 10.3333333,51.6666667 L51.6666667,51.6666667 C54.5083333,51.6666667 56.8333333,49.3416667 56.8333333,46.5 L56.8333333,10.3333333 Z'
/>
</svg>
The second one:
<svg viewBox="0 0 60 60">
<path
d='M21,2 L3,2 C1.9,2 1,2.9 1,4 L1,16 C1,17.1 1.9,18 3,18 L10,18 L10,20 L8,20 L8,22 L16,22 L16,20 L14,20 L14,18 L21,18 C22.1,18 23,17.1 23,16 L23,4 C23,2.9 22.1,2 21,2 Z M21,16 L3,16 L3,4 L21,4 L21,16 Z'
/>
</svg>
The thing is that I need to have exactly the same viewBox (here 0 0 60 60)for both but when I'm setting it like this the second icon is much smaller then the first one. I'd like to have them looking the same (size) while having hte same viewBox. What am I missing here?
You can put the width and height atribute but still will not solve the issue
<svg viewBox="0 0 60 60" width="60" height="60">
<path d="M10.3333333,16.7141667 L14.88,25.8333333 L51.6666667,25.8333333 L51.6666667,46.5 L10.3333333,46.5 L10.3333333,16.7141667 Z M56.8333333,10.3333333 L46.5,10.3333333 L51.6666667,20.6666667 L43.9166667,20.6666667 L38.75,10.3333333 L33.5833333,10.3333333 L38.75,20.6666667 L31,20.6666667 L25.8333333,10.3333333 L20.6666667,10.3333333 L25.8333333,20.6666667 L18.0833333,20.6666667 L12.9166667,10.3333333 L10.3333333,10.3333333 C7.49166667,10.3333333 5.1925,12.6583333 5.1925,15.5 L5.16666667,46.5 C5.16666667,49.3416667 7.49166667,51.6666667 10.3333333,51.6666667 L51.6666667,51.6666667 C54.5083333,51.6666667 56.8333333,49.3416667 56.8333333,46.5 L56.8333333,10.3333333 Z"></path>
</svg>
and
<svg viewBox="0 0 60 60" width="60" height="60">
<path d="M21,2 L3,2 C1.9,2 1,2.9 1,4 L1,16 C1,17.1 1.9,18 3,18 L10,18 L10,20 L8,20 L8,22 L16,22 L16,20 L14,20 L14,18 L21,18 C22.1,18 23,17.1 23,16 L23,4 C23,2.9 22.1,2 21,2 Z M21,16 L3,16 L3,4 L21,4 L21,16 Z"></path>
</svg>
You can open the svg in ilustrator and fit the path to 60x60px
The second SVG has much more whitespace, and the paths only cover the top-left of the viewbox.
Added borders to show:
<svg viewBox="0 0 60 60" style="border:solid 1px red">
<path
d='M10.3333333,16.7141667 L14.88,25.8333333 L51.6666667,25.8333333 L51.6666667,46.5 L10.3333333,46.5 L10.3333333,16.7141667 Z M56.8333333,10.3333333 L46.5,10.3333333 L51.6666667,20.6666667 L43.9166667,20.6666667 L38.75,10.3333333 L33.5833333,10.3333333 L38.75,20.6666667 L31,20.6666667 L25.8333333,10.3333333 L20.6666667,10.3333333 L25.8333333,20.6666667 L18.0833333,20.6666667 L12.9166667,10.3333333 L10.3333333,10.3333333 C7.49166667,10.3333333 5.1925,12.6583333 5.1925,15.5 L5.16666667,46.5 C5.16666667,49.3416667 7.49166667,51.6666667 10.3333333,51.6666667 L51.6666667,51.6666667 C54.5083333,51.6666667 56.8333333,49.3416667 56.8333333,46.5 L56.8333333,10.3333333 Z'
/>
</svg>
<svg viewBox="0 0 60 60" style="border:solid 1px red">
<path
d='M21,2 L3,2 C1.9,2 1,2.9 1,4 L1,16 C1,17.1 1.9,18 3,18 L10,18 L10,20 L8,20 L8,22 L16,22 L16,20 L14,20 L14,18 L21,18 C22.1,18 23,17.1 23,16 L23,4 C23,2.9 22.1,2 21,2 Z M21,16 L3,16 L3,4 L21,4 L21,16 Z'
/>
</svg>
You can either:
Reduce the viewbox down to its ~ 25x25 viewbox and style the height/width using HTML/CSS instead
edit the SVG and have it fill a 60x60 viewbox
Related
I have two SVG paths that have a gap between them.
From reading through other questions (in particular this one) I understand this is because of the native anti-aliasing properties of SVGs.
So I added shapeRendering="crispEdges"
This does remove the gap. However it results in jagged edges because of the removal of anti-aliasing.
<svg height="300" width="300" shapeRendering="crispEdges">
<path
d="M150 10 a120 120 0 0 1 103.9230 60"
fill="none"
stroke="green"
stroke-width="20"
/>
<path
d="M253.9230 70 a120 120 0 0 1 0 120"
fill="none"
stroke="green"
stroke-width="20"
/>
</svg>
I've also tried the suggestion in this question to add crispEdges to the parent svg of the path and add shapeRendering="optimizeQuality" to the path but that didn't work.
How can I remove the gap AND keep the smooth edges of my svg path?
You could also mitigate this gap rendering effect by applying a subtle svg feMorphology dilate filter – resulting in slightly expanded strokes closing thin gaps between paths:
SVG feMorphology filter
svg {
overflow: visible;
}
.chart path {
filter: url(#outline);
}
path:hover {
stroke: red;
}
<svg height="300" width="300" shape-rendering="geometricPrecision">
<g class="original">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
</g>
<text x="50%" y="50%">Original</text>
</svg>
<svg height="300" width="300">
<filter filterUnits="userSpaceOnUse" id="outline" >
<feMorphology in="SourceGraphic" result="DILATED" operator="dilate" radius="0.5" />
</filter>
<g class="chart">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
</g>
<text x="50%" y="50%">Dilate filter</text>
</svg>
But this approach will also introduce slightly rounded edges (you can see this effect on hover).
More importantly, svg filters are quite expensive with regards to rendering performance – rather negligible if you only display a few elements per page view.
Add concatenated background path
As suggested by #Robert Longson: you could also prepend a background path based on concatenated d path data.
This task could be achieved with a javaScript helper method cloning the first path and displaying the concatenated paths.
addBgPaths(".addBGPath");
function addBgPaths(selector) {
let addPathSvgs = document.querySelectorAll(selector);
addPathSvgs.forEach(function(svg) {
let paths = document.querySelectorAll(".addBGPath path");
let firstPath = paths[0];
let firstPathCloned = firstPath.cloneNode();
//cloned elements shouldn't have ids to avoid non unique ids
firstPathCloned.removeAttribute("id");
let dArr = [firstPath.getAttribute("d")];
for (let i = 1; i < paths.length; i++) {
let path = paths[i];
let d = path.getAttribute("d");
dArr.push(d);
}
firstPathCloned.setAttribute("d", dArr.join(" "));
svg.insertBefore(firstPathCloned, svg.children[0]);
});
}
<svg height="300" width="300" shape-rendering="geometricPrecision">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
<text x="0" y="50%">Original</text>
</svg>
<svg class="addBGPath" height="300" width="300" shape-rendering="geometricPrecision">
<path id="first2" d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="green" stroke-width="20" />
<text x="0" y="50%">Add bg path</text>
</svg>
<svg class="addBGPath" height="300" width="300" shape-rendering="geometricPrecision">
<path id="first" d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="red" stroke-width="20" />
<text x="0" y="50%">Add bg path (red)</text>
</svg>
<svg height="300" width="300" shape-rendering="geometricPrecision">
<path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="green" stroke-width="20" />
<path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="red" stroke-width="20" />
<text x="0" y="50%">Original (red)</text>
</svg>
If all your path segments have the same color, this is probably the most elegant solution.
But this approach will also introduce colored "halos" when segments use different stroke colors (example #3 compared to #4).
If you able to edit the svg in editor, you can overlap like this. The darker green is the intersection between two paths.
As a quick fix, you can make the ends overlap with stroke-linecap="square"
But ideally, you need to create a single path instead of two separate paths.
<svg height="300" width="300" shapeRendering="crispEdges">
<path
d="M150 10 a120 120 0 0 1 103.9230 60"
fill="none"
stroke="green"
stroke-width="20"
stroke-linecap="square"
/>
<path
d="M253.9230 70 a120 120 0 0 1 0 120"
fill="none"
stroke="green"
stroke-width="20"
stroke-linecap="square"
/>
</svg>
I'm creating a 5-star-review using SVG, but need to be able to display a value to 1-decimal-point (e.g. 2.5/5 or 4.2/5).
I also need to be able to display multiple 5-star-reviews on the same page.
I've been able to create the following (which displays 2.5) but the 50% on the second <rect> in the mask (which is required for the 0.5 on the 3rd star) is hardcoded...
<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<defs>
<mask id="partial">
<rect x="0" y="0" width="64" height="64" fill="white" />
<rect x="50%" y="0" width="64" height="64" fill="black" />
</mask>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" id="star">
<path d="M32 2l-10 22l-20 2l15 14l-5 22l20-12l20 12l-5-22l15-14l-20-2Z"
stroke-width="3" stroke="#FFC800" />
</symbol>
</defs>
</svg>
<svg width="32" height="32" viewBox="0 0 64 64">
<use href="#star" fill="#FFC800"></use>
<use href="#star" fill="none"></use>
</svg>
<svg width="32" height="32" viewBox="0 0 64 64">
<use href="#star" fill="#FFC800"></use>
<use href="#star" fill="none"></use>
</svg>
<svg width="32" height="32" viewBox="0 0 64 64">
<use href="#star" fill="#FFC800" mask="url(#partial)"></use>
<use href="#star" fill="none"></use>
</svg>
<svg width="32" height="32" viewBox="0 0 64 64">
<use href="#star" fill="none"></use>
</svg>
<svg width="32" height="32" viewBox="0 0 64 64">
<use href="#star" fill="none"></use>
</svg>
Is there any way (preferably without javascript/jquery) that I can set the x="50%" on the <use> element?
Please remember that I will have multiple instances of the 5-star-review on the page at the same time, so it's not possible for me to dynamic set the x=50% on the <mask> because it will effect all instances.
What I don't want is to have to have 9 different id="partial10", id="partial20" <mask> elements.
I would like to do something like...
<use href="#star" fill="#FFC800" maskwidth="30%"></use>
If you want multiple instances on one page, then go for a native Web Component (supported in all browsers)
All HTML required:
<star-rating stars=5 rating="3.5"
bgcolor="green" nocolor="grey" color="gold"></star-rating>
<star-rating stars=7 rating="50%"
bgcolor="rebeccapurple" nocolor="beige" color="goldenrod"></star-rating>
to create:
But it does require JavaScript to create the Web Component
Key is to draw the rating color behind cutouts of all stars
Needs minor work to make 51% notation possible,
add more <rect> elements, it now does 2 for each star, and set the correct width for each mouseover capturing <rect>
The beauty of Web Components is: It totally does NOT matter when the <star-rating> is defined.
customElements.define("star-rating", class extends HTMLElement {
set rating(rate) {
if (!String(rate).includes("%")) rate = Number(rate) / this.stars * 100 + "%";
this.querySelector(":nth-child(2)").setAttribute("width", rate); //2nd rect
}
connectedCallback() {
let {bgcolor,stars,nocolor,color,rating} = this.attributes;
let repeat = (count, func) => Array(count).fill().map(func);
this.stars = ~~stars.value || 5;
this.innerHTML = `<svg viewBox="0 0 ${this.stars*100} 100" style=cursor:pointer>` +
`<rect height=100 fill=${nocolor.value} width=100% />` +
`<rect height=100 fill=${color.value} />` +
repeat(this.stars , (i, n) => `<path fill=${bgcolor.value} d="m${ n*100 } 0h102v100h-102v-100m91 42a6 6 90 00-4-10l-22-1a1 1 90 01-1 0l-8-21a6 6 90 00-11 0l-8 21a1 1 90 01-1 1l-22 1a6 6 90 00-4 10l18 14a1 1 90 010 1l-6 22a6 6 90 008 6l19-13a1 1 90 011 0l19 13a6 6 90 006 0a6 6 90 002-6l-6-22a1 1 90 010-1z"/>`) +
repeat(this.stars * 2, (i, n) => `<rect x=${ n*50 } n=${n} opacity=0 width=50 height=100 ` +
` onclick="this.closest('star-rating').dispatchEvent(new Event('click'))" ` +
` onmouseover="this.closest('star-rating').rating=${(n+1)/2}"/>`) +
"</svg>";
this.rating = rating.value;
}
});
<star-rating stars=5 rating="3.5"
bgcolor="green" nocolor="grey" color="gold"></star-rating>
<br>
<star-rating stars=7 rating="50%"
bgcolor="rebeccapurple" nocolor="beige" color="goldenrod"></star-rating>
I want svg text to be placed on a ring. Is it possible to wrap it around? Any workarounds please? I have tried transform matrix, but I am not able to do with it.
Example of ring image
You can convert a circle into a path. I used Inkscape for that. So, here is a basic example:
<svg viewBox="-10 -10 120 120" xmlns="http://www.w3.org/2000/svg" width="300" height="300">
<defs>
<path id="MyPath" fill="none" stroke="red"
d="M 50,95 A 45,45 0 0 1 5,50 45,45 0 0 1 50,5 45,45 0 0 1 95,50 45,45 0 0 1 50,95 Z" />
</defs>
<text textLength="280">
<textPath href="#MyPath">This is your text</textPath>
</text>
</svg>
Update
Maybe I misunderstood the question, so here is the new version. I'm not satisfied with the "skewing" if the text. I will update this answer later.
text {
font-size: 8px;
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="300" height="300">
<defs>
<path id="MyPath" fill="none" stroke="red"
d="M 46.326016,82.135999 C 75.229867,67.395261 78.467889,35.580206 78.467889,35.580206" />
</defs>
<image width="100" height="100" href="data:image/jpeg;base64,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"/>
<text textLength="50">
<textPath class="text" href="#MyPath">This is your text</textPath>
</text>
</svg>
Adding a Ring Bitmap to SVG Using <image>
Open the SVG file in a vector editor and create a path for the text
as #enxaneta comments:
You can use the ring inage inside an svg element. You will need to
draw a path where you want to put your text. Next you use this path as
a textPath inside the text element.
below is full code:
.container {
width:60vw;
height:60vh;
}
<div class="container">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" preserveAspectRatio="xMinYMin meet" id="svg4" viewBox="0 0 1181 1181">
<image xlink:href="https://i.stack.imgur.com/5pn89.jpg" id="image2" height="100%" width="100%"/>
<path id="RingPath" d="M 286.49258,567.98094 C 326.93719,456.93269 377.70892,383.63001 427.86229,316.51801 534.88572,173.30617 639.45611,129.74376 639.45611,129.74376" fill="none" />
<text font-size="60px" font-weight="bold" fill="#826B28">
<textPath href="#RingPath">
SVG Text to be placed
</textPath>
</text>
</div>
</svg>
I have an SVG with <path> elements embedded into a website which will work as an image map. The client has told me she wants numbers and embedded on each of the paths, and text on others. Any ideas how to accomplish this?
Maybe if I could access the centre coordinate of every zone, I could use some JS to position the text to there, but I am not sure how to do that.
Here is some of the code with example paths to hide client information:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 916.32 2130.72" style="enable-background:new 0 0 916.32 2130.72;" xml:space="preserve">
<g id="Layer_2">
<image style="overflow:visible;" width="1909" height="4439" id="bg" xlink:href="map.jpg" transform="matrix(0.48 0 0 0.48 0.0681 -1.0503)">
</image>
</g>
<g id="Layer_1">
<a xlink:href="#">
<path id="path1" class="st0" d="M766.56,190.56l78.24-82.08l28.8,4.8l18.24,79.68l-26.88,72.48l-86.4-33.6l-0.48-7.2V213.6
l-1.92-7.68l-4.32-6.72L766.56,190.56z"></path>
</a>
<path id="path2" class="st0" d="M530.88,272.16l64.8-2.88l5.76,74.4l-67.68,1.44L530.88,272.16z"></path>
<path id="path3" class="st0" d="M407.52,276.96l45.12-0.48l5.28,72.48l-83.52,4.32L407.52,276.96z"></path>
</g>
</svg>
You could use <textPath> SVG element to draw all your textes. For each text you have to use one <textPath> and one <path> element for it. To render text along the shape of a <path>, enclose the text in a <textPath> element that has an href attribute with a reference to the <path> element. All this <path> elements you have to add into <defs> element with unique ID. Read more about this element and his attributes under the link above.
And it is very important: all your <textPath> elements you have to write within <text> element on the end of yor SVG because of the zIndex (the lattest added element is on top).
And here is the demo how it works:
<svg width="400" height="120" viewBox="0 0 1000 300">
<defs>
<path id="MyPath1"
d="M 100 200
C 200 100 300 0 400 100
C 500 200 600 300 700 200
C 800 100 900 100 900 100"/>
<path id="MyPath2" d="M300,300L700,50"/>
</defs>
<!-- red line under text. You can delete the following line -->
<use href="#MyPath1" fill="none" stroke="red"/>
<text font-family="Verdana" font-size="42.5">
<textPath href="#MyPath1">We go up, then we go down, then up again</textPath>
<textPath href="#MyPath2" fill="red">And the second text</textPath>
</text>
Unfortunately, we can not use your code, because it is incomplete.
I have an SVG with elements embedded into a website which will
work as an image map. The client has told me she wants numbers and
embedded on each of the paths, and text on others.
I want to show you step by step the technique with which this kind of problem is solved.
It is not necessary to draw a map of the region in svg. You can take a screenshot of a fragment of a real map and add any text information to it.
I took a screenshot of the map drawing from the question and uploaded it to the vector editor
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="948" height="761" viewBox="0 0 948 761" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.stack.imgur.com/DriVh.jpg" width="100%" height="100%" />
</svg>
At the second step in the vector editor using the tool Draw Bezier curves and straight lines, lines are created along which the text will be located.
The file is saved in SVG format and the paths of these lines are copied from it.
The required text will be located along these patches.
The beginning of the text on the line can be adjusted with the attribute startOffset ="35%"
Due to the fact that the bitmap and the text are located within the same SVG, the relative positioning will never be violated on any display of the gadget.
Below is the complete application code
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="948" height="761" viewBox="0 0 948 761" preserveAspectRatio="xMinYMin meet">
<!-- Screenshot of a map fragment -->
<image xlink:href="https://i.stack.imgur.com/DriVh.jpg" width="100%" height="100%" />
<!-- Paths along which text information will be located -->
<path id="pali" d="m274.8 751.9c0 0-0.5-105.9 4.6-158.5 4.7-49.1 13-97.9 23.9-145.9 9.9-43.6 19.5-87.9 37.6-128.8 15.1-34.1 28.3-97.8 41-147.1 7.8-30.3 21.7-91.2 21.7-91.2" style="fill:none;stroke-width:2;stroke:none"/>
<path id="south50" d="m228 291.3 94.6-5.7" style="fill:none;"/>
<path id="south50_2" d="m399 269.7c0 0 101.8-5 152.8-6.8 28.1-1 56.3-1.2 84.4-2.3 24.3-0.9 48.9 0.6 73-3.4 16-2.7 30.7-11.4 46.7-13.7 0.4-0.1 1.1 0 1.1 0" style="fill:none;"/>
<path id="south120" d="m348.9 516.2c0 0 76-3.4 114-4.6 35.3-1.1 72.7-2.8 106-2.3 25.1 0.4 4.1 101.1 2.3 151.6-1.1 30.9-8 92.3-8 92.3" style="fill:none;"/>
<path id="south120_2" d="m600.8 509 209.8-9.1" style="fill:none;"/>
<text font-family="serif" font-size="22px" font-weight="700">
<textPath href="#pali" startOffset="35%">Palisades DR street</textPath>
<textPath href="#south50" >50 south</textPath>
<textPath href="#south50_2" startOffset="75%" >50 south</textPath>
<textPath href="#south120" startOffset="15%" >120 south</textPath>
<textPath href="#south120_2" startOffset="55%" >120 south</textPath>
</text>
</svg>
As a bonus, the option to animate the route to the office
Please read the comments in the program code.
I hope this will help you understand the principle of the route animation
The animation will start after clicking on the SVG canvas
.container {
width:75vw;
height:75vh
}
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 948 761" preserveAspectRatio="xMinYMin meet" >
<defs>
<mask id="msk" >
<!-- Animation of a mask showing route growth -->
<path stroke="white" stroke-width="3" stroke-dasharray="1212" stroke-dashoffset="1212" stroke-dash-offset="1212" id="trace" d="m555.2 749.6c0 0 6.6-76 9.1-114 2.8-41.4 25.3-116.9 6.8-124.3-46.7-18.7-133.3 6.7-199.5 0-20.8-2.1-48.8 4.1-61.6-12.5-21.3-27.8 0.8-70.4 6.8-104.9 5.9-33.5 14.9-66.9 28.5-98 4.4-10.2 7.7-22.7 17.1-28.5 34.4-21.2 80.5-7 120.8-9.1 41.4-2.1 82.9-1.5 124.3-3.4 29.7-1.4 59.3-3.6 88.9-5.7 9.9-0.7 20.1 0.3 29.6-2.3 29.8-8.2 83.2-41 83.2-41">
<animate attributeName="stroke-dashoffset"
begin="svg1.click"
dur="10s"
values="1212;0"
fill="freeze" />
</path>
</mask>
<symbol id="marker" width="4%" viewBox="0 0 365 560" >
<path id="marker" fill="#00AEEF" d="M182.9,551.7c0,0.1,0.2,0.3,0.2,0.3S358.3,283,358.3,194.6c0-130.1-88.8-186.7-175.4-186.9
C96.3,7.9,7.5,64.5,7.5,194.6c0,88.4,175.3,357.4,175.3,357.4S182.9,551.7,182.9,551.7z M122.2,187.2c0-33.6,27.2-60.8,60.8-60.8
c33.6,0,60.8,27.2,60.8,60.8S216.5,248,182.9,248C149.4,248,122.2,220.8,122.2,187.2z"/>
</symbol>
</defs>
<!-- Fragment of a raster map -->
<image xlink:href="https://i.stack.imgur.com/DriVh.jpg" width="100%" height="100%" />
<!-- patches along which text information is located -->
<path id="pali" d="m274.8 751.9c0 0-0.5-105.9 4.6-158.5 4.7-49.1 13-97.9 23.9-145.9 9.9-43.6 19.5-87.9 37.6-128.8 15.1-34.1 28.3-97.8 41-147.1 7.8-30.3 21.7-91.2 21.7-91.2" style="fill:none;stroke-width:2;stroke:none"/>
<path id="south50" d="m228 291.3 94.6-5.7" style="fill:none;"/>
<path id="south50_2" d="m399 269.7c0 0 101.8-5 152.8-6.8 28.1-1 56.3-1.2 84.4-2.3 24.3-0.9 48.9 0.6 73-3.4 16-2.7 30.7-11.4 46.7-13.7 0.4-0.1 1.1 0 1.1 0" style="fill:none;"/>
<path id="south120" d="m348.9 516.2c0 0 76-3.4 114-4.6 35.3-1.1 72.7-2.8 106-2.3 25.1 0.4 4.1 101.1 2.3 151.6-1.1 30.9-8 92.3-8 92.3" style="fill:none;"/>
<path id="south120_2" d="m600.8 509 209.8-9.1" style="fill:none;"/>
<!-- Route to the office -->
<path id="trace_anim" mask="url(#msk)" fill="none" stroke="crimson" stroke-width="4" stroke-dasharray="10 7" d="m555.2 749.6c0 0 6.6-76 9.1-114 2.8-41.4 25.3-116.9 6.8-124.3-46.7-18.7-133.3 6.7-199.5 0-20.8-2.1-48.8 4.1-61.6-12.5-21.3-27.8 0.8-70.4 6.8-104.9 5.9-33.5 14.9-66.9 28.5-98 4.4-10.2 7.7-22.7 17.1-28.5 34.4-21.2 80.5-7 120.8-9.1 41.4-2.1 82.9-1.5 124.3-3.4 29.7-1.4 59.3-3.6 88.9-5.7 9.9-0.7 20.1 0.3 29.6-2.3 29.8-8.2 83.2-41 83.2-41" />
<text font-family="serif" font-size="22px" font-weight="700">
<textPath href="#pali" startOffset="35%">Palisades DR street</textPath>
<textPath href="#south50" >50 south</textPath>
<textPath href="#south50_2" startOffset="75%" >50 south</textPath>
<textPath href="#south120" startOffset="15%" >120 south</textPath>
<textPath href="#south120_2" startOffset="55%" >120 south</textPath>
</text>
<!-- Markers on the map -->
<use xlink:href="#marker" x="800" y="-200" />
<use xlink:href="#marker" x="550" y="350" />
</svg>
</div>
There is an imaginary square which I want to draw as two halves, i.e. two triangles. Whilst they should perfectly fit together and make a square, a tiny line caused by anti-aliasing appears.
These triangles should be of different color, but I left both them black in the given example to make the line more visible.
<svg width="100" height="100"
viewPort="0 0 100 100" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="first">
<path d="M 0 0 L 100 100 L 0 100 Z" fill="red"/>
</clipPath>
<clipPath id="second">
<path d="M 0 0 L 100 0 L 100 100 Z" fill="red"/>
</clipPath>
</defs>
<rect width="100" fill="black" height="100"
clip-path="url(#first)"/>
<rect width="100" fill="black" height="100"
clip-path="url(#second)"/>
</svg>
JSFiddle
I am open to solutions - canvas, WebGL etc. I just want to know possible solutions which would improve rendering.
I'm not sure why you are seeing the line using clip paths, but if I just change it around to using regular polygons and use shape-rendering: crispEdges the line doesn't appear:
<svg width="100" height="100" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<polygon points="0,0 100,0 100,100" style="fill:black;shape-rendering:crispEdges;" />
<polygon points="0,0 100,100 0,100" style="fill:black;shape-rendering:crispEdges;" />
</svg>