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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rnacanvas/draw.strung

v2.0.1

Published

Draw strung elements

Readme

Installation

With npm:

npm install @rnacanvas/draw.strung

Usage

All exports of this package can be accessed as named imports.

// an example import
import { StrungElement } from '@rnacanvas/draw.strung';

class StrungElement

A strung element (e.g., a triangle strung on a bond).

var triangle = Triangle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

// will move with the parent bond
var strungElement = new StrungElement(triangle, owner);

// the point of connection on the line of the parent bond
// (relative to the midpoint of the bond)
strungElement.lineX = 25;

// displacement from the line of the parent bond
strungElement.displacementX = 10;
strungElement.displacementY = 20;

For an element to be "stringable", it must fulfill the following interfaces.

interface DrawingElement {
  /**
   * The DOM node corresponding to the drawing element.
   */
  readonly domNode: SVGElement;
}
interface Centerable {
  /**
   * Center X coordinate.
   */
  centerX: number;

  /**
   * Center Y coordinate.
   */
  centerY: number;
}

Stringable elements may optionally fulfill Directed interface below if they have direction associated with them (e.g., triangles, rectangles).

interface Directed {
  /**
   * Direction angle (in radians).
   */
  direction: number;
}

readonly owner

The element owning a strung element (e.g., a primary or secondary bond).

var rectangle = Rectangle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(rectangle, owner);

strungElement.owner === owner; // true

Owner elements must fulfill the Linear interface below.

interface Linear {
  readonly length: number;

  /**
   * Returns information regarding a point at a given length along the line.
   */
  atLength(length: number): {
    // X coordinate
    readonly x: number;

    // Y coordinate
    readonly y: number;

    // direction angle (in radians)
    readonly direction: number;
  };

  /**
   * For listening for when the owner element moves.
   */
  addEventListener(name: 'change', listener: () => void): void;
}

Owner elements must also fulfill the DrawingElement interface below (which is implemented by all RNAcanvas drawing elements).

interface DrawingElement {
  readonly domNode: SVGElement;
}

readonly domNode

The DOM node corresponding to the strung element.

Is the same as the DOM node corresponding to the wrapped "stringable" element.

var circle = Circle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(circle, owner);

strungElement.domNode === circle.domNode; // true

lineX

The length along the owner element (relative to the midpoint of the owner) at which the strung element is attached.

var text = Text.create('A');

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(text, owner);

// place at the midpoint of the owner bond
strungElement.lineX = 0;

// place 10 pixels past the midpoint of the owner bond
strungElement.lineX = 10;

// place 10 pixels before the midpoint of the owner bond
strungElement.lineX = -10;

displacementMagnitude

The magnitude of the strung element's displacement from the line of its owner element.

var circle = Circle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(circle, owner);

// place at the midpoint of the owner bond
strungElement.lineX = 0;

// place 10 pixels away from the midpoint of the owner bond
// (at a 90 degree angle)
strungElement.displacementMagnitude = 10;
strungElement.displacementDirection = Math.PI / 2;

displacementDirection

The direction (in radians) of the strung element's displacement from the line of its owner element.

Note that displacement X component is expressed relative to the direction of the owner element line at the point where the strung element is attached.

var circle = Circle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(circle, owner);

// place at the midpoint of the owner bond
strungElement.lineX = 0;

// place 10 pixels away from the midpoint of the owner bond
// (at a 90 degree angle)
strungElement.displacementMagnitude = 10;
strungElement.displacementDirection = Math.PI / 2;

displacementX

The X component of the strung element's displacement from the line of its owner element.

Note that displacement X component is expressed relative to the direction of the owner element line at the point where the strung element is attached.

var triangle = Triangle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(triangle, owner);

// place at the midpoint of the owner bond
strungElement.lineX = 0;

// place 10 pixels away from the midpoint of the owner bond
// (at a 90 degree angle)
strungElement.displacementX = 10 / 2**0.5;
strungElement.displacementY = 10 / 2**0.5;

displacementY

The Y component of the strung element's displacement from the line of its owner element.

Note that displacement Y component is expressed relative to the direction of the owner element line at the point where the strung element is attached.

var triangle = Triangle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(triangle, owner);

// place at the midpoint of the owner bond
strungElement.lineX = 0;

// place 10 pixels away from the midpoint of the owner bond
// (at a 90 degree angle)
strungElement.displacementX = 10 / 2**0.5;
strungElement.displacementY = 10 / 2**0.5;

drag()

Move the strung element by the specified X and Y amounts.

X and Y amounts are expressed in absolute terms (i.e., not relative to the owner element line).

var rectangle = Rectangle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(rectangle, owner);

// place at the midpoint of the owner bond
strungElement.lineX = 0;

strungElement.displacementX = 0;
strungElement.dispalcementY = 0;

// owner bond direction is 45 degrees
owner.direction; // Math.PI / 4

// drag at a 90 degree angle to the direction of the owner bond
strungElement.drag(10, -10);

strungElement.displacementX; // 10 * 2**0.5
strungElement.displacementY; // 0

Often times elements are dragged as part of a group.

If the owner element of a strung element is part of this group, then the displacement of a strung element should not be modified (i.e., the strung element should be allowed to move with its owner element).

To accomplish this behavior, one can make use of the dragGroup option when invoking the drag() method.

var rectangle = Rectangle.create();

// any bond (e.g., a primary or secondary bond)
var owner;

var strungElement = new StrungElement(rectangle, owner);

strungElement.displacementX = 0;
strungElement.dispalcementY = 0;

// includes the owner bond
var dragGroup = {
  has: ele => ele === owner || ele === owner.domNode,
};

strungElement.drag(10, -10, { dragGroup });

// displacement not changed
strungElement.displacementX; // 0
strungElement.dispalcementY; // 0

Drag groups must fulfill the following interface.

interface DrawingElementsCollection {
  /**
   * Should return true for either a drawing element itself
   * or its corresponding DOM node.
   */
  has(ele: DrawingElement | Node): boolean;
}