SVG Marker gets rendered differently on different screens - javascript

Update:
I figured out the screen issue. device pixel ratio is the culprit. On devices with lower window.devicePixelRatio the icon gets displayed smaller, a solution is to make the size of the icon conditional on window.devicePixelRatio, i.e. :
scaledSize: highDevicePixelRatio ? new google.maps.Size(40, 60) : new google.maps.Size(60, 90)
resolution might also play a role, but I couldn't test that as of now.
The issue with Internet Explorer 11 still exists though.
** End Update **
So this is really absurd and I am somewhat still baffled. I noticed this extremely inconsistent behavior of my custom markers. Drove me crazy, because I couldn't figure out why they would be behaving differently. I just now realized it depends on the screen I am displaying the map/marker on. I am using https://github.com/tomchentw/react-google-maps.
I am using a MacBookPro 2015 and a LG 34UC98-W hooked up via HDMI cable.
But not only the screen, also the used browser gives different results. It works somewhat fine on chrome (differences in screens), the marker don't show up at all in IE 11 (haven't tested FireFox).
Now this is how I currently instantiate my marker:
const marker = {
position: new google.maps.LatLng(this.state.center.lat,this.state.center.lng),
icon: {
url: icon_url(this.props.markerIcon,'purple'),
anchor: new google.maps.Point(13,42),
scaledSize: new google.maps.Size(40, 60)
},
draggable: false,
}
On my MacBook I get the following result:
On my LG I get the following result:
This is driving me NUTS, is there a way to achieve consistent behavior across screens/browsers? What is the reason for this???
Following the SVG Code:
I tried with and without the explicit width and height attributes in the first svg tag. Does not make a difference.
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-291 377 28 40" width="28px" height="40px" style="enable-background:new -291 377 28 40;" xml:space="preserve">
<path id="pin" style="fill:#7261C3;stroke:#4B4080;stroke-width:0.6909;stroke-linejoin:round;stroke-miterlimit:10;" d="
M-277,416.286c9.188-11.902,13-17.688,13-25.75c0-7.188-5.062-12.823-13-12.823s-13,5.635-13,12.823
C-290,398.599-286.188,404.384-277,416.286z"/>
<g id="subject">
<path style="fill:#FFFFFF;" d="M-285.998,394.741c0.367,0.197,0.788-0.671,0.966-1.095c0.067-0.16,0.137-0.325,0.206-0.484
c0.354-0.812,0.713-1.485,1.1-2.059c0.451-0.67,0.933-1.2,1.473-1.618c0.477-0.37,1.017-0.658,1.603-0.857
c0.28-0.095,0.564-0.167,0.851-0.217c-0.172,0.361-0.319,0.733-0.437,1.11c-0.097,0.31-0.175,0.624-0.233,0.939
c0.208,0.046,0.407,0.131,0.582,0.253c0.072,0.062,0.144,0.125,0.216,0.187c0.122-0.854,0.404-1.684,0.812-2.444
c0.15-0.279,0.316-0.548,0.499-0.807c0.022-0.031,0.025-0.072,0.009-0.106c-0.016-0.034-0.05-0.057-0.088-0.06
c-0.137-0.009-0.275-0.014-0.413-0.014c-1.407,0-2.814,0.473-3.928,1.336c-1.309,1.013-2.173,2.495-2.834,4.012
C-285.864,393.397-286.442,394.479-285.998,394.741z"/>
<path style="fill:#FFFFFF;" d="M-267.856,399.462l-0.017-0.056c-0.031-0.104-0.104-0.191-0.2-0.24
c-0.097-0.049-0.209-0.057-0.312-0.021c-0.958,0.332-1.973,0.5-2.987,0.5c-0.685,0-1.37-0.077-2.037-0.233
c0.14,0.316,0.274,0.635,0.4,0.956c0.536,0.09,1.083,0.135,1.637,0.135c0.848,0,1.693-0.107,2.511-0.319
c0.254-0.066,0.504-0.141,0.75-0.226C-267.906,399.889-267.794,399.669-267.856,399.462z"/>
<path style="fill:#FFFFFF;" d="M-275.021,394.647c0.312-0.814,0.542-1.659,0.684-2.518c0.022-0.135,0.059-0.271,0.107-0.399
c0.159-0.423,0.284-0.862,0.373-1.304c0.083-0.414,0.134-0.834,0.154-1.256c0.544,0.229,1.111,0.434,1.697,0.611
c0.83,0.252,1.685,0.446,2.542,0.577c0.025,0.004,0.05,0.006,0.075,0.006c0.238,0,0.447-0.174,0.485-0.417
c0.041-0.268-0.143-0.518-0.411-0.559c-0.811-0.124-1.621-0.308-2.406-0.546c-0.777-0.235-1.521-0.522-2.212-0.851
c-0.374-0.178-0.752-0.378-1.117-0.571c-0.055-0.029-0.109-0.058-0.164-0.087l-0.138-0.073c-0.554-0.292-1.078-0.568-1.572-0.901
c-0.407-0.273-0.791-0.586-1.142-0.927c-0.194-0.189-0.505-0.185-0.694,0.01c-0.189,0.194-0.185,0.505,0.01,0.694
c0.393,0.383,0.824,0.732,1.279,1.038c0.459,0.309,0.942,0.573,1.417,0.825c-0.039,0.306-0.084,0.612-0.136,0.914
c-0.088,0.518-0.196,1.038-0.321,1.55c-0.267,0.019-0.533,0.046-0.797,0.08c-0.179,0.023-0.388,0.053-0.598,0.122
c-0.275,0.091-0.502,0.232-0.676,0.419c-0.225,0.243-0.328,0.533-0.404,0.745c-0.028,0.077-0.055,0.154-0.083,0.232
c-0.334-0.326-0.679-0.641-1.034-0.945c-0.238-0.166-0.527-0.257-0.817-0.259c-0.29-0.002-0.58,0.086-0.82,0.249
c-0.258,0.175-0.457,0.436-0.557,0.732c-0.1,0.295-0.101,0.623-0.003,0.919c0.955,2.143,2.443,4.046,4.293,5.489
c1.172,0.914,2.487,1.645,3.882,2.158c0.084,0.031,0.178,0.01,0.241-0.053c0.063-0.063,0.084-0.157,0.053-0.241
c-0.441-1.188-0.985-2.337-1.624-3.431c-0.26,0.242-0.603,0.508-0.997,0.685c-0.001-0.001-0.001-0.001-0.001-0.001
C-275.871,396.518-275.389,395.605-275.021,394.647z M-275.542,391.889c-0.128,0.791-0.338,1.569-0.625,2.318
c-0.107,0.28-0.225,0.555-0.354,0.826c-0.389-0.546-0.803-1.073-1.24-1.581c-0.082,0.171-0.182,0.333-0.3,0.482
c-0.162,0.207-0.356,0.389-0.572,0.538c0.003-0.007,0.006-0.015,0.008-0.022c0.263-0.732,0.53-1.476,0.792-2.21
c0.044-0.124,0.095-0.265,0.148-0.323c0.03-0.032,0.088-0.064,0.16-0.088c0.107-0.035,0.236-0.053,0.369-0.07
c0.342-0.044,0.689-0.074,1.035-0.092c0.129-0.006,0.259,0.014,0.379,0.062c0.046,0.018,0.091,0.035,0.136,0.052
C-275.56,391.798-275.534,391.843-275.542,391.889z"/>
<ellipse style="fill:#FFFFFF;" cx="-274.416" cy="385.286" rx="1.486" ry="1.739"/>
</g>
</svg>

