documentationfor yFiles for HTML 3.0.0.3

Snapping

When discussing snapping, it’s important to first define the terms snap reference and snap result.

A snap reference is a guide related to a fixed object that a moved object might snap to. Prominent examples of snap references are snap line and snap grid.

A snap result represents the position where the current position of a moved object actually snaps to a snap reference. A moved object can have multiple snap results at the same location, meaning it can snap to multiple snap references simultaneously. These snap references are then visualized.

You can set the color of the snap result visualization using the CSS classes that are provided by the default snap reference visualizations, see Styling Snap References.

Adding Custom Snap References

To add custom snap references for all elements, register a listener to the GraphSnapContext’s collect-snap-references event. The arguments of that event has a method to add additional snap references.

Adding a custom snap line for all graph elements
function addSnapLine(
  graphSnapContext: GraphSnapContext,
  start: Point,
  end: Point
): void {
  const snapLine = createSnapLine(start, end)
  if (snapLine !== null) {
    // add a snap line for all graph elements
    graphSnapContext.addEventListener('collect-snap-references', (evt) =>
      evt.addSnapReference(snapLine)
    )
  }
}

function createSnapLine(
  start: Point,
  end: Point
): OrthogonalSnapLine | null {
  // calculate the center of the snap line
  const center = start.add(end).multiply(0.5)
  // create a vertical snap line
  if (start.x === end.x) {
    return new OrthogonalSnapLine(
      SnapLineOrientation.VERTICAL,
      SnapLineSnapTypes.CENTER,
      SnapReferenceVisualizationType.FIXED_LINE,
      center,
      start.y,
      end.y,
      false,
      50
    )
  }
  // create a horizontal snap line
  if (start.y === end.y) {
    return new OrthogonalSnapLine(
      SnapLineOrientation.HORIZONTAL,
      SnapLineSnapTypes.CENTER,
      SnapReferenceVisualizationType.FIXED_LINE,
      center,
      start.x,
      end.x,
      false,
      50
    )
  }
  // we do not add non-orthogonal snap lines here
  return null
}
Moving a node close to the custom snap line
customizing interaction custom snapline 1
customizing interaction custom snapline 2

Note that the snap line appears only if you move a graph element close to it. The following snippet illustrates how to always display the snap line.

Painting the snap line
function paintSnapLine(start: Point, end: Point): void {
  const lineElement = document.createElementNS(
    'http://www.w3.org/2000/svg',
    'line'
  )
  lineElement.setAttribute('x1', String(start.x))
  lineElement.setAttribute('y1', String(start.y))
  lineElement.setAttribute('x2', String(end.x))
  lineElement.setAttribute('y2', String(end.y))
  lineElement.setAttribute('stroke', 'black')

  const renderTree = graphComponent.renderTree
  renderTree.createElement(
    renderTree.backgroundGroup,
    new SvgVisual(lineElement)
  )
}
Painting the snap line
customizing interaction paint snapline 1
customizing interaction paint snapline 2

Each graph item provides a default set of snap references. A node, for example, provides snap lines at its borders and its center. You can change this behavior by decorating the default snap reference provider. The following example shows how to add a snap line 10 pixels above the top border of each node.

Adding snap lines to nodes
const nodeDecorator = graphComponent.graph.decorator.nodes

nodeDecorator.snapReferenceProvider.addWrapperFactory((node, wrapped) =>
  ISnapReferenceProvider.create(
    (
      context: GraphSnapContext,
      evt: CollectSnapReferencesEventArgs
    ) => {
      // add default snap references
      if (wrapped !== null) {
        wrapped.addSnapReferences(context, evt)
      }
      // add a snap lines 10 pixels above the top border of a node
      const layout = node.layout.toRect()
      const center = new Point(layout.centerX, layout.y - 10)
      const snapLine = new OrthogonalSnapLine(
        SnapLineOrientation.HORIZONTAL,
        SnapLineSnapTypes.BOTTOM,
        SnapReferenceVisualizationType.FIXED_LINE,
        center,
        layout.x - 50,
        layout.maxX + 50,
        false,
        100
      )
      evt.addSnapReference(snapLine)
    }
  )
)
Additional snap line of a node
customizing interaction custom node snapline 1
customizing interaction custom node snapline 2

GraphSnapContext provides a number of properties which determine for which objects snap references should be collected.

Property Default Value Description

collectEdgeSnapReferences

true

Whether to provide snap references for orthogonal edge segments.

