### Setup Tapspace Space and View
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/grid/index.html
Initializes the Tapspace environment by creating a Space and a SpaceView, then mounting the view to a DOM element. This sets up the canvas for rendering and interaction.
```javascript
var space = new tapspace.Space()
var viewElement = document.getElementById('space')
var view = new tapspace.SpaceView(space)
view.mount(viewElement)
```
--------------------------------
### Setup Tapspace.js Viewport and Content (JavaScript)
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/minimal/index.html
Initializes a zoomable viewport using Tapspace.js and adds a 'Hello World!' item to the center. This code requires the Tapspace.js library to be loaded.
```javascript
document.addEventListener('DOMContentLoaded', () => {
const viewport = tapspace.createView('.myspaceapp')
viewport.zoomable()
const space = tapspace.createSpace()
viewport.addChild(space)
const item = tapspace.createItem('Hello World!')
item.addClass('hello')
const point = viewport.atCenter()
space.addChild(item, point)
})
```
--------------------------------
### Tapspace Image Preloading and Setup
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/go/index.html
Preloads necessary game assets (images for squares and stones) and sets up groups for organizing these elements within the Tapspace environment. Includes error handling for the preload function.
```javascript
tapspace.preload([
'../assets/square.png',
'../assets/go-stone-white.png',
'../assets/go-stone-black.png'
], function (err, imgs) {
if (err) {
console.error(err)
throw err
}
var squares = new tapspace.SpaceGroup(space)
var whiteStones = new tapspace.SpaceGroup(space)
var blackStones = new tapspace.SpaceGroup(space)
var squareImg = imgs[0]
var whiteImg = imgs[1]
var blackImg = imgs[2]
var tableImg = imgs[3]
// ... rest of the setup
```
--------------------------------
### Tapspace View Interaction Setup
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/go/index.html
Makes the main view interactive, allowing users to pan, zoom, and rotate the entire canvas. This is achieved by creating a Touchable instance for the view itself with the defined viewMode.
```javascript
var viewTouchable = new tapspace.Touchable(view, view)
viewTouchable.start(viewMode)
```
--------------------------------
### Tapspace Initialization and Interaction Setup
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/tunnel/index.html
Initializes the Tapspace environment, sets up the main space and view, and configures touch and wheel interactions for zooming, panning, and rotating. It also handles tap events for zooming in.
```javascript
// Wrap in a function namespace. Easier to debug and no conflicts. (function () {
var space = new tapspace.Space()
var view = new tapspacespace.SpaceView(space)
view.mount(document.getElementById('space'))
// Shorthands
const IVector = tapspace.geom.IVector
const Vector = tapspace.geom.Vector
// Vanishing point
const vanishingPoint = view.atNorm(0.618, 0.5)
// A heading text typical for the example apps.
const heading = new tapspace.SpaceHTML(
'
' +
'
Tunnel of Foods
' +
'
' +
'Dig in. Created with setLocal3d method.\n' +
'
' +
'
' +
'Powered by ' +
'Tapspace.js
\n' +
'Emojis by OpenMoji
\n' +
'
' +
'
'
)
// Place heading on space.
heading.setParent(space)
heading.setSize(500, 300)
const r = view.getSize().min() / 2.3
const headingTarget = vanishingPoint.offset(-r, -r)
heading.translate(heading.atNW(), headingTarget)
// Setup the view interaction
var viewtouch = new tapspace.Touchable(view, view)
var viewwheel = new tapspace.Wheelable(view, view)
// Pinch zoom and mouse wheel
viewtouch.start({ translate: true, scale: true, rotate: true, tap: true })
viewwheel.start({ scale: true })
// Tap to zoom in
viewtouch.on('tap', function (ev) {
var itr = tapspace.geom.ITransform.IDENTITY
itr = itr.scale(tapspace.geom.IVector.mean(ev.points), 0.618)
view.transformBy(itr)
})
```
--------------------------------
### JavaScript Setup and Element Creation with Tapspace
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/logo/index.html
This JavaScript code initializes the Tapspace environment, sets up the viewport and space, and defines functions for creating and manipulating elements. It includes logic for creating 'pixels' with specific colors, positions, and sizes, and adds interactivity like zooming and tap events.
```javascript
// Space setup
const viewportElement = document.querySelector('#viewport')
const viewport = tapspace.createViewport(viewportElement)
viewport.setAnchor(viewport.atCenter())
viewport.zoomable().responsive()
const space = tapspace.createSpace()
viewport.addChild(space, viewport.atCenter())
const heading = tapspace.createSpace()
space.addChild(heading, space.at(0, 0))
const rect = (color, position, size) => {
const item = tapspace.createItem()
item.setAnchor(item.atTopLeft())
item.setSize(size)
item.addClass('pixel')
const elem = item.getElement()
elem.style.background = color
heading.addChild(item, position)
return item
}
const phipow = (order) => {
const phi = (1 + Math.sqrt(5)) / 2
return Math.pow(phi, order)
}
const pixel = (color, position, order = 0) => {
const px = rect(color, position, { w: 200, h: 200 })
const scale = phipow(order)
px.scaleBy(scale, position)
// Make interactive: click to drop
px.tappable()
px.on('tap', () => {
px.animateOnce({ easing: 'ease-in', duration: '500ms' })
const v = px.atNorm(0.5, 0.5).getVectorTo(heading.at(0, 1100))
const vv = v.transitRaw(heading)
px.translateBy({ x: 0, y: vv.y * 2, z: 0 })
})
return px
}
const colors = [
'magenta', // t
'magenta', // a
'magenta', // p
'cyan', // s
'cyan', // p
'cyan', // a
'cyan', // c
'cyan', // e
'white', // .
'lightgray', // j
'lightgray' // s
]
const origin = space.at(0, 0)
const kerning = [
600 + 200 * phipow(-1), // t
600 + 200 * phipow(-1), // a
600 + 200 * phipow(-1), // p
600 + 200 * phipow(-1), // s
600 + 200 * phipow(-1), // p
600 + 200 * phipow(-1), // a
600 + 200 * phipow(-1), // c
600 + 200 * phipow(-1), // e
200 + 200 * phipow(-1), // .
600 + 200 * phipow(-1), // j
600 + 200 * phipow(-1) // s
]
const origins = kerning.reduce((acc, kern, i) => {
const prev = acc[acc.length - 1]
const nextOrigin = prev.offset(kern, 0)
acc.push(nextOrigin)
return acc
}, [origin])
const draw = (i, x, y, z = 0) => {
return pixel(colors[i], origins[i].offset(x * 200, y * 200, z * 200))
}
// TEMPLATE
// draw(i, 0, 0);
// draw(i, 1, 0);
// draw(i, 2, 0);
// draw(i, 0, 1);
// draw(i, 1, 1);
// draw(i, 2, 1);
// draw(i, 0, 2);
// draw(i, 1, 2);
// draw(i, 2, 2);
// draw(i, 0, 3);
// draw(i, 1, 3);
// draw(i, 2, 3);
// T
draw(0, 1, 0);
draw(0, 0, 1);
draw(0, 1, 1);
draw(0, 2, 1);
draw(0, 1, 2);
draw(0, 1, 3);
draw(0, 2, 3);
// A
draw(1, 1, 0);
draw(1, 2, 0);
draw(1, 0, 1);
draw(1, 2, 1);
draw(1, 0, 2);
draw(1, 1, 2);
draw(1, 2, 2);
draw(1, 0, 3);
draw(1, 2, 3);
// P
draw(2, 1, 0);
draw(2, 2, 0);
draw(2, 0, 1);
draw(2, 2, 1);
draw(2, 0, 2);
draw(2, 1, 2);
draw(2, 2, 2);
draw(2, 0, 3);
// S
draw(3, 1, 0);
draw(3, 2, 0);
draw(3, 0, 1);
draw(3, 1, 1)
draw(3, 1, 2);
draw(3, 2, 2)
draw(3, 0, 3);
draw(3, 1, 3);
draw(3, 2, 3);
// P
draw(4, 1, 0);
draw(4, 2, 0);
draw(4, 0, 1);
draw(4, 2, 1);
draw(4, 0, 2);
draw(4, 1, 2);
draw(4, 2, 2);
draw(4, 0, 3);
// A
draw(5, 1, 0);
draw(5, 2, 0);
draw(5, 0, 1);
draw(5, 2, 1);
draw(5, 0, 2);
draw(5, 1, 2);
draw(5, 2, 2);
draw(5, 0, 3);
draw(5, 2, 3);
// C
draw(6, 1, 0);
draw(6, 2, 0);
draw(6, 0, 1);
draw(6, 0, 2);
draw(6, 0, 3);
draw(6, 1, 3);
draw(6, 2, 3);
// E
draw(7, 1, 0);
draw(7, 2, 0);
draw(7, 0, 1);
draw(7, 2, 1);
draw(7, 0, 2);
draw(7, 0, 3);
draw(7, 1, 3);
draw(7, 2, 3);
// .
const zOff = 1
const zOffPx = zOff * 200
draw(8, 0, 3, zOff);
// J
draw(9, 2, 0, zOff);
draw(9, 2, 1, zOff);
draw(9, 0, 2, zOff);
draw(9, 2, 2, zOff);
draw(9, 0, 3, zOff);
draw(9, 1, 3, zOff);
draw(9, 2, 3, zOff);
// S
draw(10, 1, 0, zOff);
draw(10, 2, 0, zOff);
draw(10, 0, 1, zOff);
draw(10, 1, 1, zOff);
draw(10, 1, 2, zOff);
draw(10, 2, 2, zOff);
draw(10, 0, 3, zOff);
draw(10, 1, 3, zOff);
draw(10, 2, 3, zOff);
// Heading bounds
const headingBounds = heading.getBoundingBox()
// Intro
const descElement = document.getElementById('description')
const desc = tapspace.createItem(descElement)
desc.addClass('description')
space.addChild(desc, space.at(0, 800 + 200 * phipow(-1), zOffPx))
desc.setWidth(headingBounds.getWidth())
desc.setContentInput('handle')
// Recenter viewport
const bounds = space.getBoundingBox()
vp.translateTo(bounds.atCenter().offset(0, 0, -3000))
```
--------------------------------
### Initialize Tapspace View and Space
Source: https://github.com/taataa/tapspace/blob/master/features/geometry-measuring.html
Sets up the Tapspace environment by creating a view attached to a container and a space within that view. The view is made zoomable. This is the foundational setup for any Tapspace application.
```javascript
const container = document.querySelector('#tapspace')
const view = tapspace.createView(container).zoomable()
const space = tapspace.createSpace()
view.addChild(space)
```
--------------------------------
### Create and Style an Edge Component in JavaScript
Source: https://github.com/taataa/tapspace/blob/master/docs/api/v2/index.md
Demonstrates how to create an Edge component, add CSS classes for styling, append it to a group, and set its start and end points using tapspace. This example also shows basic CSS for styling the edge.
```javascript
const edge = tapspace.createEdge(2)
edge.addClass('my-edge')
edgeGroup.addChild(edge)
edge.setPoints(itemA.atBottomMid(), itemB.atTopMid())
.my-edge {
background: linear-gradient(0.25turn, black, white);
border-top: 2px dotted black;
}
```
--------------------------------
### Initialize Tapspace and Setup View Interactions
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/semanticzoom/index.html
Initializes the Tapspace environment, sets up a SpaceView, mounts it to a DOM element, and configures touch and wheel interactions for zooming and panning. It also defines a tap event handler to zoom into the view.
```javascript
// The example is wrapped within a function namespace, // because then we avoid global naming conflicts and // things are easier to debug. (function () {
// Init Tapspace
var space = new tapspace.Space()
var view = new tapspace.SpaceView(space)
view.mount(document.getElementById('space'))
// A heading text typical for the example apps.
const heading = new tapspace.SpaceHTML(
'' +
'
Semantic Zooming
' +
'
' +
'Zoom in and observe how the content changes. \n' +
'Created by listening the transformed event\n' +
'of SpaceView.\n' +
'
' +
'
' +
'Powered by ' +
'Tapspace.js
\n' +
'Emojis by OpenMoji
\n' +
'
' +
'
'
)
// Place heading on space.
heading.setParent(space)
heading.setSize(500, 300)
// Setup the view interaction
var viewtouch = new tapspace.Touchable(view, view)
var viewwheel = new tapspace.Wheelable(view, view)
// Pinch zoom and mouse wheel
viewtouch.start({
translate: true,
scale: true,
rotate: true,
tap: true
})
viewwheel.start({
scale: true
})
// Tap to zoom in
viewtouch.on('tap', function (ev) {
var itr = tapspace.geom.ITransform.IDENTITY
itr = itr.scale(tapspace.geom.IVector.mean(ev.points), 0.618)
view.transformBy(itr)
})
// Create the element that will react to zooming.
const reactor = new tapspace.SpaceHTML(
'Y U so far?
Come closer!
'
)
reactor.setParent(space)
reactor.setSize(300, 200)
reactor.translate(reactor.atMidN(), view.atNorm(0.5, 0.4))
// A helper function to detect if the view was scaled to a given range.
const scaledIn = (transformEv, lower, upper) => {
// Returns bool; true if transform scaled within bounds.
const oldScale = transformEv.oldTransform.getScale()
const newScale = transformEv.newTransform.getScale()
return newScale >= lower && newScale < upper && (oldScale >= upper || oldScale < lower)
}
// Listen to view's transformed event and modify the content accordingly.
view.on('transformed', function (ev) {
let content = null
if (scaledIn(ev, 0.1, 0.2)) {
// Very close distance
content = 'Too
close!'
document.getElementById('space').style.backgroundColor = 'red'
} else if (scaledIn(ev, 0.2, 0.4)) {
// Close distance
content = 'Close enough!
Have a cherry.
'
content += '
'
document.getElementById('space').style.backgroundColor = 'lightblue'
} else if (scaledIn(ev, 0.4, 0.8)) {
// Medium distance
content = 'A bit closer still...'
} else if (scaledIn(ev, 0.8, 2.0)) {
// Initial far distance
content = 'Y U so far?
Come closer!'
}
// Update the content if necessary.
if (content) {
const el = document.getElementById('reactor')
el.innerHTML = content
}
})
})()
// execute the example
```
--------------------------------
### JavaScript: Setup Tapspace Viewport and Scale-free Background
Source: https://github.com/taataa/tapspace/blob/master/features/geometry-background.html
Initializes the Tapspace viewport, creates a space, and adds a background item. It then sets up an 'idle' event listener to dynamically adjust the background size based on the viewport's zoom level, creating a scale-free effect.
```javascript
// Setup the tapspace viewport and the default layer for content.
const viewport = tapspace.createView('#tapspace').zoomable()
const space = tapspace.createSpace()
viewport.addChild(space)
const bgitem = tapspace.createItem()
bgitem.addClass('bgitem')
bgitem.setSize(800, 800)
space.addChild(bgitem)
viewport.zoomTo(bgitem)
viewport.on('idle', () => {
// Calculate how many zoom levels the apparent scale amounts to.
const scale = viewport.measureDilation(bgitem)
const level = Math.floor(Math.log2(scale))
const poslevel = Math.max(0, level)
// Convert discrete zoom level back to scale and apply to bg size.
const percentage = 100 / Math.pow(2, poslevel)
const percentStr = percentage.toFixed(8) + '%'
bgitem.getElement().style.backgroundSize = percentStr
})
```
--------------------------------
### Set and Get Item Scale in Tapspace
Source: https://github.com/taataa/tapspace/blob/master/test/components/Item/setScale.html
This snippet demonstrates setting an item's scale using a specific value and retrieving the current scale. It also shows how to match the scale of one item to another and verify the scale transformation.
```javascript
const t = test t.plan(2) // Setup
const view = tapspace.createView('#testspace')
const space = tapspace.createSpace()
view.addChild(space)
const ref = tapspace.createItem('Hello
')
ref.setSize(200, 200)
ref.setAnchor(0, 0)
space.addChild(ref)
ref.setScale(2)
const item = tapspace.createItem('World
')
item.setSize(200, 200)
item.setAnchor(0, 0)
space.addChild(item)
// Match scale
item.setScale(ref.getScale(), item.atBottomRight())
const p = item.at(0, 0).changeBasis(space)
const p0 = space.at(-200, -200)
t.ok(p.almostEqual(p0), 'should have doubled about corner')
t.equal( item.getScale().transitRaw(space), 2, 'should have correct scale' )
```
--------------------------------
### Configure Tapspace View Interactions
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/password/index.html
Enables touch and wheel interactions for the Tapspace view, allowing users to pan, zoom, and rotate. This setup is crucial for creating an interactive user experience within the Tapspace canvas.
```javascript
// Setup the view interaction
var viewtouch = new tapspace.Touchable(view, view)
var viewwheel = new tapspace.Wheelable(view, view)
viewtouch.start({ translate: true, scale: true, rotate: true, tap: true })
viewwheel.start({ scale: true })
```
--------------------------------
### tapspace TreeLoader Configuration Example
Source: https://github.com/taataa/tapspace/blob/master/docs/api/v2/index.md
A comprehensive configuration example for the TreeLoader, including the viewport, mapper, and backmapper functions. The mapper function determines the child's position relative to the parent, returning a Basis or null if no mapping is available.
```javascript
const loader = new tapspace.loaders.TreeLoader({
viewport: viewport,
mapper: function (parentId, parent, childId) {
// Find the location for the child, relative to the parent.
// The return value must be a Basis.
// Get the parent basis, and transform it as you like.
// Return null if there is no place for the child.
const data = store[parentId]
const dataPoint = data.points[childId]
if (dataPoint) {
return parent.getBasis().offset(dataPoint.x, dataPoint.y)
}
return null
},
// ... other configuration options like backmapper, tracker, backtracker
```
--------------------------------
### CSS Styling for Tapspace Canvas
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/infinity/index.html
Basic CSS to set up the full-screen canvas and heading styles for the Tapspace example. It ensures the background is black and text is readable.
```css
html, body, #space { margin: 0; padding: 0; width: 100%; height: 100%; background: black; color: black; font-family: sans-serif; }
#heading { padding: 0 1em 0 1em; }
#heading h1 { font-size: 2.62em; margin: 0.38em 0 0 0; }
#heading p { font-size: 1em; margin: 0.25em 0 0 0; text-align: right; }
#heading a { color: black; text-decoration: underline; }
```
--------------------------------
### Basic CSS for Tapspace Example
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/modes/index.html
Provides essential CSS rules for the Tapspace example, ensuring the space element fills the viewport and setting basic styling for the body and links.
```css
html, body, #space { margin: 0; padding: 0; width: 100%; height: 100%; }
body { font-size: 16px; color: white; background: #666; font-family: sans-serif; }
a { color: cyan; }
```
--------------------------------
### Tapspace Setup and Vis.js Network Creation
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/visjs/index.html
Initializes Tapspace with a SpaceView and makes it transformable using Touchable and Wheelable. It defines a function to create Vis.js networks at specified points, recursively generating subgraphs with nodes and edges. The Vis.js network is configured to disable internal navigation, ensuring Tapspace handles all interactions.
```javascript
(function tapspaceApp () {
// Tapspace setup
var space = new tapspace.Space()
var viewElement = document.getElementById('space')
var view = new tapspace.SpaceView(space)
view.mount(viewElement)
// Make the view transformable
var touchy = new tapspace.Touchable(view, view)
touchy.start({ translate: true, scale: true })
var scrolly = new tapspace.Wheelable(view, view)
scrolly.start({ scale: true })
var createVisNetworkAt = function (point, depth, prefix) {
// Parameters:
// point
// an IVector, the insertion point for the subgraph.
// depth
// a number, the larger the smaller.
// prefix
// a string, a path-like label prefix to append at each iteration.
// A container for a vis.js network
var networkItem = new tapspace.SpaceHTML('', space)
var networkElement = view.getElementBySpaceItem(networkItem)
// Uncomment to make canvas areas visible:
// networkElement.style.background = 'rgba(200,200,200,0.2)'
// Position the canvas container.
// Make the canvas large so that zooming in tapspace
// does not blur it so quickly.
networkItem.setSize(1000, 1000)
networkItem.translate(networkItem.atMid(), point)
networkItem.scale(networkItem.atMid(), 1 / Math.pow(2, depth))
// Create nodes
var nodes = new vis.DataSet([
{ // The local root node
id: 1,
label: prefix,
x: 0,
y: 0,
value: 20
},
{ id: 2, label: prefix + '.1', value: 10 },
{ id: 3, label: prefix + '.2', value: 10 },
{ id: 4, label: prefix + '.3', value: 10 },
{ id: 5, label: prefix + '.4', value: 10 },
{ id: 6, label: prefix + '.5', value: 10 }
])
// Create edges
var edges = new vis.DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 1, to: 4 },
{ from: 1, to: 5 },
{ from: 1, to: 6 },
])
// Create the network
var data = {
nodes: nodes,
edges: edges
}
var options = {
// Disable vis.js internal navigation to prevent event capture
// so we can rely on tapspace navigation.
interaction: {
dragNodes: false,
dragView: false,
keyboard: false,
zoomView: false,
selectable: false,
selectConnectedEdges: false
},
// Predictable layout that keeps the middle node at {x:0,y:0}
layout: {
randomSeed: '0.7985338123976358:1650403904927'
},
// Node styling
nodes: {
shape: 'dot',
scaling: {
min: 0,
max: 30,
customScalingFunction: function (min, max, total, value) {
return value / max
}
}
},
// Prevent refitting nodes to the canvas after stabilization,
// to ensure that the middle node is always at the canvas center.
physics: {
stabilization: {
fit: true
}
}
}
var network = new vis.Network(networkElement, data, options)
network.on('stabilized', function () {
network.moveTo({ position: { x: 0, y: 0 }, scale: 2 })
})
// Vis.js uses Hammer.js for gestures and their coordinates
// are not compatible with Tapspace's way to position elements.
// Fortunately we can use Tapspace's coordinates to command Viz.
var tapy = new tapspace.Touchable(view, networkItem)
tapy.start({ tap: true, preventDefault: false })
tapy.on('tap', function (ev) {
// Convert viewport coordinates on the canvas.
var pointOnView = ev.points[0] // an IVector
var pointOnCanvas = pointOnView.to(networkItem) // Select node at tap position.
// Node ID is null if not found.
var clickedNodeId = network.getNodeAt(pointOnCanvas)
if (clickedNodeId && clickedNodeId !== 1) {
// Emphasize node by selecting it
// network.selectNodes([clickedNodeId])
// Create a subgraph at the node center.
// Get node center position. It is in Vis's "canvas coordinates"
var nodePoint = network.getPosition(clickedNodeId)
// Convert to coordinates on the canvas element.
var domPoint = network.canvasToDOM(nodePoint)
// Convert to plane-invariant coordinates.
var nodePointV = new tapspace.geom.Vector(domPoint.x, domPoint.y)
var nodePointIV = new tapspace.geom.IVector(nodePointV, networkItem)
// Insert the new network.
var insertAt = nodePointIV
var nextDepth = depth + 1
var nextPrefix = nodes.get(clickedNodeId).label
createVisNetworkAt(insertAt, nextDepth, nextPrefix)
// Hide the old big label.
nodes.update({ id: clickedNodeId, label: null })
// Uncomment to debug coordinates:
// console.log('nodePoint', nodePoint)
// console.log('domPoint', domPoint)
} else {
// Uncomment to inspect the root node position:
// if (clickedNodeId === 1) {
// var nodePoint = network.getPosition(clickedNodeId)
// console.lo
}
})
}
// Initialize the first network
createVisNetworkAt(new tapspace.geom.IVector(0, 0), 0, 'Root')
})()
```
--------------------------------
### CSS for Tapspace Example
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/tunnel/index.html
Provides basic CSS styling for the Tapspace example, including resetting default margins and paddings, setting dimensions for the space, and defining styles for the heading and end elements.
```css
html, body, #space { margin: 0; padding: 0; width: 100%; height: 100%; background: white; color: black; font-family: sans-serif; }
#heading { padding: 1em 0 0 1em; }
#heading h1 { font-size: 2.62em; margin: 0.38em 0 0 0; }
#heading p { font-size: 1em; margin: 0.25em 0 0 0.5em; }
#heading p.credits { margin-top: 0.7em; }
#heading a { color: black; text-decoration: underline; }
#heading a:hover { color: gray; }
#theend { text-align: center; }
```
--------------------------------
### Setup Tapspace Viewport and Content Layer (JavaScript)
Source: https://github.com/taataa/tapspace/blob/master/features/viewport-navigation-scalefree.html
Initializes a zoomable Tapspace viewport and a default layer for content. It then defines a template for content blocks and generates a grid of items with varying scales and positions within the space. This demonstrates the core setup for scale-free navigation.
```javascript
// Setup the tapspace viewport and the default layer for content.
const view = tapspace.createView('#tapspace').zoomable()
const space = tapspace.createSpace()
view.addChild(space)
// Content template for blocks. Blocks give us visual reference.
const template = (t) => '' + t + '
'
const items = []
const W = 8
const H = 3
const D = 5
let xi, yi, zi, item
for (xi = 0; xi < W; xi += 1) {
for (yi = 0; yi < H; yi += 1) {
for (zi = 0; zi < D; zi += 1) {
const scale = 1 / ((1 + xi) * (1 + xi))
const label = scale.toFixed(2)
const item = tapspace.createItem(template(label))
item.addClass('mycomponent')
item.setSize(50, 20)
space.addChild(item, space.at(xi * 80, yi * 50, zi * 80))
item.setScale(scale, item.atAnchor())
item.setContentInput(false)
}
}
}
```
--------------------------------
### Tapspace Fractal Content Loader Setup
Source: https://github.com/taataa/tapspace/blob/master/features/loaders-fractal.html
Initializes the Tapspace viewport and sets up the TreeLoader for fractal content. It defines essential parameters like radii, steps, and angles, along with mapping functions for child and parent spaces, and a function to track child space IDs. This setup is crucial for the recursive loading mechanism.
```javascript
const viewport = tapspace.createView('#tapspace')
viewport.zoomable().setMeasureMode('none')
const circleRadius = 50
const frontierRadius = 300
const depthStep = 20
const scaleStep = 1 / 3
const angleStep = Math.PI / 6
// Short alias
const R = circleRadius
const FR = frontierRadius
const DD = depthStep
const M = scaleStep
const ROT = angleStep
const mapper = (parentId, parentSpace, childId) => {
// Create a basis for a child space.
const parentBasis = parentSpace.getBasis()
const innerAnchorBasis = parentBasis.offset(R, R, DD).scaleBy(M)
const radius = innerAnchorBasis.createDistance(FR)
const lastChar = childId.slice(-1)
switch (lastChar) {
case '0':
return innerAnchorBasis
.polarOffset(radius, -ROT)
.rotateBy(-ROT)
.offset(-R, -R)
case '1':
return innerAnchorBasis
.polarOffset(radius, 0)
.offset(-R, -R)
case '2':
return innerAnchorBasis
.polarOffset(radius, ROT)
.rotateBy(ROT)
.offset(-R, -R)
default:
return null
}
}
const backmapper = (childId, childSpace, parentId) => {
// Create a basis for the parent space. Optional.
const childBasis = childSpace.getBasis()
const radius = childBasis.createDistance(FR)
const lastChar = childId.slice(-1)
switch (lastChar) {
case '0':
return childBasis.offset(R, R)
.scaleBy(1 / M)
.rotateBy(ROT)
.polarOffset(radius, 5 * ROT)
.offset(-R, -R, -DD)
case '1':
return childBasis.offset(R, R)
.scaleBy(1 / M)
.polarOffset(radius, Math.PI)
.offset(-R, -R, -DD)
case '2':
return childBasis.offset(R, R)
.scaleBy(1 / M)
.rotateBy(-ROT)
.polarOffset(radius, -5 * ROT)
.offset(-R, -R, -DD)
default:
return null
}
}
const tracker = (parentId) => {
// Find child space IDs.
return [parentId + '0', parentId + '1', parentId + '2']
}
const backtracker = (childId) => {
// Find parent space ID.
if (childId.length <= 1) {
return null
}
const parentId = childId.substring(0, childId.length - 1)
return parentId
}
const getDepth = (id) => {
return id.length - 1
}
const getColor = (id) => {
const d = getDepth(id)
const hue = 5 * d
const light = Math.min(10 * d, 40)
const color = 'hsl(' + hue + 'deg 90% ' + light + '%)'
return color
}
const squareText = (str, containerWidthPx) => {
const len = str.length
// const lenpx = len * 16 // TODO 1em, square character
// const lineheight = 16 // TODO 1em
// Best square layout near square root of the number of characters.
const ratio = 2 // ratio width / height
const width = Math.ceil(Math.sqrt(ratio * len))
const height = Math.ceil(width / ratio)
const lines = []
for (let i = 0; i < height; i += 1) {
const candidate = str.substring(i * width, (i + 1) * width)
// TODO adjust white space
if (candidate.length > 0) {
lines.push(candidate)
}
}
const fontSize = (containerWidthPx / width).toFixed(1)
const style = 'padding: 0; margin: 0; line-height: 1em;' + 'font-size: ' + fontSize + 'px;'
return '' + lines.join('
') + '
'
}
const loader = new tapspace.loaders.TreeLoader({
viewport: viewport,
mapper: mapper,
backmapper: backmapper,
tracker: tracker,
backtracker: backtracker
})
// Constructor
loader.on('open', (ev) => {
const size = R
const color = getColor(ev.id)
const node = tapspace.createNode(size, color)
node.html('' + squareText(ev.id, 2 * R))
node.addClass('fractal-node')
node.spaceId = ev.id
// TODO use WeakMap in TreeLoader to prevent this.
// Tap to match orientation.
node.tappable({ preventDefault: false })
node.on('tap', () => {
const orient = node.getOrientation()
viewport.animateOnce({ duration: '500ms' })
viewport.setOrientation(orient, node.atCenter())
})
node.setContentInput('false')
// Space ready
loader.addSpace(ev.id, node)
})
// Destructor
loader.on('close', (ev) => {
loader.removeSpace(ev.id)
})
// Driver
viewport.on('idle', (ev) => {
const spaces = viewport.getSpaces()
const metrics = viewport.measureNearest(spaces, 2)
if (metrics.length > 0) {
const nearest = metrics[0].target
// Grow and prune
loader.openNeighbors(nearest.spaceId, 2)
loader.closeNeighbors(nearest.spaceId, 4)
}
})
loader.initSpace('001', viewport.getBasis())
loader.once('opened', (ev) => {
loader.openNeighbors(ev.id, 2)
const contentBounds = viewport.getHyperspace().getBoundingCircle()
const fractalCenter = contentBounds.atCenter()
viewport.translateTo(fractalCenter)
})
// Uncomment for automatic viewport orientation.
// viewport.on('idle', () => {
```
--------------------------------
### Setup Tapspace Viewport and Layers (JavaScript)
Source: https://github.com/taataa/tapspace/blob/master/features/interaction-tap.html
Initializes the Tapspace viewport and creates a default layer for content. This setup is essential for rendering and managing elements within the Tapspace environment. It requires the tapspace library to be loaded.
```javascript
// Setup the tapspace viewport and the default layer for content.
const viewport = tapspace.createView('#tapspace')
const space = tapspace.createSpace()
vport.addChild(space)
const layer = tapspace.createSpace()
space.addChild(layer)
```
--------------------------------
### Get Edge Start Point in JavaScript
Source: https://github.com/taataa/tapspace/blob/master/docs/api/v2/index.md
Retrieves the Point object representing the start of the edge, specifically at the middle of its border. This method is part of the Edge component's API.
```javascript
const startPoint = edge.atStart();
```
--------------------------------
### Get Bounding Circle of an Item
Source: https://github.com/taataa/tapspace/blob/master/test/geometry/Box/getBoundingCircle.html
This snippet demonstrates how to create a view and a space, add a node item, get its bounding box, and then calculate its bounding circle. It also shows how to change the basis of the circle and compare it with an expected circle.
```javascript
const t = test t.plan(1) // Setup
const view = tapspace.createView('#testspace')
const space = tapspace.createSpace()
view.addChild(space)
const item = tapspace.createNode(10, 'black')
space.addChild(item, space.at(10, 20, 30))
// Get a box
const box = item.getBoundingBox()
// Get circle boundary
const circle = box.getBoundingCircle()
const c = circle.changeBasis(view)
const c0 = new tapspace.geometry.Circle(view, { x: 10, y: 20, z: 30, r: Math.sqrt(200) })
t.ok(c.almostEqual(c0), 'should have larger circle')
```
--------------------------------
### Get Bounding Sphere and Compare in Tapspace
Source: https://github.com/taataa/tapspace/blob/master/test/geometry/Box/getBoundingSphere.html
This snippet demonstrates obtaining the bounding sphere of a Tapspace item, changing its basis, and comparing it with an expected sphere. It requires the tapspace library.
```javascript
const t = test t.plan(1) // Setup
const view = tapspace.createView('#testspace')
const space = tapspace.createSpace()
view.addChild(space)
const item = tapspace.createNode(10, 'black')
space.addChild(item, space.at(10, 20, 30)) // Get a box
const box = item.getBoundingBox()
// Get spherical boundary
const sphere = box.getBoundingSphere()
const s = sphere.changeBasis(view)
const s0 = new tapspace.geometry.Sphere(view, { x: 10, y: 20, z: 30, r: Math.sqrt(200) })
t.ok(s.almostEqual(s0), 'should have larger sphere')
```
--------------------------------
### Tapspace Initialization and DOM Mounting
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/go/index.html
Initializes the Tapspace environment, creates a SpaceView, and mounts it to a DOM container. This sets up the main canvas for rendering.
```javascript
var space = new tapspace.Space()
var container = document.getElementById('space')
var view = new tapspace.SpaceView(space)
view.mount(container)
```
--------------------------------
### Initialize Tapspace Space and View
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/password/index.html
Sets up the Tapspace environment by creating a Space and a SpaceView. The view is then mounted to a DOM element. This is the foundational step for any Tapspace application.
```javascript
// Wrap in a function namespace. Easier to debug and no conflicts. (function () {
var space = new tapspace.Space()
var view = new tapspace.SpaceView(space)
view.mount(document.getElementById('space'))
```
--------------------------------
### Initialize Tapspace and Load Assets
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/gears/index.html
Initializes the Tapspace environment, sets up the view, and preloads necessary image assets for the gear animation. It handles potential errors during asset loading and proceeds to create and position the gear elements once assets are ready.
```javascript
var SpaceGroup = tapspace.SpaceGroup
var SpaceImage = tapspace.SpaceImage
var SpaceHTML = tapspace.SpaceHTML
var space = new tapspace.Space()
var view = new tapspace.SpaceView(space)
view.mount(document.getElementById('space'))
// Load images
tapspace.preload([
'../assets/gear18.png',
'../assets/gear11.png',
'../assets/gearhandle.png'
], function (err, imgs) {
if (err) {
console.error(err)
throw err
}
var gear18Img = imgs[0]
var gear11Img = imgs[1]
var gearhandleImg = imgs[2]
var touchmode = { rotate: true }
// Create
var gears = new SpaceGroup(space)
var gear18a = new SpaceGroup(gears)
var gear18ai = new SpaceImage(gear18Img, gear18a)
var gear18ahandle = new SpaceImage(gearhandleImg)
gear18a.addChild(gear18ahandle)
var gear18b = new SpaceGroup(gears)
var gear18bi = new SpaceImage(gear18Img, gear18b)
var gear18bhandle = new SpaceImage(gearhandleImg, gear18b)
var gear11 = new SpaceImage(gear11Img, gears)
// Position
gear18a.translate(gear18a.atMid(), space.at(0, 0))
gear11.translate(gear11.atMid(), space.at(321, 245))
gear18ahandle.translate(
gear18ahandle.atMid(),
gear18ai.atMidN().offset(0, 160)
)
gear18b.translate(gear18b.atMid(), space.at(641, 0))
gear18b.rotate(gear18b.atMid(), 0.163)
gear18bhandle.translate(
gear18bhandle.atMid(),
gear18b.atMid().offset(0, 120)
)
// Define interaction. Redirect manipulation of the handles
// to gear18a. Note that we connect the b-handle to gear a.
var ahandleTouch = new tapspace.Touchable(view, gear18ahandle, gear18a)
var bhandleTouch = new tapspace.Touchable(view, gear18bhandle, gear18b)
ahandleTouch.start({ rotate: true, pivot: gear18a.atMid() })
bhandleTouch.start({ rotate: true, pivot: gear18b.atMid() })
// Initial view position
view.fitScale(gears)
view.scale(gears.atMid(), 1.23)
})
```
--------------------------------
### Initialize NodePoint and Network Visualization
Source: https://github.com/taataa/tapspace/blob/master/docs/examples/visjs/index.html
This snippet initializes the 'nodePoint' and creates a root network visualization at a specified view. It also includes a commented-out section for logging layout seeds after a delay, useful for debugging.
```javascript
g('nodePoint', nodePoint) // } } })
// Uncomment to find alternative layout seeds:
// setTimeout(function () {
// console.log('layoutSeed', network.getSeed())
// }, 500)
}
// Init root network
createVisNetworkAt(view.atMid(), 1, 'Node 1')
})()
```