I had a similar issue recently and had to change the meta tag in my html to work across devices. Seems like currently you don't have one so maybe try adding the following to your html:
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=0">
If you're only modifying the XML then you may have to use /> to close the tag or use the xml namespace as referenced in this post

Related

How do I get d3.zoom working for inline svg?

I am trying to use d3.zoom on an inline svg, specifically a map of the USA (please note that I am very inexperienced at d3js). After some research I found a simple tutorial for using d3.zoom https://www.datamake.io/blog/d3-zoom/.
The issue I have now is that it just doesn't work. There is no error which shows up. It just does nothing.
Here is the HTML code with the svg map.
<div id="map">
<?xml version="1.0" encoding="UTF-8"?>
<svg id="usa_svg" height="800" width="1200" version="1.1" viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg">
<g id="USA">
<rect height="600" width="1200"></rect>
<!-- paths here -->
</g>
</svg>
</div>
Here is the JavaScript
var usa = d3.select("svg")
var rect = d3.select("rect");
var zoom = d3.zoom().on("zoom", zoomed);
rect.call(zoom);
function zoomed() {
var transform = d3.event.transform;
usa.attr("transform", transform.toString());
}
I have no clue what I am doing wrong. Is it a syntax error? Am I just missing a vital part of the code? Help would be much appreciated.

