### 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') })() ```