Making a D3 widget scrollable - javascript

I'm sticking a D3 tree widget into my web app. It grows children and appends them to the tree. However, when the tree gets to be too big, it starts to go off the page. That's fine since I don't want to the individual tree nodes to get too small, but it would be nice if I could add a scroll bar. However, I've tried doing it the normal way, overflow: auto, but it doesn't work. Maybe it's something to do with the D3 svg stuff.
Here's the code for a tree with 2 nodes:
<div id="Graph">
<svg width="100%" height="10%" id="SVG" overflow="auto" display="block">
<g transform="translate(40,0)">
<path class="link" d="M0,20C213.75,20 213.75,20 427.5,20"></path>
<g class="node" transform="translate(427.5,20)">
<circle r="4.5" style="fill: rgb(255, 255, 255);"></circle>
<text x="10" dy=".35em" text-anchor="start" style="fill-opacity: 1;">1</text>
</g>
<g class="node" transform="translate(0,20)">
<circle r="4.5" style="fill: rgb(255, 255, 255);"></circle>
<text x="-10" dy=".35em" text-anchor="end" style="fill-opacity: 1;">0</text>
</g>
</g>
</svg>
</div>
Once it gets to be more than around 10 or 11 nodes, it goes off the screen. How can I fix this?

Make the width of the svg element > 100%. That will overflow the div and the div will be scrollable. You might also need to set the overflow style to scroll on the <div>

Related

How can I apply a pattern to an SVG element that ignores the element's transform values?

