1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-09-27 08:39:00 +02:00
Files
BezierInfo-2/docs/js/custom-element/api
2020-09-19 12:29:43 -07:00
..
2020-09-19 12:29:43 -07:00
2020-09-19 12:29:43 -07:00
2020-09-17 22:18:08 -07:00
2020-09-19 12:29:43 -07:00
2020-09-17 22:18:08 -07:00
2020-09-19 12:29:43 -07:00

The Graphics API

Graphics code is bootstrapped and drawn uses two "master" functions:

setup() {
    // initialisation code goes here
}

draw() {
    // drawing code goes here
}

All code starts at setup(), automatically calling draw() after setup has been completed. Standard JS scoping applies, so any variable declared outside of setup/draw will be a "global" variable.

User Events

Graphics code can react to touch/mouse, which can be handled using:

  • onMouseDown() triggered by mouse/touch start events.
  • onMouseUp() triggered by mouse/touch end events.
  • onMouseMose() triggered by moving the mouse/your finger.

Mouse event data can be accessed via the this.cursor property, which encodes:

{
    x: current event's screen x coordinate
    y: current event's screen x coordinate
    down: boolean signifying whether the cursor is engaged or not
    mark: {x,y} coordinate object representing where mousedown occurred
    last: {x,y} coordinate object representing where the cursor was "one event ago"
    diff: {x,y} coordinate object representing the x/y difference between "now" and "one event ago",
          with an additional `total` propert that is an {x,y} coordinate object representing the x/y
          difference between "now" and the original mousedown event.
}

Graphics code can also react to keyboard events, although this is a great way to make sure your code won't work for mobile devices, so it's better to use range sliders to keep things accessible. That said, they can be handled using:

  • onKeyDown() triggered by pressing a key
  • onKeyUp() triggered by releasing a key

Keyboard event data can be accessed via the this.keyboard property, which encodes:

{
    currentKey: the name of the key associated with the current event
}

Additionally, the this.keyboard property can be consulted for named keys to see if they are currently down or not, e.g. to check whether the up arrow is down or not:

draw() {
    if (this.keyboard[`ArrowUp`]) {
        ...
    }
}

Controllable parameters

Graphics code can be passed external values from HTML using data attributes:

<graphics-element src="..." data-propname="somevalue"></graphics-element>

which can be access on the code side using

this.parameters.propname;

Additionally, graphics code has special functions for range values, either directly in code:

setup() {
    // name, min, max, step, initial value
    addSlider(`rangeValue`, 0, 1, 0.001, 0.5);
}

draw() {
    // values defined through sliders become accessible on `this`:
    console.log(this.rangeValue);
}

Alternatively, they can be hooked into a predefined slider:

<graphics-element src="..." data-propname="somevalue">
    <input type="range" min="0" max="1" step="0.001" value="0.5" class="my-slider">
</graphics-element>

using the setSlider function:

setup() {
    // local query selector, name, initial value
    setSlider(`.my-slider`, `rangeValue`, 0.5);
}

draw() {
    console.log(this.rangeValue);
}

Movable points

An important part of the Graphics API is showing shapes that are controlled or defined by coordinates, and as there are special functions for marking points as "movable" - that is, these points can be click/touch-dragged around a graphic. To fascilitate this, the following functions can be used:

  • setMovable(points, ...) takes one or more arrays of points, and marks all points as "being movable", such that if the cursor activates at an x/y coordinate near one of these, that point gets assigned to this.currentPoint, as well as being automatically moved around as you drag the cursor around on the sketch.
  • resetMovable() will clear the list of movable points.
  • resetMovable(points, ...) is the same as calling resetMovable() followed by setMovable(points, ...).

The API

The following is the list of API functions that can be used to draw... whatever you like, really.

gGobal constants

  • PI 3.14159265358979
  • TAU 6.28318530717958
  • POINTER "default"
  • HAND "pointer"
  • CROSS "crosshair"
  • POLYGON Shape.POLYGON, "Polygon"
  • CURVE Shape.CURVE, "CatmullRom"
  • BEZIER Shape.BEZIER, "Bezier"
  • CENTER "center"
  • LEFT "left"
  • RIGHT "right"

