Zum Hauptinhalt springen
Diese Seite wurde automatisch übersetzt und kann Fehler enthalten. Original auf Englisch ansehen

References

The tact-js package provides functions for controlling bHaptics haptic devices from JavaScript. It enables you to play haptic patterns, control device motors directly, and manage haptic playback.

import Tact from "tact-js";

Play Event-driven Haptic

Play haptic patterns bound to specific events (designed in the bHaptics Designer/Portal). These are the recommended functions for most applications.

play

play({ eventKey, startTime, intensityRatio, durationRatio, offsetX, offsetY, deviceIndex }: PlayParams): Promise<void>;

type PlayParams = {
eventKey: string; // Name of the haptic event
startTime?: number; // Playback start position in milliseconds
intensityRatio?: number; // Intensity multiplier [0.0 - 2.0]
durationRatio?: number; // Duration multiplier
offsetX?: number; // Rotation offset [0.0 - 360.0]
offsetY?: number; // Vertical offset [-0.5 - 0.5]
deviceIndex?: number; // Target device index
};

Play the predefined haptic event.

Parameters

  • eventKey: Name of the haptic event.
  • startTime(optional): Playback start position in milliseconds — the first startTime milliseconds of the event are skipped. For example, playing a 3,260ms event with startTime: 2000 plays only the last 1,260ms. (Default: 0)
  • intensityRatio(optional): Multiplier for haptic intensity. Valid range is: [0.0 - 2.0] (Default: 1.0)
  • durationRatio(optional): Multiplier for duration. (Default: 1.0)
  • offsetX(optional): Rotate haptic counterclockwise. Valid range is: [0.0 - 360.0] (Default: 0.0)
  • offsetY(optional): Move haptic up or down. Valid range is: [-0.5 - 0.5] (Default: 0.0)
  • deviceIndex(optional): Index of the device to target when multiple devices of the same position type are connected. (Default: -1, no specific device)

Returns

The promise resolves with no value (undefined) once the request is sent to bHaptics Player.

Note that it also resolves normally when the event key is not registered — in that case nothing plays and no error is thrown. Use getEvent to check whether an event key exists.

Example

import Tact from "tact-js";

const playExample = async () => {
await Tact.play({ eventKey: "heartbeat" });
};

const playMoreExample = async () => {
await Tact.play({
eventKey: "hit",
startTime: 0,
intensityRatio: 1.0,
durationRatio: 1.0,
offsetX: 180.0,
offsetY: 0.25,
});
};

playLoop

playLoop({ eventKey, intensityRatio, durationRatio, interval, maxCount, offsetX, offsetY, deviceIndex }: PlayLoopParams): Promise<number>;

type PlayLoopParams = {
eventKey: string; // Name of the haptic event
intensityRatio?: number; // Intensity multiplier [0.0 - 2.0]
durationRatio?: number; // Duration multiplier
interval: number; // Pause between repetitions (milliseconds)
maxCount: number; // Total number of plays
offsetX: number; // Rotation offset [0.0 - 360.0]
offsetY: number; // Vertical offset [-0.5 - 0.5]
deviceIndex?: number; // Target device index
};

Play the haptic event in a loop for a specified number of times.

Parameters

  • eventKey: Name of the haptic event.
  • intensityRatio(optional): Multiplier for haptic intensity. Valid range is: [0.0 - 2.0] (Default: 1.0)
  • durationRatio(optional): Multiplier for duration. (Default: 1.0)
  • interval: Pause between repetitions in milliseconds, measured from the end of one playback to the start of the next. For example, a 460ms event with interval: 500 and maxCount: 3 finishes after about 2,380ms (460 + 500 + 460 + 500 + 460).
  • maxCount: Total number of times to play the haptic event, including the first play. Values less than 1 behave as 1.
  • offsetX: Rotate haptic counterclockwise. Valid range is: [0.0 - 360.0] (Default: 0.0)
  • offsetY: Move haptic up or down. Valid range is: [-0.5 - 0.5] (Default: 0.0)
  • deviceIndex(optional): Index of the device to target when multiple devices of the same position type are connected. (Default: -1, no specific device)

