I have a rather large tree diagram modeled in SVG.
It renders well, with vertical scrolling as desired, in IE-9.
In Chrome and Firefox, not so. No scrolling in Chrome but zooming out lets me see a little more.
In Firefox, it is only showing a token amount of the vertical space.
I assume I am missing some attributes in the "svg" element to make it show up correctly in Chrome/Firefox but not sure what.
Here is how the doc source starts:
<!DOCTYPE html>
<html>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100%" width="100%" style="overflow-x: auto; overflow-y: auto;" >
<rect x="685" y="15" rx="10" ry="10" width="380" height="116" style="fill:lightgrey;stroke-width:5;stroke:rgb(0,0,0)" />
<text x="777" y="38" fill="black" font-size = "18" font-family = "sans-serif" font-weight="bold">Folder</text>
<text x="960" y="38" fill="black" font-size = "18" font-family = "sans-serif" font-weight="bold">Content</text>
<rect x="700" y="45" rx="10" ry="10" width="200" height="75" style="fill:powderblue;stroke-width:1;stroke:rgb(0,0,0)" />
................... and so on for 150000 lines ...................
Any ideas on what can be added so it will render in Chrome/Firefox as it does in IE-9?
Hard coding values into "height" and "width" solved the acute problem of no scrolling in Chrome and Firefox.
Making the script that generates the svg smarter to put in appropriate values for "height" and "width" is a better solution but for now, just setting
height="50000" width="2400"
instead of using the % values, worked for me.
Related
I'm trying to construct a buttons collection for a website. Since the buttons share several properties (colours and effects) I've decided to use SVG. In order to reduce the HTTP requests, I tried to nest several elements and filters inside the same SVG file. The idea is instantiate these elements to construct all the buttons, toggle switches, etc by simply using the <use> tag.
After reading great articles like this, this, and this I'm still not being able to do such thing. I found myself stuck. So I decided to simplify the problem as much as I could within the snippet down bellow.
<style>
svg,
img,
object {
width: 50px;
height: 50px;
border: 1px solid black;
}
h3 {
margin-top: 50px;
}
</style>
<h1>Swimming Veggies. The SVG club that's driving me nuts.</h1>
<h3>This is an inline SVG.</h3>
<svg viewBox="0 0 50 50">
<g id="pool">
<rect width="50" height="50" fill="aqua" />
</g>
<symbol id="tomato">
<circle cx="35" cy="35" r="10" fill="tomato" />
</symbol>
<g id="orange">
<circle cx="15" cy="15" r="12" fill="orange" />
</g>
</svg>
<p>Things work as expected here. The <g> elements #pool and #orange show up while the <symbol id="tomato"> doesn't. Great!</p>
<h3>This is a SVG using <use> to referencing elements from the inline SVG above.</h3>
<svg style="border: 1px solid black;" width="50" height="50">
<use xlink:href="#pool"></use>
<use xlink:href="#tomato"></use>
</svg>
<p>Note that the <symbol id="tomato"> element shows up here like the g elemet "pool". The "orange" element is NOT being <use>d. Works fine. Expected behaviour.</p>
<h3>This is a SVG being put as an IMG.</h3>
<img src="club.svg">
<p>Works fine to me and the absence of the <symbol id="tomato"> is the expeted behaviour. I don't want to use SVG this way though.</p>
<p> Unfortunately, IMGUR didn't accept SVGs and I didn't find an image sharing platform that accepts SVG files. The "club.svg" file has the same content as the commented code at the end of this HTML snippet. The SVG file is located ON THE SAME FOLDER of the HTML file. Sorry for the inconvenience :(</p>
<h3>This is a SVG being put as an OBJECT</h3>
<object type="image/svg+xml" data="club.svg"></object>
<p>This works as expected.</p>
<p>Again, the "club.svg" file content is shown as a comment inside and at the end of this HTML snippet.</p>
<h3>An unsuccessful attempt to extract elements from an OBJECT SVG </h3>
<object type="image/svg+xml" data="club.svg#tomato"></object>
<p>The browser is ignoring the "#tomato" after the file name. Is it possible to extract/manipulate elements inside the SVG file this way? If so, how?</p>
<h3>This is a SVG being put as an external reference.</h3>
<svg>
<use xlink:href="club.svg#pool"></use>
<use xlink:href="club.svg#tomato"></use>
<use xlink:href="club.svg#orange"></use>
</svg>
<p>That would be my preferable way to clone/manipulate elements from an external source (in this case, "club.svg"). Unfortunately, it's not working for me. It's not clonning the element. What am I doing wrong?</p>
<h3>Here goes the club.svg content (it's commented inside the snippet).</h3>
<!--
Down bellow is the code inside the club.svg file:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50">
<g id="pool">
<rect width="50" height="50" fill="aqua" />
</g>
<symbol id="tomato">
<circle cx="35" cy="35" r="10" fill="tomato" />
</symbol>
<g id="orange">
<circle cx="15" cy="15" r="12" fill="orange" />
</g>
</svg>
-->
By the way... I tried to open up the file on Brave, Opera, Chrome and Safari. All of them show the same results.
Any help will be very much appreciated.
I'm trying to use external svg file to link particular element from svg stack to "background-image"/"content" of the button element using #fragment identifier.
i.e.:
Button1 - background-image: url(icons.svg#fragment1);
Button2 - background-image: url(icons.svg#fragment2);
External icons.svg consists tons of fragments and pretty big.
Everything works perfectly in all browsers. However for each button that needs only one particular fragment it loads whole svg. At the end, having (let's say) 10 buttons, I've got 10 loaded instances of the whole svg.
An ideal solution (IMHO) would be to use the tag "use" with "inlined" SVG but as far as I know such combination wont work.
Using URI encoded fragments not a solution for my particular case.
What would be the best approach?
You can avoid using a background image if you use the svg as a child of your button element.
To use different icons for different states, you can add multiple icons and only make them visible depending on the state of the button.
button:hover use.hover,
button:active use.active {
display: inline;
}
button use:not(.default),
button:hover use.default,
button:active use.default,
button:active use.hover {
display: none;
}
<!-- inline your icons -->
<svg display="none">
<symbol id="icon1" viewBox="0 0 30 20">
<ellipse cx="15" cy="10" rx="15" ry="10" />
</symbol>
<symbol id="icon2" viewBox="0 0 30 20">
<rect x="5" y="5" width="20" height="10" />
</symbol>
<symbol id="icon3" viewBox="0 0 30 20">
<path d="M7,17H23L15,3z" />
</symbol>
</svg>
<button style="width:80px;height:30px;">
<svg width="100%" height="100%">
<use class="default" href="#icon1" />
<use class="hover" href="#icon2" />
<use class="active" href="#icon3" />
</svg>
</button>
For a website, I'm trying to add a mask to a processing.js canvas. In Chrome it works, I have a responsive mask using SVG. But in Firefox all my canvas disapears. I know that the were problems with clipping mask in Firefox, but as I understood it's now OK to use clipping mask on FF. So I don't know were is the probleme.
Here is my code :
HTML :
<canvas class=" processing-intro" data-processing-sources="intro.pde"></canvas>
<div class="svg-container">
<svg width="100%" >
<defs>
<clipPath id="clipping" >
<rect class="col-12 rect-cache" width="1280" height="35vw" />
</clipPath>
</defs>
</svg>
</div>
CSS :
.processing-intro{
clip-path: url(#clipping);
}
Any ideas ? Thank you !
I need to make text automatically stretch in both dimensions, to fill a container. It will distort.
This shows the the container space in red
This shows what a long name would normally resize to put in that space and maintaining aspect ratio
.
This shows what my client wants to happen
.
I would prefer to use SVG but I will work with what works.
I have searched for a solution to the best of my abilities but all seem to either refer to maintaining aspect ratio or stretching text when the page or viewbox changes dimensions.
That's quite a broad question, but yes you can do it with svg, I'll let you implement it though since you didn't provided anything to chew on.
The key point is to set your svg's preserveAspectRatio to "none":
svg{
height: 100vh;
width: 50vw;
}
body{
margin:0;
}
<div>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 300 40" preserveAspectRatio="none">
<text x="0" y="35" font-family="Verdana" font-size="35">
Hello, out there
</text>
</svg>
</div>
If your text is already part of an SVG (as it appears in your example), you will probably need to use a nested <svg> element.
<svg width="400" height="400">
<rect width="400" height="400" fill="rebeccapurple"/>
<!-- rect representing area that our text has to squeeze into -->
<rect x="20" y="50" width="200" height="50" fill="white"/>
<!-- x y width height match above rect -->
<!-- viewBox values need to match text bounds -->
<svg x="20" y="50" width="200" height="50"
viewBox="0 8 244 28" preserveAspectRatio="none">
<text x="0" y="35" font-family="Verdana" font-size="35">
HELLO THERE
</text>
</svg>
</svg>
The hardest part is workoing out the correct values for viewBox. It needs to match the bounds of the (normal unsqueezed) text.
Is it possible to "use" a whole other svg within a separate svg? I want to use an map generated with d3 as an icon on the same page. This is what I tried but it doesn't work.
<svg id="map">
svg stuff here
</svg>
<svg id="bar">
svg stuff here
<use xlink:href="#map" height="20" width="30" ...>
</svg>
Also tried the cloning approach but ended up with an entire svg within another svg and couldn't get it to scale. eg. makeicon("#map", "#icon")
function makeicon(source, destination) {
//https://groups.google.com/forum/?fromgroups=#!topic/d3-js/-EEgqt29wmQ
var src = d3.select(source);
var dest = d3.select(destination);
if (!src.empty() && !dest.empty()) {
var newNode = d3.select(dest.node().insertBefore(src.node().cloneNode(true),
src.node().nextSibling))
.attr("id", "newnode")
.attr("width", null) // remove height and width of original svg
.attr("height", null)
.attr("viewBox", "0 0 20 30"); // try to make it smaller
return newNode;
It should work fine.
Here's a simple example that works fine in Firefox, Opera and Chrome:
http://jsfiddle.net/gew54/
Source:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type='text/css'>
svg {
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<svg id="map" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="20" fill="lime"/>
</svg>
<svg id="bar" viewBox="0 0 100 100">
<use xlink:href="#map" />
</svg>
</body>
</html>
You can use svgWeb to make it work in webkit browsers.
Considering very limited support at the moment (Gecko engines only), this can be done using the CSS 3 element() function.
The MDN docs also specifies your case as a common use case:
... A particularly useful scenario for using this would be to render an
image in an HTML <canvas> element, then use that as a
background.
Live Demo
Since SVG 2, the [ xlink:href ] attribute is deprecated in favor of [ href ].
<use xlink:href="#myId" />
Deprecated: This feature is no longer recommended. Though some
browsers might still support it, it may have already been removed from
the relevant web standards, may be in the process of being dropped, or
may only be kept for compatibility purposes. Avoid using it, and
update existing code if possible; see the compatibility table at the
bottom of this page to guide your decision. Be aware that this feature
may cease to work at any time. INFO...
<use href="#myId" />
<svg viewBox="0 0 30 10" width="300" height="100" xmlns="http://www.w3.org/2000/svg">
<circle id="myCircle" cx="5" cy="5" r="4" stroke="blue"/>
<use href="#myCircle" x="10" fill="blue"/>
<use href="#myCircle" x="20" fill="white" stroke="red"/>
<!--
stroke="red" will be ignored here, as stroke was already set on myCircle.
Most attributes (except for x, y, width, height and (xlink:)href)
do not override those set in the ancestor.
That's why the circles have different x positions, but the same stroke value.
-->
</svg>
Demo-codepen.io