npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

visual-tree

v1.0.3

Published

Visual Tree

Downloads

3

Readme

Visual-Tree

A basic interactive tree visualization library that can be used to render different types of tree structures.

Node Version npm version Build Status License

https://user-images.githubusercontent.com/2601749/214102138-84f599e7-630a-4abf-adc9-94fd77593bb2.mp4

Installation

npm install visual-tree --save

Features

  • Custom node with icon and title
  • Collapse and expand child nodes
  • Add and insert new nodes
  • Remove single node and remove node with children
  • Insert new nodes between nodes
  • Zoom in & Zoom Out
  • Zoom fit to view port
  • Select and highlight nodes
  • Search for node
  • Keyboard navigation support
  • Highlight path to node
  • Toggle to fullscreen
  • Export tree to image

Overview

A tree visualization displays hierarchical data with a collection of nodes (data points that can store value or whole object) and edges (hierarchical relations between nodes).

Basic Terminologies

  • Root Node: The topmost node of a tree or the node which does not have any parent node. There is only one root per tree and one path from the root node to any node.
  • Parent Node: Any node except the root node has one edge upward to a node called parent.
  • Child Node: The node which is the immediate successor of another node (connected below a given node).
  • Leaf Node: (External Node) The node which do not have any child nodes are called leaf nodes.
  • Traversing: Traversing means passing through nodes in a specific order.

Usage

Initial Setup

  1. Create a new div element with specific id to be used as canvas container
<div id="visual-tree-container"></div>
  1. Create visual tree instance and add new node
// Create visual tree instance
var element = document.getElementById("visual-tree-container");
var visualTree = new VisualTree(element);

// Create new Nodes
var root = new Node({
    id: "0",
    name: "Home",
    icon: '/public/assets/home.png',
    textColor: '#ffffff',
    backgroundColor: '#1e981e'
});

var node = new Node({
    id: "1",
    name: "Child Node"
});

// Add nodes
visualTree.add(root);
visualTree.add(node, root);

// Finally render tree
visualTree.render();

Control View

// Zoom in
visualTree.zoomIn();
// Zoom out
visualTree.zoomOut();
// Zoom fit
visualTree.zoomFit();
// Zoom reset (Scale 1 and center in viewport)
visualTree.zoomReset();
// Toggle fullscreen
visualTree.toggleFullScreen();

Control Nodes

// Get selected node
var selected = visualTree.selectedNode;
// Select node by id
visualTree.selectNode("12");
// Reset selection
visualTree.resetSelection();

// Highlight node
node.highlighted = true;
// Reset all nodes highlight
visualTree.resetHighlight();

// Add child node to parent A
visualTree.add(new Node({id: "1", name: "child"}), A);
// Insert node between node "A" as parent and "B" as a child 
visualTree.add(new Node({id: "1", name: "child"}), A, B);

// Remove single node
visualTree.remove(selected, false);
// Remove node with its children
visualTree.remove(selected, true);

// Show node within viewport
visualTree.panToNode(node);
// Select edges between start and end nodes
visualTree.selectPath(startNodeId, endNodeId);
// Reset edges selection
visualTree.resetPathsSelection();

Highlight edges between nodes

We can highlight edges path between 2 nodes, and the library will traverse the tree between nodes to select the edges.

  • To highlight path between 2 nodes we need to call selectPath and pass start node id and end node id
  • To reset edges highlight we need to call resetPathsSelection function.
visualTree.selectPath(root.id, endNode.id);
// To reset highlight
visualTree.resetPathsSelection();

Search for and highlight nodes

function searchForNodes(term) {
    if(term.length === 0) {
        // Reset current highlighted nodes
        return visualTree.resetHighlight();
    }

    // Very basic search method
    // You can implement whatever you need
    Object.values(visualTree.nodes).forEach((node) => {
        if(node.name.indexOf(term) >= 0) {
            node.highlighted = true;
        } else {
            node.highlighted = false;
        }
    });
}

Show hide toggle button

// Show/Hide collapse and expand button (Toggle Button)
visualTree.setToggleButtonVisibility(false); // default = true

Listening to mouse move event

visualTree.setOnMouseMoveEvent((e) => {
    // Get current node (Node intersects with mouse current position x,y) 
    const node = e['node'];
    
    // Show action button on current hovered node under mouse position
    if(node != null) {
        tree.setActionButtonVisibility(true, node);
    } else {
        tree.setActionButtonVisibility(false);
    }
});

Challenges

  • Canvas Rendering
  • Tree Visualization
  • Keyboard Navigation

Tree Visualization

We have used the Reingold-Tilford tree visualization algorithm.

With current implementation and use case, we need to draw on x-axis, so we have done the implementation accordingly, the main challenge here is to determine the Y position for each node, also we have variable width and height for nodes, so we've also added some optimizations, for example, to get max-width for each column (along y-axis) and adjusted node X positions accordingly.

Additional details:

Canvas Rendering

For canvas rendering we use a low-level library Konva.js which helps focus on functionalities we need without wasting time with canvas and shape low-level rendering details.

Konva.js is an HTML5 2d canvas js library for desktop and mobile applications that can work with ES5, ES6, or even Typescript.

Additional details:

Keyboard Navigation

Keyboard navigation is implemented through considering the tree as a virtual grid (rows, columns) then move along the y-axis using up and down arrows, or along the x-axis using right and left arrows.

TODO

  • [ ] Testing
  • [ ] Vertical layout
  • [ ] Easy configuration for text and highlight colors
  • [ ] Export diagram to pdf
  • [ ] Performance optimization
  • [ ] Packaging optimization

License

MIT