Returns

Request ID identifying this playback request.

Note that a request ID is returned even when the event key is not registered — in that case nothing plays. To stop a looping event, use stop with the event key or stopAll.

While the loop is running, isPlayingByEventKey returns true for the whole span, including the interval pauses between repetitions.

Example

import Tact from "tact-js";

const playLoopExample = async () => {
const requestId = await Tact.playLoop({
eventKey: "hit",
intensityRatio: 1.0,
durationRatio: 1.0,
interval: 1000,
maxCount: 5,
offsetX: 0.0,
offsetY: 0.0,
});

console.log(`Playback request ID: ${requestId}`);
};

Play Haptic Directly

If you want to play haptics without events, use these functions.

playDot

playDot({ position, motorValues, duration, deviceIndex }: PlayDotParams): Promise<number>;

type PlayDotParams = {
position: PositionType; // Device position type
motorValues: number[]; // Array of motor intensity values [0 - 100]
duration?: number; // Duration in milliseconds
deviceIndex?: number; // Target device index
};

Play haptic feedback on the specific haptic actuators.

Parameters

  • position: Type of haptic device to playback. Refer the PositionType enum.
  • motorValues: Array of intensity values for each motor. The array length must match the number of motors in the device. Each value must be integer and in range. Valid range is: [0 - 100].
  • duration(optional): Duration of haptic feedback in milliseconds. Greater than or equal to 100 is recommended.
  • deviceIndex(optional): Index of the device to target when multiple devices of the same position type are connected. (Default: -1, no specific device)

Returns

Request ID identifying this playback request. To stop playback, use stopAll.

Note that the parameters are not validated client-side — a request ID is returned even when, for example, motorValues has a wrong length or contains out-of-range values; in that case the haptic may simply not play.

Example

import Tact, { PositionType } from "tact-js";

const playDotExample = async () => {
const requestId = await Tact.playDot({
position: PositionType.ForearmL, // Left TactSleeve
motorValues: [100, 80, 60], // TactSleeve has 3 motors
duration: 100
});

console.log(`Playback request ID: ${requestId}`);
}

playPath

playPath({ position, x, y, intensity, duration, deviceIndex }: PlayPathParams): Promise<number>;

type PlayPathParams = {
position: PositionType; // Device position type
x: number[]; // Array of x coordinates [0.0 - 1.0]
y: number[]; // Array of y coordinates [0.0 - 1.0]
intensity: number[]; // Array of intensity values [0 - 100]
duration?: number; // Duration in milliseconds
deviceIndex?: number; // Target device index
};

Play haptic feedback along specified coordinates. Unlike playDot which controls individual motors, this method specifies haptic intensity for particular coordinates on the device.

When specifying haptic position, playDot offers discrete control, while playPath is more continuous. playDot assigns intensity to individual actuators, whereas playPath allows intensity specification for specific coordinates (between 0 and 1 for both X and Y axis), causing nearby actuators to vibrate accordingly.

You can specify multiple coordinates with multiple intensities. Note that all actuators around these coordinates in the list will activate simultaneously, not sequentially. The size of all arrays (x, y, and intensity) must be the same.

warnung

If the x, y, and intensity arrays have different lengths, the SDK's internal WebAssembly module crashes with an unrecoverable error (verified in tact-js 2.0.4) — haptics stop working until the page is reloaded. Always make sure the three arrays have the same length before calling.

By continuously calling this function while gradually changing the values, you can achieve the effect of a moving haptic point.

Coordinate