Instance propeties

  • this.width the width of the graphic
  • this.height the height of the graphic
  • this.panelWidth the width of a single panel in the graphic, only meaningful in conjunction with setPanelWidth (see below)
  • this.parameters the collection of externally passed parameters (via HTML: data-... attributes, via JS: a key/value object)
  • this.cursor represents the current mouse/touch cursor state
  • this.currentPoint whatever point thec cursor is currently close enough to to interact with
  • this.keyboard the current keyboard state
  • this.currentShape the currently active shape. warning: this value gets reset any time start() is used, so it is recommended to cache the current shape using saveShape() instead of directly referencing this.currentShape.

General functions

  • setSize(width,height) explicitly resizes the canvas. warning: this will reset all color, transform, etc. properties to their default values.
  • setPanelCount(int) use this in setup() to let the API know that this graphic is technically a number of "separate" panels of content, setting this.panelWidth to width/panelcount.
  • toDataURL() returns the graphic as PNG image, encoded as a data URL.
  • find(qs) find an HTML elements in the <graphics-element> DOM tree, using a query selector
  • findAll(qs) find all HTML elements that match the provided querySelector. note: unlike the DOM API, this function returns a plain array.

Maths functions

  • abs(v) get the absolute value
  • approx(v1, v2, epsilon = 0.001) check whether v1 differs from v2 by no more than epsilon
  • atan2(dy, dx) atan2
  • binomial(n, k) get the binomial coefficient, i.e. "n choose k"
  • ceil(v) round any fractional number up to the next highest interger
  • constrain(v, lowest, highest) restrict a value in its lowest and highest value.
  • cos(v) cosine
  • dist(x1, y1, x2, y2) the euclidean distance between (x1,y1) and (x2,y2)
  • floor(v) round any fractional number to an integer by discarding its fractional part
  • map(v, fromStart, fromEnd, toStrart, toEnd, constrain = false) compute a value on an interval [fromStart,fromEnd] to its corresponding value on the interval [toStart,toEnd], with optional constraining to that new interval.
  • max(...v) find the highest number in two or more numbers
  • min(...v) find the lowest number in two or more numbers
  • random() generate a random value between 0 (inclusive) and 1 (exclusive)
  • random(v) generate a random value between 0 (inclusive) and v (exclusive)
  • random(a,b) generate a random value between a (inclusive) and b (exclusive)
  • round(v) round any fractional number by applying ceil for any number with fractional part >= 0.5, and floor for any number with fractional part < 0.5.
  • sin(v) sine
  • sqrt(v) square root
  • tan(v) tangent

Property functions

  • setBorder(width = 1, color = "black") set the canvas border width and color
  • setColor(color) set the color for both shape stroke and fill
  • noColor() set both stroke and fill color to "transparent"
  • setCursor(type) set the CSS cursor type. POINTER, HAND, and CROSS constants are provided, other values must be supplied as string.
  • setFill(color) set the fill color
  • noFill() set the fill color to "transparent"
  • setFont(font) set the text font, using CSS font syntax
  • setFontFamily(name) set the font to be used, by name
  • setFontSize(px) set the font size in pixels
  • setFontWeight(val) set the font weight in CSS weight units
  • setGrid(size, color) set the background grid's spacing and line coloring
  • noGrid() do not draw a background grid
  • setLineDash(...values) set the interval values for dashed lines
  • noLineDash() do not use line dashing for strokes
  • setShadow(color, px) set the color and blur distance for drawing shape shadows
  • noShadow() do not use shape shadows
  • setStroke(color) set the stroke color
  • noStroke() set the stroke color to "transparent"
  • setTextStroke(color, weight) set the text outline stroke color and width (in pixels)
  • noTextStroke() disable text outline
  • setWidth() reset the stroke width to be 1 pixel wide
  • setWidth(width) set the stroke width to a custom value, in pixels

For coloring purposes, there is also the randomColor function:

  • randomColor() returns a random, full opaque CSS color
  • randomColor(opacity) returns a random CSS color with the indicated opacity (in interval [0,1])
  • randomColor(opacity, cycle=false) if the second parameter is explicitly set to false, the random seed used to generate the random color will not be updated, and the resulting random color will be the same as when the function was previously called.

For temporary work, where you might want to change some properties and then revert to the previous state, there are two functions available:

  • cacheStyle() cache the current collection of properties. This uses a stack, with each call adding a new "snapshot" on the stack.
  • restoreStyle() restore the most recently cached state from the stack.

