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.
Related
Due to confidentiality, I cannot get into the specifics of the code I am working with, but I'll do my best to describe the issue I'm having.
My professor made a simple-ish React program that generates and outputs SVGs based on a set of parameters for a microchip manufacturing project. We make use of the Flatten-js npm library to create the svgs, along with some helper functions that cobble everything together. We specify parameters as a number, but the number represents units in microns. We have a save function that downloads the svg from the webpage, which makes use of the Flatten.Polygon.svg() method. The method takes some parameters, but specifying units is not one of them. The SVG looks something like:
<svg>
<path stroke="none" stroke-width="1" fill="black" fill-rule="evenodd" fill-opacity="1" d="
M5999.774896627996,6000.3432414235895 L5992.810049576532,6002.509804857073 A0.0338333333333333,0.0338333333333333 0 0,1 5992.789950423468,6002.445192150708 L5999.754797474932,6000.278628717223 A0.04999999999999982,0.04999999999999982 0 0,1 5999.8,6000.25 L6005.7,6000.25 A0.04999999999999982,0.04999999999999982 0 0,1 6005.7,6000.35 L5999.8,6000.35 A0.04999999999999982,0.04999999999999982 0 0,1 5999.774896627996,6000.3432414235895 z
..."></path>
</svg>
The issue is, I need to import the svg into Adobe Illustrator and Fusion 360. When I import them, the SVG works well enough to contain the shapes we predict, but the scaling is wrong. Since the units were meant to be in microns, but F360 works in mm, I expected to have to scale it down to 0.001 the size, but it is way too small when scaled. I'm assuming this has something to do with the program assuming the path's DPI, so in Illustrator I hoped that I could specify PPI manually, but it only has preset values of 72PPI and 300PPI, but the size of the svg in Illustrator is the same regardless of the PPI setting.
To a point, this ceases to be about React, and more about the specifics of html and svg paths, but the program does use React to do what it does. I'm hoping we can do it in code, but if I have to manually edit SVGs I will. Any insight would be appreciated. Thanks!
To spell out what #enxaneta probably thinks, a <svg width="1mm" height="1mm" viewBox="5000 6000 1000 1000"> would identify the
userspace units for the path as micron.
It turns out that this was most definitely the solution. That, coupled with a transform attribute to scale it from microns to mm. Thank you everyone for the speedy responses!
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
<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/
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).