Parameters

  • position: Type of haptic device to playback. Refer the PositionType enum.
  • x: Array of X coordinates for the haptic effect. Each value must be in range: [0.0 - 1.0]
  • y: Array of Y coordinates for the haptic effect. Each value must be in range: [0.0 - 1.0]
  • intensity: Array of intensity values for each coordinate. Each value must be integer and in range: [0 - 100]
  • duration(optional): Duration of haptic feedback in milliseconds. Greater than or equal to 100 is recommended.
  • deviceIndex(optional): Index of the device to target when multiple devices of the same position type are connected. (Default: -1, no specific device)

Returns

Request ID identifying this playback request. To stop playback, use stopAll.

Example

import Tact, { PositionType } from "tact-js";

const HAPTIC_PATHS = [
{
x: [0.738, 0.723, 0.709, 0.696, 0.682, 0.667, 0.653],
y: [0.680, 0.715, 0.749, 0.782, 0.816, 0.852, 0.885],
intensity: 20
},
{
x: [0.061, 0.072, 0.102, 0.184, 0.254, 0.310, 0.363],
y: [0.632, 0.587, 0.542, 0.498, 0.411, 0.366, 0.301],
intensity: 60
}
];

const TIME_OF_FRAME = 250; // milliseconds

const playPathExample = async () => {
const frames = HAPTIC_PATHS[0].x.length;

for (let i = 0; i < frames; i++) {
await Tact.playPath({
position: PositionType.Vest, // TactSuit
x: HAPTIC_PATHS.map(point => point.x[i]),
y: HAPTIC_PATHS.map(point => point.y[i]),
intensity: HAPTIC_PATHS.map(point => point.intensity),
duration: TIME_OF_FRAME
});
await new Promise(resolve => setTimeout(resolve, TIME_OF_FRAME));
}
}

playGlove

playGlove({ position, motors, playtimes, shapes, repeatCount }: PlayGloveParams): Promise<number>;

type PlayGloveParams = {
position: PositionType; // GloveL or GloveR
motors: Int32Array; // Array of 8 motor intensity values [0 - 100]
playtimes: Int32Array; // Array of 8 time interval values
shapes: Int32Array; // Array of 8 waveform values
repeatCount: number; // Number of times to play the pattern
};

TactGlove Only. Play haptics in TactGlove with fine-grained control over duration and intensity patterns. This provides more detailed control compared to playDot.

Each array parameter must contain exactly eight elements, one for each motor in the glove.

Parameters

  • position: Type of haptic device to playback. Must use PositionType.GloveL or PositionType.GloveR.

  • motors: Array of 8 intensity values, one per motor. Each value must be integer and in range: [0 - 100]

    Array IndexMotor is positioned at…
    0Tip of the thumb
    1Tip of the index finger
    2Tip of the middle finger
    3Tip of the ring finger
    4Tip of the little finger
    5On the wrist
    6On the palm (thumb side)
    7On the palm (little finger side)
  • playtimes: Array of 8 time interval values. Valid values are:

    ValueDuration
    15ms
    210ms
    420ms
    630ms
    840ms
  • shapes: Array of 8 waveform values controlling how intensity changes over time:

    ValueWaveform Pattern
    0Constant intensity for the duration
    1Starts at specified intensity and decreases by half
    2Starts at half intensity and increases to full
  • repeatCount: Total number of times to play the 8-motor pattern, including the first play.

Returns

Request ID identifying this playback request. To stop playback, use stopAll.

Example

import Tact, { PositionType } from "tact-js";

const playGloveExample = async () => {
const motors = new Int32Array([100, 100, 100, 100, 100, 100, 100, 100]);
const playtimes = new Int32Array([8, 8, 8, 8, 8, 8, 8, 8]);
const shapes = new Int32Array([2, 2, 2, 2, 2, 2, 2, 2]);

const requestId = await Tact.playGlove({
position: PositionType.GloveR,
motors,
playtimes,
shapes,
repeatCount: 3
});

console.log(`Playback request ID: ${requestId}`);
}

Playback Control

pause

pause(eventKey: string): Promise<void>

Pause a specific haptic event that is currently playing.

Parameters

  • eventKey: Name of the haptic event to pause.

