🎉 JointJS has new documentation! 🥳
Paper scroller wraps the paper element and implements scrolling, panning, centering and auto-resizing of the paper content.
Include joint.ui.paperScroller.js
and joint.ui.paperScroller.css
files to your HTML:
<link rel="stylesheet" type="text/css" href="joint.ui.paperScroller.css">
<script src="joint.ui.paperScroller.js"></script>
PaperScroller creates a window to the paper area. This way, the actual paper can be large but the user will see only the PaperScroller area which he can scroll & pan. First, we create a PaperScroller object. Then we pass the automatically created PaperScroller element as a container for our paper. Once we have our paper object created, we pass it back to the PaperScroller as it needs a reference to the actual paper.
var paper = new joint.dia.Paper({
width: 2000,
height: 2000,
model: graph
});
var paperScroller = new joint.ui.PaperScroller({
paper: paper
});
document.getElementById('paper-container').appendChild(paperScroller.render().el);
width
and height
of the paper must be a number. A CSS value such as '100%'
will result in PaperScroller: paper dimension must be a number exception.The next step is to hook the startPanning
method of the paper scroller
on the blank:pointerdown
paper event which will cause panning whenever the user drags a blank
area of the paper:
paper.on('blank:pointerdown', paperScroller.startPanning);
In order to help users understand what action will happen when they drag the paperScroller, use setCursor(cursor)
method. It sets the mouse cursor, which is displayed when the mouse pointer is over the PaperScroller. It accepts any valid CSS cursor property value. Alternatively the cursor can be passed to the constructor. It defaults to 'default'
(an arrow).
var paperScroller = new joint.ui.PaperScroller({
paper: paper,
cursor: 'grab'
});
// Or dynamically change cursor e.g. when user is about to select elements.
paperScroller.setCursor('crosshair');
The default padding around the paper's content. The padding ensures the paper inside the PaperScroller is always pannable. It also makes sure that there is always at least a fragment of the paper visible. Padding can be a number, an object, or a function.
const scroller = new joint.ui.PaperScroller({
paper: paper,
// Default Padding function
padding: function() {
var clientSize = this.getClientSize();
var minVisibleSize = Math.max(this.options.minVisiblePaperSize, 1) || 1;
var padding = {};
padding.left = padding.right = Math.max(clientSize.width - minVisibleSize, 0);
padding.top = padding.bottom = Math.max(clientSize.height - minVisibleSize, 0);
return padding;
}
});
/*
Example Usage
padding: 10
padding: { top: 20, left: 20 }
padding: function() { return 10; }
*/
User scrolling of the paper is allowed by default. Two methods are provided to toggle this functionality:
lock() |
Lock the current viewport by disabling user scrolling. |
unlock() |
Enable user scrolling if previously locked. |
PaperScroller also provides methods for programmatic scrolling. These methods try scroll the paper so that a specified point on the paper lies at the center of the paper scroller viewport. If this is not possible (e.g. if the requested point lies in a corner of the paper), the paper is scrolled as far as possible without requiring paddings. This means that the requested point will not actually move into the center of the viewport if there is not enough room for it. (Use the center
functions to add paddings if necessary and force the requested point to move to the center of paper scroller viewport.)
All scroll
methods optionally support animation if an opt.animation
object is provided. (Note that animated transitions are better supported with the transition
functions.)
opt.animation | |||
---|---|---|---|
option | type | default | description |
duration | number (milliseconds) | 400 | Duration of the animation in ms. |
timingFunction | function |
|
A callback function that is called on every frame of the animation. It receives the time progress of the animation, represented as a number between 0 and 1, as its first argument. This function is responsible for computing and returning the current step of the animation based on the provided progress value. |
complete | function | undefined | A callback function fired when the animation is complete. |
scroll(x, y [, opt]) |
Try to scroll the paper scroller so that the position (
|
scrollToContent([opt]) |
Try to scroll the paper scroller so that the center of paper content is at the center of the paper scroller viewport.
|
scrollToElement(element [, opt]) |
Try to scroll the paper scroller so that the center of
|
The PaperScroller constructor takes an optional parameter scrollWhileDragging
. When
this parameter is set to true
, the PaperScroller automatically scrolls the paper
to ensure that the dragged shape stays within the viewport. This scrolling behavior can be adjusted further by providing the following options:
ScrollWhileDragging | |||
---|---|---|---|
option | type | default | description |
interval | number (milliseconds) | 25 | A debounce interval between changes in the scrollLeft and scrollTop properties of the PaperScroller, in ms. |
padding | number (pixels) | -20 | Additional padding to add to the viewport area until scrolling is triggered. A negative value means that scrolling is triggered when the dragging pointer approaches the viewport boundary from the inside. A value of 0 means that scrolling is triggered when the dragging pointer crosses the viewport boundary. A positive value means that scrolling is triggered when the dragging pointer is that much farther from the viewport boundary. |
scrollingFunction | function |
|
A function that translates the distance between the pointer and the viewport boundary into the number of pixels by which to scroll. The default function scrolls slowly while the pointer is within the viewport and goes faster when the pointer leaves the viewport. |
Another optional parameter is inertia
. If set to true
, panning of the PaperScroller will have an inertia effect where the scroller builds momentum while dragging and continues moving in the same direction for some time. The parameter can be also enabled with an object containing the following properties.
inertia | |||
---|---|---|---|
option | type | default | description |
friction | number | 0.92 | Rate at which values slow down after the user releases the pointer. A value between 0 and 1. |
The optional parameter borderless
changes the default behavior of the padding. If set to true
, the paper inside the paperScroller extends beyond the padding. i.e. the blank space around the paper is converted to the paper itself making the borders of the paper visible no more.
The center
methods are more aggressive than the scroll
methods. These methods position the paper so that a specific point on the paper lies at the center of the paper scroller viewport, adding paddings around the paper if necessary (e.g. if the requested point lies in a corner of the paper). This means that the requested point will always move into the center of the viewport. (Use the scroll
functions to avoid adding paddings and only scroll the paper scroller viewport as far as the paper boundary.)
The position
methods are a more general version of the center
methods. They position the paper so that a specific point on the paper lies at requested coordinates inside the paper scroller viewport.
Padding can be added with opt.padding
, to offset positioned elements away from the edges of client viewport. This stacks up with the x
and y
coordinates; it also affects the center calculations. The padding value is normalized using the joint.util.normalizeSides
function; either a single number may be passed (e.g. padding: 10
applies padding of 10px to all edges), or an object with numeric properties (e.g. padding: { top: 20, horizontal: 10 }
applies padding of 20px to the top edge and 10px to the right and left edges).
center([opt]) |
If no coordinate is specified, position the center of paper to the center of the paper scroller viewport.
Adding 100px of left padding causes the effective center of the paper scroller window to shift by 50px to the right. That is where the center of paper will be positioned.
|
center(x, y [, opt]) |
Position the point (
Adding 100px of left padding causes the effective center of the paper scroller window to shift by 50px to the right. That is where the point will be positioned.
|
centerContent([opt]) |
Position the center of paper content to the center of the paper scroller viewport.
|
centerElement(element [, opt]) |
Position the center of
|
positionContent(positionName [, opt]) |
Align paper content inside the paper scroller viewport as specified by
|
positionElement(element, positionName [, opt]) |
Align
|
positionRect(rect, positionName [, opt]) |
Align a custom
|
positionPoint(point, x, y [, opt]) |
Position a custom The following example positions the origin of the paper to the origin (top-left point) of the paper scroller viewport:
The following example positions
The following example positions
|
ui.PaperScroller provides methods for checking whether elements or points are visible and not scrolled outside the viewport.
getVisibleArea() | Returns the size and origin of the current paperScroller viewport. The returned value is a g.Rect object, which contains x , y , width and height describing the visible area of the paper ignoring paper transformations (as would no scale, translate or rotate be applied).
|
isElementVisible(element [, opt]) | Returns true if the element is visible in the current paperScroller viewport. It returns false otherwise. Use { strict: [Boolean] } option for toggling complete true vs. partial false visibility. It's non-strict by default.
|
isPointVisible(point) | Returns true if the point (e.g. { x: 100, y: 200 } ) is visible in the current paperScroller viewport. It returns false otherwise. |
The PaperScroller exposes an API to scale the contained paper more easily:
paperScroller.zoom();
Return the current zoom level of the paper. Technically speaking, the zoom level
is the scaling factor (sx
) of the paper's SVGElement.
paperScroller.zoom(value [, opt]);
The zoom()
method accepts a value by which we want to increase/decrease the scaling factor of the paper. A positive value increases the scaling factor, which causes the paper to be zoomed in. A negative value decreases the scaling factor, which causes the paper to be zoomed out.
You can pass two options to cap the range of possible scaling factors as part of an opt
object - min
and max
. The scaling factor cannot then be decreased below min
(if provided) or increased above max
(if provided). These options are often useful in practice, with UI buttons bound to the paperScroller's zooming operations:
document.getElementById('zoom-in').addEventListener('click', () => {
paperScroller.zoom(0.2, { max: 4 });
});
document.getElementById('zoom-out').addEventListener('click', () => {
paperScroller.zoom(-0.2, { min: 0.2 });
});
Options of ox
and oy
are also available to transform the origin of the zoom. By default, the origin is the center of the
viewport.
paper.on('blank:mousewheel', (evt, ox, oy, delta) => {
evt.preventDefault();
paperScroller.zoom(delta * 0.2, { min: 0.4, max: 3, grid: 0.2, ox, oy });
});
Additionally, passing a value for the grid
option causes the resulting scaling factor to be rounded to the closest multiple of the grid
value.
Passing absolute: true
as an option sets the scaling factor directly to the provided value
(instead of treating it as a relative value). The constraints imposed by the min
, max
, and grid
are still in effect, however.
paperScroller.zoomToFit([opt]);
Scale the paper so that all of the contents of its graph fit into the user's viewport. For a list of available options, refer to paper.scaleContentToFit()
documentation.
paperScroller.zoomToRect(rect [, opt]);
Zoom and reposition the paper so that the area defined by rect
(in the paper local coordinates) fits into the user's viewport. For a list of available options, refer to paper.scaleContentToFit()
documentation.
The paperScroller provides few methods for panning and zooming in animated fashion. These are:
paperScroller.transitionToPoint(x, y [, opt])
paperScroller.transitionToPoint(point [, opt])
The method pans and optionally zooms the paperScroller to a given point. It accepts a point defined in the paper local coordinate system and an option object with several properties to control the transition.
scale | The zoom level to reach at the end of the transition. It defaults to the current paperScroller zoom level. |
duration | A string representing the number of seconds or milliseconds a transition animation should take to complete. E.g. '500ms' , '2s' . It defaults to '1s' |
delay | A string representing the amount of time to wait before a transition starts. It defaults to '0s' |
timingFunction | The option to describe how the intermediate pan positions and zoom values are calculated. For all available values visit CSS transition-timing-function property documentation. It defaults to 'ease' . |
onTransitionEnd | A callback function fired with transitionend event as its first parameter when the transition ends. |
// Move paper point (x=100, y=100) to the center of the viewport.
paperScroller.transitionToPoint(100, 100);
// Move and scale paper, so the point { x: 100, y: 100 } will appear in the center of the viewport.
paperScroller.transitionToPoint(100, 100, { scale: 2 });
// Move the the center of the `element` to the center of the viewport.
paperScroller.transitionToPoint(element.getBBox().center(), {
duration: '500ms',
onTransitionEnd: function(transitionEvent) {
// do something when the animation ends
}
});
paperScroller.transitionToRect(rect [, opt]);
The method pans and zooms the paperScroller over a specific period so the given rectangular area is at the end of the transition entirely visible in the viewport. The rectangular area is an object with x
, y
, width
and height
properties and defined in the paper local coordinate system. The method accepts all options from transitionToPoint()
(but scale
) and the following options from the table below.
center | An object with x and y properties, which defines the point to be in the center of the viewport when the transition ends. By default the center of the rectangular area is used. |
visibility | A number to change the percentage coverage of the viewport. The rectangular area covers 100% of the viewport by default (i.e. { visibility: 1 } ). For instance 80% coverage could be set with { visibility: .8 } |
minScale | A number to make the resulting scale always greater than or equal to minScale value. |
maxScale | A number to make the resulting scale always less than or equal to maxScale value. |
scaleGrid | A number to make the resulting scale the largest multiple of scaleGrid value less than or equal to the calculated scale. |
// Zoom the paperScroller so the given area covers 90% of the viewport.
// Also do not let the paperScroller exceed the zoom level 3.
paperScroller.transitionToRect({
x: 100,
y: 100
width: 200,
height: 200
}, {
visibility: 0.9,
maxScale: 3,
onTransitionEnd: function(transitionEvent) {
// do something when the animation ends
}
});
// Zoom the paperScroller in a way the elements `el1`, `el2`, `el3` cover the entire viewport
// and the center of the `el1` moves to the center of the viewport.
var rect = graph.getCellsBBox([el1, el2, el3]);
paperScroller.transitionToRect(rect, {
duration: '500ms',
center: el1.getBBox().center()
});
paperScroller.removeTransition();
When method called, the ongoing (if any) paperScroller transition is removed and the associated onTransitionEnd
callback is not fired.
The PaperScroller constructor takes an optional parameter autoResizePaper
. When
this parameter is set to true
, the PaperScroller automatically resizes the paper
so that it fits the content inside it. This makes it possible to have a fixed (even smaller) size of
the paper and when the user drags an element outside this area, the PaperScroller extends this paper
in order to accommodate for the new element. By default, the ui.PaperScroller
resizes the paper
by the paper width
/height
. If you want the paper to extend by a different amount,
pass the baseWidth
/baseHeight
options to the ui.PaperScroller
constructor
function. The paper adjustment is internally handled by calculating proper parameters for the
joint.dia.Paper:fitToContent method. You can further adjust
the behavior by setting the contentOptions
object to the ui.PaperScroller
constructor
function. This object can contain additional parameters that will be mixed with the calculated ones before calling
the joint.dia.Paper:fitToContent
method. This is handy if you, for example, want to set the maximum
width and height of the paper. In this case, you can just set contentOptions: { maxWidth: 3000, maxHeight: 3000 }
to the ui.PaperScroller
constructor function. contentOptions
can be also defined as a function returning the options.
new joint.ui.PaperScroller({
padding: 0,
contentOptions: function(paperScroller) {
var visibleArea = paperScroller.getVisibleArea();
return {
padding: {
bottom: visibleArea.height / 2,
top: visibleArea.height / 2,
left: visibleArea.width / 2,
right: visibleArea.width / 2
},
allowNewOrigin: 'any'
};
}
});
Try how this works in the following demo by zooming the paper out so that you see its borders and move your element outside the paper area. You should see how the paper gets automatically resized. When you drag the element back to its original location, the PaperScroller resizes the paper back to its original size.
var paperScroller = new joint.ui.PaperScroller({ autoResizePaper: true });
The plugin fires the following events.
Event Name | Handler Signature | Description |
---|---|---|
pan:start | (evt) |
Triggered when the user starts panning. |
pan:stop | (evt) |
Triggered when the user stops panning. |
scroll | (evt) |
Triggered when the paper has been scrolled. |
paperScroller.on('scroll', function(evt) {
console.log('The visible area has been changed:', this.getVisibleArea());
});