Coordinate transform function

  • rotate(angle) rotate the coordinate system by angle (clockwise, in radians)
  • scale(x, y) scale the coordinate system by a factor of x horizontally, and y vertically
  • translate(x, y) move the coordinate system by x units horizontally, and y units vertically
  • resetTransform() reset the coordinate system to its default values
  • transform(a,b,c,d,e,f) transform the coordinate system by applying a transformation matrix to it. This matrix has the form:
    | a b c |
m = | d e f |
    | 0 0 1 |

note: all transforms are with respect to (0,0) irrespective of where (0,0) has been moved to through successive transforms.

In addition to transformations, there are also two functions to allow you to map screen coordinates (e.g. cursor position) to their corresponding transformed coordinate, and vice versa, to allow for drawing/computing points in either coordinate system

  • screenToWorld(x, y) converts a screen coordinate (x,y) to its corresponding transformed coordinate system coordinate (x',y')
  • worldToScreen(x, y) converts a transformed coordinate system coordinate (x,y) to its corresponding screen coordinate (x', y')

Drawing functions

  • arc(x, y, r, s, e) draw a section of outline for a circle with radius r centered on (x,y), starting at angle s and ending at angle e.
  • circle(x, y, r) draw a circle at (x,y) with radius r
  • clear(color="white", preserveTransforms=false) clears the graphics to a specific CSS background color, resetting the transform by default.
  • drawAxes(hlabel, hs, he, vlabel, vs, ve, w, h) draw a set of labelled axes, using {hlabel, hs, he} as horizontal label, with start marker hs and end marker he, and using {vlabel, vs, ve} as vertical label, with start marker vs and end marker ve
  • drawGrid(division = 20) draw a grid with the specified spacing, colored using the current stroke color
  • drawShape(...shapes) draw one or more saved full shapes (see below)
  • image(img, x = 0, y = 0, w = auto, h = auto) draw an image at some (x,y) coordinate, defaulting to (0,0), scaled to some width and height, defaulting to the native image dimensions
  • line(x1, y1, x2, y2) draw a line from (x1,y1) to (x2,y2)
  • plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1) plot a function defined by fn (which must take a single numerical input, and output an object of the form {x:..., y:...}) for inputs in the interval [start,end], at a resolution of steps steps, with the resulting values scaled by xscale horizontally, and yscale vertically.
  • point(x, y) draw a single point at (x,y)
  • rect(x, y, w, h) draw a rectangle from (x,y) with width w and height h
  • redraw() triggers a new draw loop. Use this instead of calling draw() directly when you wish to draw a new frame as part of event handling.
  • text(str, x, y, alignment = LEFT) place text, colored by the fill color, anchored to (x,y), with the type of anchoring determined by alignemtn. The alignment constants LEFT, RIGHT, and CENTER are available.
  • wedge(x, y, r, s, e) similar to arc, but draw a full wedge

Shape drawing functions

  • start(type = POLYGON, factor) set up a new Shape as this.currentShape in preparation for receiving data. Types can be POLYGON (default), CURVE (Catmull-Rom), or BEZIER. If CURVE is specified, the factor indicates how loose or tight the resulting Catmull-Rom curve will be.
  • segment(type, factor) set up a new section of the shape. If left unspecified the type and factor are inherited from the current Shape.
  • vertex(x, y) add a point to the current Shape's current segment.
  • end(close = false) draw the current Shape
  • saveShape() returns the current shape for later reuse

Built in object types

Shape

The Shape class reprents a drawable shape consisting of one or more polygonal, Catmull-Rom curve, or Bezier curve segments. It has a minimal API:

  • new Shape(type, factor, points = []) construct a new Shape of the specified type (options are Shape.POLYGON, Shape.CURVE for Catmull-Rom curves, and Shape.BEZIER for Bezier curves), with the specified factor (used for Catmull-Rom curve tightness), and optional list of points to prepopulate the first shape segment.
  • merge(other) merge another Shape's segments into this Shape
  • copy() returns a copy of this Shape
  • newSegment(type, factor) start a new segment in this Shape of the indicated type, with the indicated tightness factor.
  • vertex(p) add an on-shape coordinate (x,y) to this Shape. How this vertex contributes to the overall shape drawing depends on the current segment type.

Vector

