How to use svg in Vue standalone script without build step - javascript
I'm trying to use Vue as a standalone script in an HTML file, but it's causing my inline svg icons to just become solid filled squares. I've tried both Vue 2 and Vue 3 as standalone scripts and both give the same behavior.
Although I've found solutions to Vue's svg issues that involve webpack loader configuration, I'm looking for a way to resovle the svg issues without any build step and only using Vue as a standalone script.
Note that the icon svg is copied directly from Carbon Design Icons
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<script src="https://unpkg.com/vue#3"></script>
</head>
<body>
<div id="app">
{{message}}
<svg
id="icon"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<defs>
<style>
.cls-1 {
fill: none;
}
</style>
</defs>
<path
d="M16,8a5,5,0,1,0,5,5A5,5,0,0,0,16,8Zm0,8a3,3,0,1,1,3-3A3.0034,3.0034,0,0,1,16,16Z"
/>
<path
d="M16,2A14,14,0,1,0,30,16,14.0158,14.0158,0,0,0,16,2ZM10,26.3765V25a3.0033,3.0033,0,0,1,3-3h6a3.0033,3.0033,0,0,1,3,3v1.3765a11.8989,11.8989,0,0,1-12,0Zm13.9925-1.4507A5.0016,5.0016,0,0,0,19,20H13a5.0016,5.0016,0,0,0-4.9925,4.9258,12,12,0,1,1,15.985,0Z"
/>
<rect
id="_Transparent_Rectangle_"
data-name="<Transparent Rectangle>"
class="cls-1"
width="32"
height="32"
/>
</svg>
</div>
<div>
Icon outside of Vue
<svg
id="icon2"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<defs>
<style>
.cls-2 {
fill: none;
}
</style>
</defs>
<path
d="M16,8a5,5,0,1,0,5,5A5,5,0,0,0,16,8Zm0,8a3,3,0,1,1,3-3A3.0034,3.0034,0,0,1,16,16Z"
/>
<path
d="M16,2A14,14,0,1,0,30,16,14.0158,14.0158,0,0,0,16,2ZM10,26.3765V25a3.0033,3.0033,0,0,1,3-3h6a3.0033,3.0033,0,0,1,3,3v1.3765a11.8989,11.8989,0,0,1-12,0Zm13.9925-1.4507A5.0016,5.0016,0,0,0,19,20H13a5.0016,5.0016,0,0,0-4.9925,4.9258,12,12,0,1,1,15.985,0Z"
/>
<rect
id="_Transparent_Rectangle_"
data-name="<Transparent Rectangle>"
class="cls-2"
width="32"
height="32"
/>
</svg>
</div>
</body>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
message: "Hello Vue!"
};
}
}).mount("#app");
</script>
</html>
https://codesandbox.io/s/wonderful-albattani-dxkvdt?file=/index.html:0-2221
change fill:none to fill:transparent
This ended up not being a Vue issue, but a problem in the SVG code copied from an icon library. Estus Flask spotted that the style tag inside the SVG defs was likely the problem because it can cause inconsistent behavior in different scenarios, such as whether or not the inline svg style is contained within a div managed by Vue. The solution was moving that style class to a separate stylesheet.
Related
SVG filter updates by javascript not consistent across browsers
I'm trying to modify the filter of an svg object through javascript. Mouse over should make the grey shadow turn red. Problem is that Chrome and Safari don't have any effect, but Firefox does. I was able to get Safari to do the right thing when I single stepped through the Javascript debugger, so I worry it might be a timing thing with the webkit that is out of my control. My goal is to find a solution that allows a filter to be updated in javascript by all 3 browsers. Safari 11.1, Chrome 65.0.3325.181, Firefox 59.0.2 <!DOCTYPE html> <html> <head> </head> <body> <svg width="250" height="150"> <defs> <filter id=glow x="-50%" y="-50%" width="200%" height="200%"> <feDropShadow dx=2 dy=2 stdDeviation=2 flood-color="#F00" /> </filter> <filter id=shadow x="-50%" y="-50%" width="200%" height="200%"> <feDropShadow dx=2 dy=2 stdDeviation=2 flood-color="#888" /> </filter> </defs> <g style="filter: url(#shadow)"> <rect x=50 y=50 width=50 height=50 style="fill: yellow" onmouseover="this.parentNode.style.filter = 'url(#glow)'" onmouseout="this.parentNode.style.filter = 'url(#shadow)'" /> </g> <g style="filter: url(#shadow)"> <rect x=150 y=50 width=50 height=50 style="fill: green" onmouseover="this.parentNode.style.filter = 'url(#glow)'" onmouseout="this.parentNode.style.filter = 'url(#shadow)'" /> </g> </svg> </body> </html> Associated Codepen: https://codepen.io/anon/pen/yjeXMJ?editors=1000
If you remove the .parent selector: onmouseover="this.style.filter = 'url(#glow)'" it works on chrome. hope it helps.
Export style with <svg> to .svg
I have an HTML file, that has a link to export all the <svg> inside to one .SVG. That's perfect, it's what I need and the community helped me a lot. Now I have a problem that all the SVG inside the file, are clogged on top of each other. I need them to keep the same 'display' they have on the webpage. I tried using internal, inline and external style... But nothing worked. The X and Y I have in the <svg> is executed when I open the .SVG file in any program, but it doesn't affect anything on the HTML document. I'm using the svg-converter.js to get all the .svg inside the <img> and convert to <svg>. For some reason, inside that JS, something don't let me group all the <svg> inside another <svg>, only inside <div>. I have no idea if that is somehow causing the problem of the style not being exported. Here is the working link. Any help will be much appreciated. Ps: I'd love to know why my question is downvoted.
You need to use x and y attributes to arrange your inner <svg> elements inside your root <svg> element. Something like this (I've replaced the SVG contents with circles for brevity): <svg xmlns="http://www.w3.org/3000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 1224 1224"> <svg x="0" y="0" width="50%" height="50%" viewBox="0 0 612 612"> <circle fill="#7AB344" cx="306" cy="306" r="250"/> </svg> <svg x="50%" y="0" width="50%" height="50%" viewBox="0 0 612 612"> <circle fill="#8DD4F0" cx="306" cy="306" r="250"/> </svg> <svg x="0" y="50%" width="50%" height="50%" viewBox="0 0 612 612"> <circle fill="orange" cx="306" cy="306" r="250"/> </svg> <svg x="50%" y="50%" width="50%" height="50%" viewBox="0 0 612 612"> <circle fill="rebeccapurple" cx="306" cy="306" r="250"/> </svg> </svg>
THIS IS THE FINAL WORKING CODE: <!DOCTYPE html> <html xmlns="http://www.w3.org/3000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <head> <meta charset="UTF-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://brand.express/projects/teste/svg-converter.js"></script> </head> <body> <main id="content"> <div id="mySVG" style="width:100%;padding:0;margin:0;"> <img src='img/leafers-sapling.svg' class='svg-convert' x="0" y="0" width="286px"> <img src='img/aqualine-sapling.svg' class='svg-convert' x="286px" y="0" width="286px"> <img src='img/leafers-sapling.svg' class='svg-convert' x="572px" y="0" width="286px"> <img src='img/aqualine-sapling.svg' class='svg-convert' x="858px" y="0" width="286px"> </div> </main> <script> //transforma os .svg para <svg> jQuery(document).ready(function($) { $('.svg-convert').svgConvert({ onComplete: function() { exportSVG(document.getElementById('mySVG')); }, svgCleanupAttr: [] }); }); </script> <script> var exportSVG = function(divContainer) { var svgContainer = document.createElementNS("http://www.w3.org/1999/xhtml", "svg"); svgContainer.setAttribute('width','1200px'); $('#mySVG').find("svg").clone().appendTo(svgContainer); var svgData = svgContainer.outerHTML; var a = document.createElement('a'); a.href = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData); a.download = 'finalSVG.svg'; a.innerHTML = 'download the .SVG file'; document.body.appendChild(a); }; </script> </body> </html>
Displaying and changing an external SVG background image
I'm trying to display and an external image inside an svg and then change it on button click. I can't get the background to show nor can I get it to change. here is my fiddle: https://jsfiddle.net/bsp9601z/ <head><meta http-equiv="X-UA-Compatible" content="IE=edge"> </head> <div id="slider"></div> <button onclick="go()">change background</button> <g id="backgroundImage"> <image width="100%" height="100%" xlink:href="http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg" /></g> <svg width="792pt" height="612pt" viewBox="0 0 792 612" enable-background="new 0 0 792 612" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" > </svg> </svg> function go(){ var im = document.getElementById('backgroundImage'); im.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://demo.elmanawy.info/moraco/layout1/assets/images/portfolio/8.jpg'); im.setAttributeNS('http://www.w3.org/1999/xlink','width', "100%"); im.setAttributeNS('http://www.w3.org/1999/xlink','height', "100%"); }
You are missing <svg> tags and selecting <g> rather than <image> <button onclick="go()">change background</button> <svg> <g id="backgroundImage"> <image width="100%" height="100%" xlink:href="http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg" /> </g> </svg> <script> function go() { var im = document.getElementById('backgroundImage').querySelector("image"); im.setAttributeNS('http://www.w3.org/1999/xlink' , 'xlink:href' , 'http://demo.elmanawy.info/moraco/layout1/assets/images/portfolio/8.jpg'); } </script>
Click events stop working after replacing attribute of <use> element in <svg> (Win7/IE11)
We are using multiple svg symbols for displaying icons. <!-- defining them at the start of the page --> <div id="icon-container"> <svg xmlns="http://www.w3.org/2000/svg"> <symbol xmlns="http://www.w3.org/2000/svg" id="rect" ...> <rect... /> </symbol> <symbol xmlns="http://www.w3.org/2000/svg" id="circle" ...> <circle... /> </symbol> </svg> </div> <!-- using them in the page somewhere --> <svg> <use xlink:href="#rect"></use> </svg> In some cases we need to replace them later on with another icon (like on a collapse control), therefore I created a little helper function to change the xlink:href to the new symbol name. $.fn.replaceSVGIcon = function(id) { $(this).find('svg') .andSelf() .filter('svg') .find('use') .attr('xlink:href', '#' + id); } This works in every browser except for IE10 + IE11 on Windows 7 (but weirdly enough it works with Windows 8). When you open the snippet below in IE11 and click on the red box everything is fine, but as soon as you start clicking on the element within, it breaks the whole page after the icon is changed for the first time. (function($){ $.fn.replaceSVGIcon = function(id) { $(this).find('svg').andSelf().filter('svg').find('use').attr('xlink:href', '#' + id); } })(jQuery); clickFunction = function() { var $elem = $('#icon'); if ($elem.find('use').attr('xlink:href') == '#rect') { $elem.replaceSVGIcon('circle'); } else { $elem.replaceSVGIcon('rect'); } }; #icon-container { visibility: collapse; display: none; } #icon { height: 40px; width: 40px; fill: #454545; cursor: pointer; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="icon-container"> <svg xmlns="http://www.w3.org/2000/svg"> <symbol xmlns="http://www.w3.org/2000/svg" id="rect" viewBox="0 0 50 50"> <rect x="15" y="15" width="20" height="20"></rect> </symbol> <symbol xmlns="http://www.w3.org/2000/svg" id="circle" viewBox="0 0 50 50"> <circle cx="25" cy="25" r="10"></circle> </symbol> </svg> </div> <svg id="icon" onclick="clickFunction()"> <rect fill="red" height="40" width="40"></rect> <use xlink:href="#rect"></use> </svg> Why is this happening and is this a known Internet Explorer bug? What are my options to work around this issue?
Yes, this is a known IE bug. https://connect.microsoft.com/IE/feedback/details/796745/mouse-events-are-not-delivered-at-all-anymore-when-inside-an-svg-a-use-is-removed-from-the-dom If you can, you should set pointer-events: none; for the use tag in your CSS. It's crazy, but it should work.
jQM single page app ignores SVG markers
I´ve got a problem combining SVG elements and jQM single page applications. Starting on my first page of the jQM single page application (index.html), I can draw an arrow with the following code: <html> <head> <link rel="stylesheet" href="jQueryMobile/jquery.mobile-1.4.2.css" /> <link rel="stylesheet" href="themes/jquery.mobile.icons.min.css" /> <script type="text/javascript" src="jQueryMobile/jquery-2.1.1.js"></script> <script type="text/javascript" src="jQueryMobile/jquery.mobile-1.4.2.js"></script> </head> <body> <!--MainPage--> <div data-role="page" id="Index"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="90%" style="margin: 1em;" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"> <defs> <marker id="MyMarker" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto"> <path d="M2,2 L2,11 L10,6 L2,2" style="fill: black;" /> </marker> </defs> <line x1="5" y1="5" x2="10" y2="10" stroke="black" stroke-width="1" style="marker-end: url(#MyMarker);"/> </svg> </div> </body> The user can navigate to another page (anotherpage.html) by: $.mobile.changePage("content/anotherpage.html", { transition: "flow", changeHash: false }); anotherpage.html looks like this: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <div data-role="page" id="AnotherPage"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="90%" style="margin: 1em;" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"> <defs> <marker id="MyMarker2" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto"> <path d="M2,2 L2,11 L10,6 L2,2" style="fill: black;" /> </marker> </defs> <line x1="5" y1="5" x2="10" y2="10" stroke="black" stroke-width="1" style="marker-end: url(#MyMarker2);"/> </svg> </div> </body> </html> Opening the page directly shows the arrow as expected. But after navigating from index.html to this page the marker of the svg is not displayed and I don´t know why. I tested all kind of different combinations and SVG marker examples I found but it seems that by navigating via jQM to the second page markers a generally ignored. I found this link about Using base tag on a page that contains.... Tried the following with no success: <line x1='5' y1='5' x2='20' y2='20' stroke='black' stroke-width='1' style='marker-end: url(#MyMarker2);'/> <line x1='5' y1='5' x2='30' y2='20' stroke='black' stroke-width='1' style='marker-end: url(Test_de.html#MyMarker2);'/> <line x1='5' y1='5' x2='20' y2='30' stroke='black' stroke-width='1' style='marker-end: url(content/Test_de.html#MyMarker2);'/> <line x1='5' y1='5' x2='10' y2='20' stroke='black' stroke-width='1' style='marker-end: url(./content/Test_de.html#MyMarker2);'/> Also tried adding the marker programmatically with full path. Tested it on Chrome. It always says marker-end is none on the computed properties listed in the developer tools. I hope someone can help. Thank you. Edit: Sorry. Solved the problem by myself. Problem was the option "changeHash: false" for the page transition.