collectNodeSizes

true

Whether to provide snap references for sizes of fixed nodes.

collectNodeSnapReferences

true

Whether to provide snap references for fixed nodes (parallel to borders, at border, at center).

collectPortSnapReferences

true

Whether to provide snap references for ports (orthogonal snap lines at the port’s x and y coordinates).

collectNodePairSnapLines

true

Whether to provide snap references for equal distances between two nodes to which moved nodes will snap.

collectNodePairCenterSnapLines

false

Whether to provide snap references for equal distances between the centers of two nodes to which the center of moved nodes will snap.

collectNodePairSegmentSnapLines

true

Whether to provide snap references for equal distances between two nodes to which moved orthogonal edge segments will snap.

nodeDistance

0

Defines the distance to a fixed node’s border for snap lines to which moved nodes can snap.

nodeToEdgeDistance

-1

Defines the distance to an orthogonal edge segment for snap lines to which moved nodes can snap.

edgeDistance

0

Defines the distance to an orthogonal edge segment for snap lines to which moved orthogonal edge segments can snap.

cropSnapLines

true

Whether to crop snap lines at obstacles.

snapLineExtension

40

The amount by which snap lines that are induced by existing edge segments and node borders are being extended.

Some of the settings are tailored to be used with a moved label:

Property Default Value Description

considerInitialLabelLocationSnapping

true

Whether to collect snap references for the initial position of a label.

considerEdgeLabelOwnerPathSnapping

true

Whether to collect snap lines on the edge path of an edge label.

considerEdgeLabelOwnerDistanceSnapping

true

Whether to collect two snap lines in parallel to the edge path of the label owner at the initial distance of the edge label.

considerEdgeLabelOwnerLabelsDistanceSnapping

true

Whether to collect snap lines in parallel to the edge path of the label owner at the distances of all edge labels of that owner.

considerEdgeLabelAllEdgeLabelsDistanceSnapping

false

Whether to collect snap lines in parallel to the edge path of the label owner at the distance of other edge labels in the graph.

considerNodeLabelOwnerShapeSnapping

true

Whether to collect six snap lines, two through the center and four through the border sides of the label owner.

considerNodeLabelOwnerDistanceSnapping

true

Whether to collect four snap lines in parallel to the owner’s borders at the initial label distance.

considerNodeLabelOwnerLabelsDistanceSnapping

true

Whether to collect snap lines in parallel to the border of the label owner at the distance of other node labels of that owner.

considerNodeLabelAllNodeLabelsDistanceSnapping

false

Whether to collect snap lines in parallel to the border of the label owner at the distance of other node labels in the graph.

considerPortLabelOwnerLocationSnapping

true

Whether to collect snap lines to the center of the owner port of a port label.

In addition, the following settings determine which and how items are snapped:

Property Default Value Description

snappableItems

NODE | ORTHOGONAL_SEGMENT | PORT_ADJACENT_SEGMENT | BEND_ADJACENT_SEGMENT | PORT | LABEL

Determines, for which types of items snap result provider implementations should snap.

gridSnappableItems

ALL

Determines for which types of items the method collectGridSnapReferences collects snap results.

Adding Custom Snap Results

Similar to adding custom snap references, you can modify the set of SnapResults collected during a move or edit operation. For example, grid snapping provides the center of a node as a result to snap to the grid. The following example shows how to also specify the top left corner of the node as a snap result.

Adding grid snap results to nodes
class CustomNodeSnapResultProvider extends NodeSnapResultProvider {
  protected collectGridSnapResults(
    context: GraphSnapContext,
    evt: CollectSnapResultsEventArgs,
    snapGrid: SnapGrid,
    suggestedLayout: Rect,
    node: INode
  ) {
    // add the default grid snap results (center of the node)
    super.collectGridSnapResults(
      context,
      evt,
      snapGrid,
      suggestedLayout,
      node
    )
    // add the top left corner of the node as grid snap result
    this.collectGridSnapResult(
      context,
      evt,
      snapGrid,
      suggestedLayout.topLeft,
      node
    )
  }
}

const nodeDecorator = graphComponent.graph.decorator.nodes
nodeDecorator.snapResultProvider.addConstant(
  new CustomNodeSnapResultProvider()
)
Additional snap result of a node
customizing interaction custom grid snap result 1
customizing interaction custom grid snap result 2

The Custom Snapping source code demo shows how to customize snapping behavior and how to add custom snap references.