How to display scrollbar in svg-pan-zoom? - javascript

I would like to know how can I enable the scrollbar while zooming with svg-pan-zoom.
I've tried overflow: auto on external div or svg tag with no luck.
Hopefully I can get some help here.

There is no way to have scrollbars by default inside of svg-pan-zoom as it's essentially an SVG, and inside of an SVG things behave like they're overflow: hidden. You'll have to implement scrollbars by yourself (render some elements that would look like scrollbars, compute their size and position...).

For anyone who comes across the problem, the best solution (hack) I've come up with is to set the container div to overflow: auto, set the svg element width and height to the width and height of the container div, set the position of the svg element to absolute, and then place a second div alongside the svg element. Then you need to synchronize size of the second div to the "true" size of the svg which you can get by calling getBBox() on the svg element, plus any scaling you have incurred by zooming. Thus the second div forces the containing div to have scroll bars. Similarly you need to synchronize the pan events with the scrollbars of the container, and vice versa.
When everything is said and done, panning and zooming happens through svg transformations that are synchronized with the scroll bars of the parent div, and happens completely transparently to the user.

Related

How to keep position of scrollbar with JavaScript?

There are a lot of pdf pages that is wrapped by div in a page. When they were zoomed by increasing div's width and height, scrollbar lose its position.
How can I fix it like this example?
As you see in the example, when you zoom anywhere in the page, scrollbar didn't lose its position and it acts as a sticky.
What is your suggestion?

How do I understand html page dimensions?

It's been a mystery for me since day one. And it still is. The time has come to reveal it. So I've made a test page, containing a div, which extents you can change. And info panel that displays values of relevant properties. Let's take just Chrome for simplicity.
Default body margin is 8px. html's background is blue, body's green, and div is of red color. And here we can see that html's offsetHeight is equal to body.offsetHeight + 2 * body.margin, as if it just envelopes body. But html.clientHeight == window.innerHeight, as if it's stretched to fill the viewport.
Now let's add horizontal scrollbar (make div's width 1000px), and scroll to the right a bit:
html and body move to the left. body's scrollLeft changes in sync with window.pageXOffset as if it owns the scrollbar. html's clientHeight changed owing to the added scrollbar.
Let's do it the other way around (vertical scrollbar):
Now both html's extents changed (offsetWidth and clientWidth). Which suggests it doesn't own the scrollbar.
And finally, with both scrollbars:
Well, at this point things are more or less clear to me. At least as long as we're only considering Chrome. But there are still a couple of things I'd like know.
How come html's clientHeight can possibly be less then offsetHeight? Is there any better explanation than "it's just so"?
Why body's scrollLeft/scrollTop changes as I scroll the page? It doesn't own the scrollbars, does it?
Also some summary would be in place.
So, there's a canvas that is displayed in a viewport (window). On the canvas we have html element, which contains body. They're mostly like divs, but have some quirks:
Along the X axis html element by default (width: auto) stretches to fit viewport. Not a quirk probably. Viewport is html's container. And as an ordinary div it by default fits container width (excluding scrollbar).
html's height is as big as to fit body element. But for some reason its clientHeight equals to viewport height minus scrollbar. As if it stretches to fit viewport along the Y axis as well.
body's scrollLeft/scrollTop properties mirror viewport's pageXOffset/pageYOffset
body's top margin doesn't collapse with html's one
body shows no signs of stretching to the bottom edge of the viewport unless you have, e.g., absolutely positioned element with bottom property being set. Judging from offsetParent value, body acts as an element, relative to which absolutely positioned elements are rendered by default (unless there are other absolutely positioned elements up the hierarchy)
With Firefox the difference is that it's html's scrollLeft/scrollTop properties that mirror viewport's pageXOffset/pageYOffset.
That all is just my interpretation of what I see. I'd be glad if someone were to correct me, or add to my findings.

Raphael Canvas parent div having resize CSS3 property doesn't work well: SVG is above canvas

I want to implement the ability to allow users to resize the SVG by just dragging it with the trigger in the lower right corner introduced with resize: both, but it is just weird:
Whenever I resize it to min-width and min-height (which is my SVG min-width and min-height) I cannot resize the SVG anymore because the trigger is not "draggable" / clickable anymore.
I tried everything: from playing around with z-index, to wrapping another div around it.
This is the status I mean:
http://puu.sh/8tIGJ.png
http://jsfiddle.net/UW7bY/
Another issue I have is that the canvas is a little higher in size than the SVG... I can only fix it by using display: flex, but that doesn't work well with resize.
Thanks in advance!

Why is drag & drop so much smoother when adding "overflow: auto"?