I have a JavaScript application that modifies an inline SVG. I have multiple elements within the SVG that all need to have the same background image applied to them. Elements (paths) are positioned in the SVG via transform attributes. Presently I am using a pattern fill on the elements. Is there any way to achieve the effect of the pattern staying stationary irrespective to element transforms?
Currently I have this:
I want this:
(note: I hard-baked the path in the second photo, which can't be used in the application)
Edit:
The patterns are currently applied like so:
<defs>
<pattern id="metallicgold" x="0" y="0" width="1240" height="775" patternUnits="userSpaceOnUse">
<image xlink:href="img/gold-texture.png" />
</pattern>
</defs>
The transforms on elements look like this:
<path transform="translate(-445.0000396775016 -1950.3326958481455) rotate(317.2309439443859 2926.326416015625 2926.32666015625) scale(1 1)" style="fill: url('#metallicgold'); stroke: none;" d="M1951.326416015625,1951.32666015625L3901.326416015625,1951.32666015625L3901.326416015625,3901.32666015625L1951.326416015625,3901.32666015625L1951.326416015625,1951.32666015625Z" x="0" y="0"></path>
If you want a constant background as you transform shapes, you should consider using a filter with userSpaceOnUse filterUnits, unless the transforms are easy and apply to all elements filled, in which case, you can use patternTransform on the pattern to reverse the transform on the elements.
<svg width="800px" height="600px" viewBox="0 0 4000 4000">
<defs>
<filter id="brick" x="0" y="0" width="4000" height="4000" filterUnits="userSpaceOnUse">
<feImage xlink:href="https://s-media-cache-ak0.pinimg.com/originals/c9/97/81/c99781a0ab356681cb038f70b1df68f1.jpg" x="0" y="0" width="4000" height="4000" preserveAspectRatio="xMinYMin meet"/>
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
</defs>
<g filter="url(#brick)">
<path transform="translate(-445.00 -1950.33) rotate(317.23 2926.32 2926.32) scale(1 1)" stroke="none" fill="red" d="M1951.326416015625,1951.32666015625L3901.326416015625,1951.32666015625L3901.326416015625,3901.32666015625L1951.326416015625,3901.32666015625L1951.326416015625,1951.32666015625Z" x="0" y="0"></path>
</g>
<rect x="1250" y="500" width="300" height="300" fill="blue"/>
<g filter="url(#brick)">
<circle cx="1000" cy="1000" r="500"/>
</g>
</svg>

SVG elements disappear after dynamic updates in Edge

This issue does not affect Chrome, but is consistent in Edge and Internet Explorer.
I have two svg's defined in my .cshtml:
<div class="row" style="height: 100%;">
<div class="col-sm-1" style="height:inherit;">
<div class="card" style="height:100%">
<svg id="bayLegendSVG" viewBox="0 0 112 900" height="100%" width="100%" style="display:block; margin: auto;">
<g>
<g name="Empty" style="display:none">
<text x="56" y="256" text-anchor="middle">Not Selected</text>
<circle class="zoom" cx="56" cy="300" r="31" stroke="lightgrey" stroke-width="12" fill="white"></circle>
<text name="count" x="56" y="305" text-anchor="middle">81</text>
</g>
<g name="Selected" style="display:none">
<text x="56" y="556" text-anchor="middle">Selected</text>
<circle class="zoom" cx="56" cy="600" r="31" stroke="orange" stroke-width="12" fill="white"></circle>
<text name="count" x="56" y="605" text-anchor="middle">0</text>
</g>
</g>
<additional g's...>
</svg>
</div>
</div>
<div class="col-sm-7" style="height: inherit;">
<div class="card" style="height:100%;">
<svg id="baySVG" viewBox="0 0 788 900" height="100%" width="100%" style="display:block; margin: auto;" >
<g name="bayText">
<circle cx="384" cy="6200" r="6170" stroke="darkgrey" stroke-width="1" fill="none" />
<text x="353" y="20">Top Label</text>
</g>
<g name="bayText">
<circle cx="384" cy="6200" r="5340" stroke="darkgrey" stroke-width="1" fill="none" />
<text x="334" y="885">Bottom Label</text>
</g>
<lots of additional g's...>
</svg>
</div>
<div>
I am making changes to these elements from JavaScript (showing/hiding certain elements, changing colors, changing text, etc.) based on user selections.
The issue is that some or all of the elements in the SVG will not be displayed after user interactions, even interactions that do not initiate dynamic changes to elements. The html for the svg is there, and it is not set to hidden (proof is that it always works in Chrome). And to make everything appear as intended, all that I need to do is resize the browser or even just click anywhere on the SVG (everything immediately appears).
I am fairly new to svg's and love everything they have provided...except for this.
Edit: The issue seems to occur when the height of the page changes (from either hiding or showing divs to the right of the content I have posted). It does not change the height of the SVGs, as thy are set when the page is created. The area to the right changes and is scrollable.
I am wondering if it has something to do with using the collapse hide/show and there being some issue with animation happening after the SVG content has been updated.
Sorry but edge / internet explorer is not a good browser he not support few class css/svg.. is normal , use chrome.

How to append div tag into a SVG rect element?

I couldn't find a correct solution for this problem so I decided to write a new question.
I'm not even sure that this is possible but I hope it is.
So here is my HTML that the browser provides. I'm copying it from the "Elements" tab in the browser.
<svg width="960" height="728" style="margin-left: 0px;">
<g transform="translate(0,24)" style="shape-rendering: crispEdges;">
<g class="depth">
<g>
<g>
<rect class="child" x="0" y="0" width="960" height="704" style="fill: rgb(192, 192, 192);">1.1.1.
<div class="jstree">
<div>TestContent</div>
</div>
</rect>
</g>
</g>
</g>
</g>
(I'm creating everything with JS).
My problem is that I'm creating this div inside the rect tag, but this div and its content doesn't appear on the screen inside the rectangle.
I want to know if it is possible to make it appear and if it is how ?
Unfortunately, it's not possible: you cannot append an HTML element to an SVG element.
The only way for using a div (or a p, h1, li etc) in an SVG is by using foreignObject. In your code, something like this:
<svg width="960" height="728" style="margin-left: 0px;">
<g transform="translate(0,24)" style="shape-rendering: crispEdges;">
<g class="depth">
<g>
<g>
<rect class="child" x="0" y="0" width="960" height="704" style="fill: rgb(192, 192, 192);">
</rect>
<foreignObject x="100" y="100" width="100" height="100">
<div xmlns="http://www.w3.org/1999/xhtml" class="jstree">
<div>TestContent</div>
</div>
</foreignObject>
</g>
</g>
</g>
</g>
Notice that foreignObject comes after the rectangle, not inside it (as in your code). Also, notice that foreignObject does not work in IE: https://developer.mozilla.org/en/docs/Web/SVG/Element/foreignObject

D3.js Text on path not rendered (no height / width)

I am trying to render circles which have a text inside, that runs along a given path.
The markup d3 produces looks fine, but Chrome is not showing the texts.
Upon inspection it says text elements have 0 width and 0 height.
This is sample markup including only two circles:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 950 600">
<g>
<g transform="translate(334.14792673070184,58.96385042366173)">
<defs>
<path id="path-1" d="m5,50 a45,45 0 0 0 90,0"></path>
</defs>
<circle class="circle" fill="#ccc" cx="50" cy="50" r="50"></circle>
<text fill="#333" font-size="15px">
<textpath xlink:href="#path-1" start-offset="0%">123456</textpath>
</text>
<use xlink:href="#path-1" fill="#666" opacity="0.1"></use>
</g>
</g>
<g transform="translate(374.66047394649974,371.7948729806046)">
<defs>
<path id="path-2" d="m5,50 a45,45 0 0 0 90,0"></path>
</defs>
<circle class="circle" fill="#ccc" cx="50" cy="50" r="50"></circle>
<text fill="#333" font-size="15px">
<textpath xlink:href="#path-2" start-offset="0%">123456</textpath>
</text>
<use xlink:href="#path-2" fill="#666" opacity="0.1"></use>
</g>
</svg>
When I inspect the markup in Chrome console and click "Edit as HTML" on the SVG element, make a random change, save & exit - the SVG suddenly renders correctly.
The exact same thing happens in Firefox and Opera.
Copy pasting the generated markup into a jsfiddle renders everything as expected.
I have tried pulling the < defs > tags out of each individual group into a single global < defs > but it did not solve the problem.
I have also looked at user-agent-stylesheet and other CSS rules that might interfere with rendering.
Is this a problem with how the SVG tag is included and/or the container element's width/height properties? I have been trying different things to fix this for a couple of hours now...
Here is the full SVG markup http://pastebin.com/J2Lz8p23
Here are the relevant parts in my code http://pastebin.com/Bym8kJVN

Is it possible to extend the height and width of a child element beyond its container?

I have a zoomable svg that's provided by 3rd a party API. It's basically a drawing that's mapped to a grid. The problem is the API doesn't include the grid in the provided svg file so I have to hack it to include one. Basically, the markup is like this:
<svg>
<g>
<line>....
<rect>....
etc...
</g>
</svg>
The zoom functionality is done and now I'd like to add the grid. I'm thinking I should add it like so:
<svg>
<g>
<rect x="0" y="0" width="100%" height="100%" fill="black" />
<defs>
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 1 1 L 0 0 0 0" fill="none" stroke="green" stroke-width="1" />
</pattern>
</defs>
<rect x="-100%" y="-100%" width="200%" height="200%" fill="url(#grid)" />
<line>....
<rect>....
etc...
</g>
</svg>
The grid is drawn but it's bound within the <g> tag. Is it possible to extend the grid beyond it but still zoomable? Or are there other better ways to achieve this?

Categories