Example

import Tact from "tact-js";

const playAndPauseExample = async () => {
await Tact.play({ eventKey: "dash" });
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.pause("dash");
}

resume

resume(eventKey: string): Promise<void>

Resume a previously paused haptic event.

Parameters

  • eventKey: Name of the haptic event to resume.

Example

import Tact from "tact-js";

const playPauseAndResumeExample = async () => {
await Tact.play({ eventKey: "dash" });
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.pause("dash");
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.resume("dash");
}

stop

stop(eventKey: string): Promise<void>

Stop a specific haptic event completely.

Parameters

  • eventKey: Name of the haptic event to stop.

Example

import Tact from "tact-js";

const stopExample = async () => {
await Tact.play({ eventKey: "dash" });
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.stop("dash");
}

stopAll

stopAll(): Promise<void>

Stop all currently playing haptics.

Example

import Tact from "tact-js";

const stopAllExample = async () => {
await Tact.play({ eventKey: "dash" });
await Tact.play({ eventKey: "heartbeat" });
await Tact.play({ eventKey: "hit" });
await Tact.play({ eventKey: "slash" });
await new Promise(resolve => setTimeout(resolve, 500));

await Tact.stopAll();
}

Lifecycle

init

init({ appId, apiKey }: InitParams): Promise<boolean>;

type InitParams = {
appId: string; // Your bHaptics App ID
apiKey: string; // Your bHaptics API Key
};

Initialize the bHaptics SDK. This function must be called before using any other functions in the SDK. It initializes the SDK and establishes connection with bHaptics Player.

Parameters

  • appId: Your bHaptics application ID from the bHaptics Developer Portal
  • apiKey: Your bHaptics API key from the bHaptics Developer Portal

Returns

Returns true if initialization is successful, false otherwise.

Example

import Tact from "tact-js";

const initTact = async () => {
const result = await Tact.init({
appId: "your-app-id",
apiKey: "your-api-key",
});

console.log(result ? "Connection Success!" : "Connection Failed...");
}

Status Checking

getConnectedDevices

getConnectedDevices(): Promise<any[]>

Get a list of all connected haptic devices.

Returns

Array of connected device objects. Returns an empty array ([]) when no devices are connected. Each object has the following fields:

FieldTypeDescription
positionnumberNumeric position of the device: 0 Vest, 1 ForearmL, 2 ForearmR, 3 Head, 4 HandL, 5 HandR, 6 FootL, 7 FootR, 8 GloveL, 9 GloveR. Use PositionUtils.positionToType(position) to convert it to a PositionType.
deviceNamestringDisplay name of the device (e.g. "TactGlove (L)").
addressstringMAC address of the device. Use it with ping.
connectedbooleanWhether the device is currently connected.
pairedbooleanWhether the device is paired in bHaptics Player.
batterynumberBattery level in percent.
audioJackInbooleanWhether an audio jack is plugged in (audio-accessory devices).
vsmnumberVibration strength setting configured in bHaptics Player.

The example of return value follows:

[
{
"position": 8,
"deviceName": "TactGlove (L)",
"address": "F418EB165E99",
"connected": true,
"paired": true,
"battery": 91,
"audioJackIn": false,
"vsm": 20
},
{
"position": 9,
"deviceName": "TactGlove (R)",
"address": "DF8B33412EC5",
"connected": true,
"paired": true,
"battery": 84,
"audioJackIn": false,
"vsm": 20
}
]

Example

import Tact from "tact-js";

const showDevicesExample = async () => {
const devices = await Tact.getConnectedDevices();
console.log("Connected devices:", devices);
}

getHapticMappings

getHapticMappings(): Promise<any[]>

Get a list of all haptic events registered in the current haptic application (deployed from the bHaptics Developer Portal).

Returns

Array of haptic mapping objects. Each object has the following fields:

FieldTypeDescription
eventNamestringEvent key. Use it with play and the other event-driven functions.
eventTimenumberDuration of the event in milliseconds.