The Vector class represents a 2d/3d coordinate, with a minimal standard API:

  • new Vector(x,y,z?) / new Vector({x:,y:,z:} construct a new Vector
  • vector.dist(other, y, z = 0) calculate the distance to some other vector-as-coordinate
  • vector.normalize(f) return a new Vector representing a scaled copy of this vector, with length 1.0
  • vector.getAngle() get the angle between this vector and the x-axis.
  • vector.reflect(other) reflect this vector-as-coordinate over the line that some other vector lies on
  • vector.add(other) return a new vector representing the addition of some other vector to this vector
  • vector.subtract(other) return a new vector representing the subtraction of some other vector to this vector
  • vector.scale(f = 1) return a new vector representing the scaled version of this vector

Matrix

The Matrix class represents an NxM matrix, with minimal standard API:

  • new Matrix(n,m,data?) construct a new Matrix. If data is provided, the matrix will be filled with that. warning: data is assumed to be n x m, but is not validated.
  • setData(data) warning: data is assumed to be n x m, but is not validated.
  • get(i, j) get the value at row i and column j
  • set(i, j, value) set the value at row i and column j
  • row(i) get the entire ith row as an array of values
  • col(j) get the entire jth column as a (flat) array of values
  • multiply(other) return a new Matrix representing the right-multiplication of this matrix with some other matrix
  • invert() return a new Matrix representing the inverse of this matrix, or undefined if no inverse exists
  • transpose() return a new Matrix representing the transpose of this matrix ...

Bezier

The Bezier class is an instance of bezier.js with all its API functions, extended for use on the canvas:

  • static defaultQuadratic(apiInstance) returns a new quadratic Bezier with preset coordinate values tailored to the Primer on Bezier Curves. The apiInstance must be a reference to a valid Graphics-API instance (typically thiat will simply be this in your code).
  • static defaultCubic(apiInstance) returns a new cubic Bezier with preset coordinate values tailored to the Primer on Bezier Curves. The apiInstance must be a reference to a valid Graphics-API instance (typically thiat will simply be this in your code).
  • static fitCurveToPoints(apiInstance, points, tvalues) returns a new n-dimensional Bezier that has been fit to the provided list of points, constrained to the provided tvalues, using MSE polygonal curve fitting. The apiInstance must be a reference to a valid Graphics-API instance (typically thiat will simply be this in your code).

The extended API in addition to these static functions are:

  • new Bezier(apiInstance, ...coords) construct a new Bezier curve controlled by three or more points, either supplied as numerical arguments, or as point objects {x:..., y:..., z?:...} where z is optional. The apiInstance must be a reference to a valid Graphics-API instance (typically thiat will simply be this in your code).
  • project(x, y) returns an {x:..., y:...} object representing the projection of some point (x,y) onto this curve.
  • getPointNear(x, y, d = 5) returns either undefined, or one of the Bezier curve's control points if the specified (x,y) coordinate is d or fewer pixels from a control point.
  • drawCurve(color = #333) draws this curve on the canvas, with optional custom color
  • drawPoints(labels = true) draws the curve's control points, with optional coordinate labels (defaulting to true)
  • drawSkeleton(color = #555) draws this curve's coordinate polygon, with optional custom color
  • getStrutPoints(t) get the list of points obtained through "de Casteljau" interpolation, for a given t value
  • drawStruts(t, color = "black", showpoints = true) draws this curve's "de Casteljau" points and lines, for a given t value, with optional custom color, and optional omission of the points if only the lines are required.
  • drawBoundingBox(color = "black") draw the axis-aligned bounding box for this Bezier curve with optional custom color

BSpline

The BSpline class represents a generaic B-spline curve, with a minimal API:

  • new BSpline(apiInstance, points) constructs a B-spline controlled by a points array in which each element may be either of the form {x: ..., y: ...} or a numerical tuple [x,y]. The apiInstance must be a reference to a valid Graphics-API instance (typically thiat will simply be this in your code).
  • getLUT(count) returns an array of count coordinates of the form {x:...,y:...}, representing a polygonal approximation of this BSpline.
  • formKnots(open = false) set-and-return the list of B-spline knots using either the standard uniform interval spacing, or if open is set to true, special spacing to effect a B-spline that start and ends at the actual start and end coordinates. The knot array returned in this fashion is a live array, and updating its values will change the B-spline's shape.
  • formUniformKnots() set-and-return uniformaly spaced knot values. The knot array returned in this fashion is a live array, and updating its values will change the B-spline's shape.
  • formWeights() set-and-return the array of weights. These will all be uniformly initialized to 1, with the weight array returned being a live array, so that updating its values will change the B-spline's shape.