What is a Classic Stroke?
So named for its timelessness. The OG stroke. It commands Ayva to perform a simple up and down movement on the stroke axis with some
(optional) variation on a few parameters such as speed, positions, shape, and twist. Its been often stated that many people are satisfied
with just the stroke and twist axis. If you're one of those people, ClassicStroke
has got you covered!
Setup
ClassicStroke
is available as part of the standard distribution, but to use it within an ES6 module, you must import it. This can be done at the same time that you import the Ayva class. For example, in a browser:
import { Ayva, ClassicStroke } from 'https://unpkg.com/ayvajs';
or from within a Node.js app:
import { Ayva, ClassicStroke } from 'ayvajs';
Once ClassicStroke
is imported, you can create new strokes using ClassicStroke
's constructor:
// Create a new stroke with default parameters.
const myStroke = new ClassicStroke();
// Perform the stroke until commanded to do otherwise.
ayva.do(myStroke);
Parameters
To customize ClassicStroke
's behavior, a configuration object can be passed to the constructor with any of the following parameters:
bottom
The bottom of the stroke range. This can be an absolute value, an array of values, or a function that provides the value for each stroke.
Defaults to 0
// Specify as absolute value.
ayva.do(new ClassicStroke({
bottom: 0.5,
}));
// Specify as array of values (this pattern will repeat).
ayva.do(new ClassicStroke({
bottom: [0, 0.25, 0.5, 0.25]
}));
// Specify as a function (this example generates a random value between 0 and 0.5 for each stroke).
ayva.do(new ClassicStroke({
bottom: () => Ayva.map(Math.random(), 0, 1, 0, 0.5)
}));
top
The top of the stroke range. This can be an absolute value, an array of values, or a function that provides the value for each stroke.
Defaults to 1
// Specify as absolute value.
ayva.do(new ClassicStroke({
top: 0.75,
}));
// Specify as array of values (this pattern will repeat).
ayva.do(new ClassicStroke({
top: [1, 0.75, 0.5, 0.75]
}));
// Specify as a function (this example generates a random value between 0.5 and 1 for each stroke).
ayva.do(new ClassicStroke({
top: () => Ayva.map(Math.random(), 0, 1, 0.5, 1)
}));
speed
The speed of the stroke. This can be an absolute value, an array of values, or a function that provides the value for each stroke.
Defaults to 1
// Specify as absolute value.
ayva.do(new ClassicStroke({
speed: 1.5,
}));
// Specify as array of values (this pattern will repeat)
ayva.do(new ClassicStroke({
speed: [0.5, 1, 1.5, 1 ]
}));
// Specify as a function (this example generates a speed that varies with sin)
ayva.do(new ClassicStroke({
speed: (index) => {
const x = index / 20; // One cycle every 20 strokes.
const minSpeed = 0.5;
const maxSpeed = 3;
return Ayva.map(Math.sin(x * Math.PI * 2), -1, 1, minSpeed, maxSpeed);
}
}));
duration
Alternative to speed—the duration of each stroke. This can be an absolute value, an array of values, or a function that provides the value for each stroke. Defaults to undefined
(incompatible with speed property).
shape
The "shape" of the stroke. This can be a ramp function, or an even lengthed array of ramp functions.
When specified as an array, the even indexed array entries correspond with up strokes, and odd index entries with down strokes.
Defaults to Ayva.RAMP_COS
// Specify as function (ramp)
ayva.do(new ClassicStroke({
shape: Ayva.RAMP_PARABOLIC
}));
// Specify as array of values (this pattern will repeat)
ayva.do(new ClassicStroke({
shape: [ Ayva.RAMP_NEGATIVE_PARABOLIC, Ayva.RAMP_PARABOLIC, Ayva.RAMP_COS, Ayva.RAMP_LINEAR ]
}));
relativeSpeeds
An even lengthed array of factors to scale stroke speeds by. The even indexed array entries correspond with up strokes, and odd index entries correspond with down strokes.
Defaults to [1, 1]
// Specify as array of values (this pattern will repeat)
ayva.do(new ClassicStroke({
speed: 2,
// Multiply base speed (2) by these factors on corresponding strokes.
relativeSpeeds: [ 0.5, 0.75, 0.75, 1 ]
}));
suck
The suck algorithm value.
Defaults to null
(i.e. no suck algorithm).
ayva.do(new ClassicStroke({
// Set suck algorithm to close valve to 0.8 on the up strokes.
suck: 0.8
}));
twist
A configuration object for a cos shaped twist with the following parameters:
from
- position of the twist axis when at the bottom of a stroke.
to
- position of the twist axis when at the top of a stroke.
phase
- phase of the cos wave in multiples of π/2
ecc
- the eccentricity of the cos wave
Defaults to null
(i.e. no twist).
ayva.do(new ClassicStroke({
twist: {
from: 0.5,
to: 1,
phase: 1,
ecc: 1
}
}));
pitch
A configuration object for a cos shaped pitch with the following parameters:
from
- position of the pitch axis when at the bottom of a stroke.
to
- position of the pitch axis when at the top of a stroke.
phase
- phase of the cos wave in multiples of π/2
ecc
- the eccentricity of the cos wave
Defaults to null
(i.e. no pitch).
ayva.do(new ClassicStroke({
pitch: {
from: 0.5,
to: 1,
phase: 1,
ecc: 1
}
}));
All Together Now
All of these parameters can be used together to create a unique experience:
ayva.do(new ClassicStroke({
// Random bottom
bottom: () => Ayva.map(Math.random(), 0, 1, 0, 0.3),
// Random top
top: () => Ayva.map(Math.random(), 0, 1, 0.7, 1),
// Speed vary by sin
speed: (index) => {
const x = index / 20; // One cycle every 20 strokes.
const minSpeed = 0.5;
const maxSpeed = 3;
return Ayva.map(Math.sin(x * Math.PI * 2), -1, 1, minSpeed, maxSpeed);
},
// "Bouncy" motion by using parabolic ramps
shape: [ Ayva.RAMP_NEGATIVE_PARABOLIC, Ayva.RAMP_PARABOLIC ],
// Make up strokes perform at half speed.
relativeSpeeds: [0.5, 1],
// With some twist motion slightly out of phase.
twist: {
from: 0.25,
to: 0.75,
phase: 0.5
}
}));
Warning:
ClassicStroke
does not manipulate the values of any axis but the stroke, pitch, and twist axes (the latter two only if configured). You must therefore take care to orient other axes to the values you would like them to be for the duration of the stroke. The following example demonstrates the effect of not doing this. 😅
// Move the roll and pitch axis way off.
ayva.$.roll(0, 1).pitch(0, 1).execute().then(() => {
// This stroke will occur without changing the pitch or roll back!
// Probably not what you want...
ayva.do(new ClassicStroke());
});
Shorthand
For simple strokes, you do not have to pass a configuration object. The constructor of ClassicStroke
accepts the bottom
, top
, speed
, and shape
properties directly; with each being optional and set to appropriate default values. Ex:
// A parabolic stroke with bottom = 0, top = 1, and speed = 2.
new ClassicStroke(0, 1, 2, Ayva.RAMP_PARABOLIC);
See the API Documentation for additional details.