I need help understanding how to get s stringified (variable) version of an SVG image

I am currently working with an svg image that I need help stringifying, If that makes sense. Basically how to make the image open in a text/code editor as only variables?
Here is an example of what I am looking for:
var svgData='PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2ZXJzaW9uPSIxLjEiPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0ic3Ryb2tl
Currently when open an svg image in a text editor I just get something like this.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG
Version: 6.00 Build 0) -->
<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 255.1 227.3" style="enable-background:new 0 0 255.1
227.3;" xml:space="preserve">
<style type="text/css">
Any help is welcome! Thank You.
It looks like svgData is cut a little short. But if I understand your question right, you want that encoded svgData available in a textarea?
You can use the native functions btoa and atob (https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding) to encode and decode the svg content.
For example using your svgData value: atob("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2ZXJzaW9uPSIxLjEiPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0ic3Ryb2tl") = <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" version="1.1"><defs><linearGradient id="stroke"
and we can convert it back with:
btoa('<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" version="1.1"><defs><linearGradient id="stroke"') = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2ZXJzaW9uPSIxLjEiPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0ic3Ryb2tlIg=="

Using an svg object as a container for a Google map

As the title says I have an svg object and I want that object to contain a Google map instance. I was trying to do this the same way I usually do with divs or simple elements, using Javascript and getElementByID and placing the map inside the element. however this does not seem to work here. I have done a lot of searching but since Google uses svg for custom icons and overlays all the responses are related to that. I've mostly tried different approaches regarding where to put the id="map_canvas but nothing has worked.
My HTML with the svg as an object:
<div class="row map">
<div class="span12">
<object type="image/svg+xml" id="map_canvas" data="assets/map/MA_map.svg"></object>
</div>
</div>
My JavaScript (this is currently in the <head> tag but I want to move it to the .js document):
<script>
function initialize() {
var mapCanvas = document.getElementById('map_canvas');
var mapOptions = {
center: new google.maps.LatLng(44.5403, -78.5463),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(mapCanvas, mapOptions)
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
And finally this is what my svg file looks like (created in Illustrator):
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
id="map_canvas"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-79.892 94.942 960 599.864"
enable-background="new -79.892 94.942 960 599.864"
xml:space="preserve">
<filter id="dropshadow" height="130%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/> <!-- stdDeviation is how much to blur -->
<feOffset dx="2" dy="2" result="offsetblur"/> <!-- how much to offset -->
<feMerge>
<feMergeNode/> <!-- this contains the offset blurred image -->
<feMergeNode in="SourceGraphic"/> <!-- this contains the element that the filter is applied to -->
</feMerge>
</filter>
<path
id="map_canvas"
style="filter:url(#dropshadow)"
<path //lots of lines of code for the path />
</svg>
Possible solutions you can try:
Use an SVG <foreignObject> with a <clipPath> or <mask>. I am not sure how well this will work though.
Use a CSS Mask (http://caniuse.com/#feat=css-masks).
Create a maps Polygon that has the same colour as the background and which is the size of the map and has a hole the shape of your mask.
Cover the map with an <img> (eg. PNG) that has the same colour or texture as the background and which has a hole the shape of your mask.

How to get hammer.js to work with svg files without using jquery?

I am trying to implement the hammer.js with svg files and without using any jquery. I'm trying to use the sample code from the hammer.js site {https://github.com/EightMedia/hammer.js/wiki/Getting-Started}. I have the external javascripts called like this.
<script src="javascript/hammer.js" type="text/javascript"></script>
My javascript is as follows:
<script type="text/javascript">
//<![CDATA[
var element = document.getElementById("testsvg");
var hammertime = Hammer(element).on('doubletap', function(event){
alert("doubletap!");
return false;
}
);
//]]>
</script>
My svg looks like the following.
<svg version="1.1" id="testsvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="585px" height="230" viewBox="0 0 585 230" enable-background="new 0 0 585 230" xml:space="preserve">
<rect x="10" y="10" height="210" width="565" style="stroke:#006600; fill: #00cc00"/>
</svg>
Starting out, I'm just trying to get any detection to work. I do not get any alert when I double tap. I have also tried to implement this with the hammer.fakemultitouch.js plugin on my desktop. Neither the desktop or touch environment do anything.
Anyone have any idea what I might be doing wrongly?
Thanks,
--christopher
First make sure hammer.js is loading correctly. If it is, then you are most likely executing the javascript before the DOM is loaded. The easiest way to fix this is to place your <script> right before the closing </body> tag (near the bottom of your html file). You can also wrap your code in a load event function such as...
window.onload = function(){
var element = document.getElementById("testsvg");
var hammertime = Hammer(element).on('doubletap', function(event){
alert("doubletap!");
return false;
});
}

Snap.load() external SVG fails to Load

PROBLEM:
I'm using Snap.svg to create some basic interactive graphics, but for some reason I can't get my external SVG file to load using Snap.load(). I've pulled code straight from the tutorial at snap.io and checked and double-checked the docs. My SVG file renders in the browser fine, it just doesn't display inside the Snap SVG. Other shapes (i.e. not pulled in using Snap.load() ) do display.
CODE:
I've boiled my example down to the most simple HTML and SVG files imaginable, and the Snap.load() method still isn't working for me. Does anyone see what I'm missing?
HTML:
<head>
<style media="screen">
#svg {
width: 300px;
height: 300px;
}
</style>
<script src="snap.svg-min.js"></script>
<meta charset=utf-8 />
</head>
<body>
<svg id="svg"></svg>
<script type="text/javascript">
var s = Snap("#svg");
Snap.load("svgtest.svg");
</script>
</body>
SVG (originally exported from Illustrator):
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<rect x="14" y="33" fill="#2BB673" width="70" height="30"/>
</svg>
UPDATE:
Updated the code as per #Ian's suggestion -
var s = Snap("#svg");
Snap.load("http://www.w3.org/TR/SVG/images/struct/Use01.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}
- but still no display of external SVG. I tried using an SVG from w3.org just to be sure it wan't a problem with the file itself or my domain.
The load function takes a callback, as loading can take some time. So I think you would do something like the following...
var s = Snap("#svg");
Snap.load("svgtest.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}
Edit: There may be some access control issues if not accessing from the same server as the script, check the console log for any errors.
I was having exactly this problem in Internet Explorer only, and it turned out to be because the SVG file I was loading in was a minified one from which the doctype had been removed. Other browsers were ok without the doctype, but leaving the doctype in fixed the problem in IE as well:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
In case, like me, you're using Grunt to minify SVGs, you can leave the doctype in by adding the following option to your Gruntfile:
svgmin: {
options: {
plugins: [
{ removeDoctype: false }
]
}
// etc...
}
There is a small bug in the distribution - see https://github.com/adobe-webplatform/Snap.svg/issues/196. The suggested fix works correctly. The online demo works because it is referencing a much older build of the library.
With version 0.5.1 installed. The code in the correct answer above needs to be re-written as follows to work:
var s = Snap();
Snap.load("svgtest.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}

Categories