I am making a CMS for a website. In the CMS I want to make a drag/drop/select -able index.
Dragging and dropping on a placeholder was not really smooth. But after I added overflow: auto to the div's where you can drag/drop/select, it is way more smoother and easier to work with.
Can someone explain me why this is happening?
It only shows if you have many div's in your webpage. (Like in an almost finished website.)
This happens in Chrome and Firefox. (I didn't test it in other browsers.)
With overflow auto <-- smoother
Without overflow auto <-- It doesn't do what you want
You must think about the HTML elements. Every HTML element is wrapped within its own 'box'. For each box, you can set its CSS properties like height, width, margin, padding, and so on. Each box is designed to expand with its content, even when you give it a set height. This state is known as overflow: visible; and is the default for every element.
In your case, you are dragging elements within an element to another element. Let's break this down a little. Before we begin dragging, our element lives within another element, inheriting its properties as well. The child element will do its best to fit within the parent element. When we drag the child element, jQuery is allowing the child element to be free from the parent element, and it will no longer inherit the parent element's properties. The child element's content will now expand to its own CSS properties until you drag it into another parent element, at which point it will inherit the new parent's properties.
In the same sense that the child is affected by the parent, the parent can be affected by the child element as well. After all, its default is overflow: visible; and wants to show all the content that is contained within it. So if the parent is 100px in width and the child is 200px, the child will be visible for 100 px outside the parent's original size.
As designers want to contain our elements to a fixed size, whether it is a px value or % fraction based on the parent element, so we need a way to prevent child elements overflowing outside of our parent element. This is were CSS overflow: hidden;, scroll;, and and auto; comes into play. I do want to note that there are overflow-x and overflow-y properties, however, I won't cover them too much as they are self-explanatory. Overflow: hidden; will simply hide the content that would overflow outside the parent element. This option will give no scrollbars for the user to view the overflowed content. So Overflow: Scroll shows the scrolling bars so that the user can scroll and see hidden overflowed content within the parent element. This option will always show vertical and horizontal scrollbars. Note: This is why there are overflow-x and overflow-y properties, however with overflow: auto;, they are not necessary.
Overflow: auto; is the solution for having only the necessary scrollbars for the content, and as a bonus, if the content does not overflow, no scrollbars are shown. So when we look at your div.sortobject, without overflow: auto;, it will attempt to visually stretch out to fit it's child elements. When you begin to drag elements around, the potential parent divs are overflowing visually trying to resize both for the child element and the jQuery helper element, the element that shows the user where to drop content. Setting overflow: auto; will cause the parent element to always retain its set width and height, so that when you drag your child element, it will appear smoothly as no potential parent elements are resizing. jQuery loves to calculate current exact dimensions of the elements it affects, and will also improve the animation as well.
I hope this gave some insight.
The default value for overflow is "visible", meaning that the overflow is not clipped. It renders outside the element's box.
The value auto means that if overflow is clipped, a scroll-bar should be added to see the rest of the content.
The smoothness effect that you refer to is simple that in default overflow, rendering outside the element's box will probably be slower/jumpier than when set to auto which moves the rendering into the actual element. This was especially noticeable for me in firefox looking at your fiddle example after moving all the elements to one column then trying to move them back.
Surprisingly in IE11, there was no noticeable difference between auto/default that I could see.
Please Read: Official W3 Documentation for Visual Effects
In the overflow-auto, I noticed there is a horizontal scroll bar in some of your boxes. If you take off any overflow, the div width will expand due to the content contained within them. When you get fatter divs, you'll get mixed div widths, and can cause quirky div placements when you drag them within a parent container. Think of a bucket with fat apples and small apples, versus a bucket with apples of all the same size; the position of the apples will be scrunched up differently between the two.
Bucket of fat apples with small apples: (div width of different sizes)
If you don't believe me that the div's are fat, you made the under lay of the divs the same size, but open up your link without the overflow = auto, you'll notice your images go over the right hand side of the border.
Bucket of apples of equal size (div width of same sizes)
With overflow set to auto, if you get beyond a certain width, the scroll bar will appear, and the width of the content will flow through, not changing the width of the div; so nothing gets quirky.

SVG resizing height on window resize, also center to parent

So I've run into troubles when making my web app responsive. I've managed to make it so that the SVG adapts when the width is resized, but I've run into trouble with height.
The best solution I've come up with for height resize is the following js/jQuery code:
function updateWindow(){
var y = (($(window).height()));
svgMap.style.height=y;
}
updateWindow();
window.onresize = updateWindow;
What this does is set the SVG viewport height to equal that of the window.. This works in a sense that it centers the SVG with the browser window's height. Not so excellent, it screws up on mobile devices and adds a strange top-margin almost. It also makes the SVG slightly smaller unless I multiply "y" by some value greater than one. Doing so, however, increases the margin-top esque gap. How troublesome..
You can view the demo here:
http://zadias.me/SVG/Harrison%20Wilson/HarrisonWils.html
and the demo w/o the height center change here: http://zadias.me/SVG/Harrison%20Wilson/HarrisonWils%20-%20Copy.html
To sum things up, How does one go about centering an SVG within an <object> tag, horizontally AND vertically. Also, I would like it so that the SVG map itself fills the wrapper container.
Any help is appreciated, thanks.
EDIT: So I've given up on trying to get it to just fit the parent's height.. Instead I just wrote some JS that will prompt the user with a warning if the height is too small that it will cause overflow of the page. I also made it so that it would be styled perfectly by adding inline CSS to each page, accompanied with media queries.
If you set the SVG's width and height to 100%, ie.:
<svg width="100%" height=="100%">...
then it should just be a matter of resizing the container that the SVG is inside. The preserveAspectRatio setting of "xMidYMid meet" should then centre it vertically.

Categories

Resources