The example of return value follows:

[
{
"eventName": "punch-recoil",
"eventTime": 180
},
{
"eventName": "dash",
"eventTime": 3260
},
{
"eventName": "teleport",
"eventTime": 460
}
]

Example

import Tact from "tact-js";

const showMappingsExample = async () => {
const mappings = await Tact.getHapticMappings();

for (const mapping of mappings) {
console.log(`${mapping.eventName}: ${mapping.eventTime}ms`);
}
}

getEvent

getEvent(eventKey: string): Promise<number>

Get the duration of a registered haptic event.

Parameters

  • eventKey: Name of the haptic event to look up.

Returns

Duration of the event in milliseconds. Returns 0 if the event key is not registered — you can use this to check whether an event key exists before calling play.

Example

import Tact from "tact-js";

const getEventExample = async () => {
const duration = await Tact.getEvent("dash");

if (duration > 0) {
console.log(`dash is ${duration}ms long`);
} else {
console.log("dash is not registered");
}
}

isDeviceConnected

isDeviceConnected(position: PositionType): Promise<boolean>

Check if a specific device type is connected.

Parameters

Returns

true if the device type is connected, false otherwise.

Example

import Tact, { PositionType } from "tact-js";

const isDeviceConnectedExample = async () => {
const isGloveConnected = await Tact.isDeviceConnected(PositionType.GloveR);
console.log("Right TactGlove connected:", isGloveConnected);
}

isConnected

isConnected(): Promise<boolean>

Check the connection status with bHaptics Player.

Returns

true if connected to bHaptics Player, false otherwise.

isPlaying

isPlaying(): Promise<boolean>

Check if any haptic feedback is currently playing.

Returns

true if any haptic is playing, false otherwise.

isPlayingByEventKey

isPlayingByEventKey(eventKey: string): Promise<boolean>

Check if a specific haptic event is currently playing.

Parameters

  • eventKey: Name of the haptic event to check

Returns

true if the specified haptic event is playing, false otherwise.

Device Control

ping

ping(address: string): Promise<void>

Sends a ping signal to a specific device to test connection.

Parameters

  • address: The MAC address of the haptic device. You can get the address from getConnectedDevices()

Example

import Tact from "tact-js";

const pingFirstDeviceExample = async () => {
const devices = await Tact.getConnectedDevices();

if (devices.length > 0) {
await Tact.ping(devices[0].address);
}
}

pingAll

pingAll(): Promise<void>

Send a ping signal to all connected devices.

motorTest

motorTest(): Promise<void>

Run a motor test sequence on the TactSuit (Vest): each of the 40 motor positions fires at full intensity for one second, one after another. The full sequence takes about 40 seconds; the returned promise resolves when the sequence finishes.

Note that this test covers the Vest position only — it does not test other device types.

Common Enums

PositionType

enum PositionType {
Vest = "Vest",
ForearmL = "ForearmL",
ForearmR = "ForearmR",
Head = "Head",
HandL = "HandL",
HandR = "HandR",
FootL = "FootL",
FootR = "FootR",
GloveL = "GloveL",
GloveR = "GloveR"
}

String enums. Use it to decide the type of haptic device.

ValueDeviceMotors Count
VestTactSuit32
ForearmLTactSleeve(Left)3
ForearmRTactSleeve(Right)3
HeadTactVisor4
HandLTactosy for Hands(Left)3
HandRTactosy for Hands(Right)3
FootLTactosy for Feet(Left)3
FootRTactosy for Feet(Right)3
GloveLTactGlove(Left)8
GloveRTactGlove(Right)8

tact-js also exports a PositionUtils class with static helpers for converting between the numeric positions used by getConnectedDevices and the PositionType enum:

import { PositionType, PositionUtils } from "tact-js";

PositionUtils.positionToType(9); // PositionType.GloveR
PositionUtils.enumToPosition(PositionType.Vest); // 0