In SVG, is it possible to translate the marker_start / marker_end along a Path?
<path id="e:3" fill="black" fill-opacity="1.0" stroke="black" stroke-opacity="1.0" stroke-width="1" d=" M2 12 L18 17 z" marker-start="url(#markerStart)">
I'd like to translate marker-start some X units along the path. How would I do that?
You can set your marker's refX and refY attributes, which define where the marker should be attached to the path. For more details see the specification.
Possibly you will also need to adjust the viewBox on the <marker> element. And you can draw outside the viewBox if you need, provided you set overflow:visible on the <marker> element (or alternatively specify large enough values in the markerWidth, markerHeight attributes).
Related
Background:
I running an express server with a route to all my static files.
In the static files, I have a folder full of map .svg's.
On the client side (React), I fetch the maps and adding them to to a component.
Question:
I need to rewrite the .svg's, and add this to their path attribute: fill=url(#some_flag).
Svg before:
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1024pt" height="1024pt" viewBox="0 0 1024 1024"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0,1024) scale(0.1,-0.1)"
fill="#000000" stroke="none">
<path d="... numbers...-78 -28 -115 "/>
</g>
</svg>
Svg After:
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1024pt" height="1024pt" viewBox="0 0 1024 1024"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0,1024) scale(0.1,-0.1)"
fill="#000000" stroke="none">
<path d="... numbers...-78 -28 -115"
fill="url(#some_flag)"/> <!--THE ADDED ATTRIBUTE -->
</g>
</svg>
I had a few directions in mind:
Pure Javascript: setAttribute of path, which means I'll have to give each path an id?
somehow penetrate the .svg with CSS? I tried it and its impossible to override inline SVG attributes
Have you dealt with it before (of course you did...)? What are my options?
I'm answering this part: << I had a few directions in mind:
1- Pure Javascript: setAttribute of path, which means I'll have to give each path an id? >>.
It can be the best solution, but I wouldn't use "id" because it is not reliable enough (no unicity guaranty, if inadvertently duplicated).
You want to add an attribute fill="url(#some_flag)", and your #some_flag is probably indexed somewhere (flag[i]), and linkable to the sequence of path. If #some_flag must be computed from the geometry, you may pre-process it into an array, or compute at run-time. The CSS selector can be more complex also, depending on your needs. This may answer that part of your question:
document.querySelectorAll("g > path")
.forEach((x,i) => x.setAttribute("fill",`url(${flag[i]})`));
Actually I did experiment it with a svg map excerpted from The Economist Big Mac Index (a local copy):
fetch("./bigMacSvg1.txt", {method:"GET"})
.then(res => res.text())
.then(res => {
//console.log(res);
document.querySelector(".here").innerHTML = res; //div for svg
document.querySelectorAll("path:nth-child(n+2)")
.forEach(x => x.setAttribute("fill","#a1b2c3"));
})
.catch(err => {console.log(err)});
The above code sets a light color to every country, but not to the ocean (first path).
As I think you've discovered, including SVG's via an img tag is limiting. Avoid it.
You can set up a sort of proxy component that fetches the SVG contents, converts them to JSX, and lets you include the SVG contents inline. This will allow them to be easily manipulated with CSS and JavaScript.
Here's a library that will handle translating the files to JSX format.
https://www.npmjs.com/package/svg-to-jsx
I have the coordinates that draw the following polygon in the google maps API:
Here is a sample of the coordinates:
longitude: -71.09972, latitude: 9.15553
Following the Mercator-projection formula from this post: Convert a Google Maps polygon path to an SVG path, I get a SVG path that has negative values like this:
M-50.559802168888886,121.46151557464762 -50.589327502222226,121.46285530595195 -50.643108835555566,121.428264939842 ...
When I try to draw that path, no image is shown. However, when I remove the negative symbol, show the following SVG image:
The SVG image is flipped. Is there a way to change the formula to get the correct value? I need the SVG path clean, that means that flip the image with CSS is not an option.
Thanks and regards.
Without seeing your actual SVG output (in SVG fileformat) is hard to say where the problem is. It could be wrong coordinates conversion, wrong encoding.
The most often cause of no image shown in SVG export is wrong or no viewport
For example this is one of my SVG exports (2D slice of glass mesh profile used as input for some machinery):
<svg width="512" height="512" viewBox="-84.609371 -84.500872 461.177478 1568.45906" stroke-width="1.5px" stroke="black" fill="none" >
<path stroke="blue" stroke-width="1px" d="M 285.581417 0.067317 l 6.4185 12.837 l -3.2093 1386.3928 l -0.000617 0.092881 l -288.79 -0.039845 "/>
<path stroke="red" stroke-width="1px" d="M 285.581417 0.067317 l -38.5109 1222.7214 l -16.0462 22.4647 l -41.7202 16.0462 l -189.3453 0 "/>
</svg>
Take a look especially on the first line. And check if your SVG has it. The viewBox property selects which part of the space will be shown and width,height are the output image resolution where the viewBox is mapped to. You need to set booth to maintain aspect ratio.
The mirror x (flip) is done quite easily see the same example again
<svg width="512" height="512" viewBox="-84.609371 -84.500872 461.177478 1568.45906" stroke-width="1.5px" stroke="black" fill="none" >
<g transform="scale(-1.0,1.0) translate(+84.609371,0.0) translate(-461.177478,0.0)">
<path stroke="blue" stroke-width="1px" d="M 285.581417 0.067317 l 6.4185 12.837 l -3.2093 1386.3928 l -0.000617 0.092881 l -288.79 -0.039845 "/>
<path stroke="red" stroke-width="1px" d="M 285.581417 0.067317 l -38.5109 1222.7214 l -16.0462 22.4647 l -41.7202 16.0462 l -189.3453 0 "/>
</g>
</svg>
As you can see I added <g> tag with transform to flip the whole thing without changing path coordinates. I use scale and 2x translate (can be done with one but I wanted to show where the values comes from) You can also use matrix instead. The scale just inverts x axis and translates shift the image so it is centered again ...
[Edit1] if you want "clean" points in path
Then you need to apply the transform on them directly so uppercase letters (like M,L) means absolute values ... so apply both scale and translation on them. Lowercase letters mean relative values so apply just scale on them and you should be fine. Another option is to apply this on the input polygon you are exporting to SVG instead.
I am currently working on svg animations.
I have a SVG element which follows a path with the animateMotion property.
My shape :
<g id="dart" transform="scale(-1,1) translate(-587, -145)">
<path d="..." />
</g>
My path :
<path id="motionPath" fill="none" stroke="none" stroke-miterlimit="10" d="..."/>
My AnimateMotion :
<animateMotion xlink:href="#dart" dur="1s" begin="0s" fill="freeze" rotate="auto"><mpath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#motionPath"></mpath></animateMotion>
It works perfectly. However, it begins to move after 2s when page is loaded. I would like to launch the animation on an JS event. Indeed, I need to scroll down in the page for see the SVG and when he is visible the animation starts.
The JS :
var pos = $("#dart").offset().top;
$(window).scroll(function(){
var scrollTop=$(window).scrollTop();
if(scrollTop>=pos){
/* --- start animation here with injecting --- */
var motion=document.createElementNS("http://www.w3.org/2000/svg","animateMotion");
motion.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#dart");
motion.setAttributeNS("http://www.w3.org/2000/svg", "dur", "1s");
motion.setAttributeNS("http://www.w3.org/2000/svg", "begin", "0s");
motion.setAttributeNS("http://www.w3.org/2000/svg", "fill", "freeze");
motion.setAttributeNS("http://www.w3.org/2000/svg", "rotate", "auto");
var mpath = document.createElementNS("http://www.w3.org/2000/svg","mpath");
mpath.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#motionPath");
motion.appendChild(mpath);
document.getElementById("target").appendChild(motion);
}
});
I tried to inject (with createElementNS) the <animateMotion> or to change the begin's value in order to start the animation on the event but it does not work.
If someone has an idea...
To summarise what I originially wrote in comments...
You'd normally set the animate motion to begin on click by setting its begin attribute e.g. begin="dart.click"
jquery is designed to work with html, any svg support is mostly by accident. So when it creates elements it creates them in the html namespace rather than the SVG namespace. So the first step is to convert your code to using standard DOM methods such as document.createElementNS.
If you do use the DOM to create elements and attributes, take care to create them in the correct namespace.
SVG elements should be created in the SVG namespace
most attributes are in the null namespace and should be set by calling element.setAttribute
xlink:href attributes are in the xlink namespace however and must be created by calling element.setAttributeNS, passing the xlink namespace as the first argument.
<svg height="210" width="400">
<path d="M150 0 L75 200 L225 200 Z" />
</svg>
Does d stand for something in particular? I couldn't find anything via Google.
d is Path Data. The definition of the outline of a shape.
Reference : http://www.w3.org/TR/SVG/paths.html#PathData
d refers to the <path> data. (mdn link)
M tells the canvas to put the pen down at a specific location. It doesn't draw to that point from wherever it was previously.
L tells the canvas to draw a line from wherever it was last to the given coordinate.
Z tells the canvas to stop drawing (pick the pen up).
I found this overview from Dashing d3js on SVGs helpful.
I would like to display on google maps a marker for my current position that I can rotate depending on the user's heading.
Currently only symbols can be attached to a marker and rotated (more here https://developers.google.com/maps/documentation/javascript/symbols).
My challenge is that I want to use a custom symbol that looks like this (https://drive.google.com/file/d/0B5UD8mTDFqP7UHZ6bGpMeGpFR1U/edit?usp=sharing).
My problem is that the SVG file uses to define the shape a PATH and CIRCLE, but google API supports only path.
This is the SVG markup:
<g>
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#ED6C61" d="M8.234,17.247c- .68,0-3.28-0.336-4.744-0.938c1.975,2.701,3.938,4.688,4.744,4.688s2.77-1.986,4.745-4.688C11.516,16.911,9.915,17.247,8.234,17.247z"/>
</g>
</g>
<circle fill="#ED6C61" cx="8.235" cy="8.235" r="8.235"/>
How do I obtain this shape by only using the path?
Thanks
Create a single path of both objects.
Workflow(using inkscape):
open the SVG
select the circle
convert the circle into a path:
CTRL+SHIFT+C (or menu->path->object to path)
select both pathes:
CTRL+A
combine the pathes:
CTRL+K (or menu->path->combine)
Result:
m 16.469999,8.2349997 c 0,4.5480643 -3.686935,8.2349993 -8.2349993,8.2349993 C 3.6869349,16.469999 0,12.783064 0,8.2349997 0,3.6869349 3.6869349,0 8.2349997,0 12.783064,0 16.469999,3.6869349 16.469999,8.2349997 z M 8.234,17.247 c -1.68,0 -3.28,-0.336 -4.744,-0.938 1.975,2.701 3.938,4.688 4.744,4.688 0.806,0 2.77,-1.986 4.745,-4.688 -1.463,0.602 -3.064,0.938 -4.745,0.938 z
Demo: http://jsfiddle.net/doktormolle/LLH5s/