or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation.mdchart-types.mdcore-plotting.mddata-streaming.mddata-updates.mdexport-utilities.mdindex.mdinteractive-components.mdlayout-system.mdtrace-management.md

animation.mddocs/

0

# Animation

1

2

Functions for creating smooth animated transitions between plot states and managing animation frames. Plotly.js provides a powerful animation system for creating engaging data visualizations.

3

4

## Capabilities

5

6

### animate

7

8

Animates the plot through a sequence of frames or to a specific frame state with customizable animation options.

9

10

```javascript { .api }

11

/**

12

* Animates the plot through frames or to a target state

13

* @param graphDiv - DOM element ID (string) or element reference

14

* @param frames - Frame objects, frame names, or frame group names to animate to

15

* @param animationOpts - Animation configuration options

16

* @returns Promise that resolves when animation completes

17

*/

18

function animate(

19

graphDiv: string | HTMLElement,

20

frames: Frame[] | string | string[],

21

animationOpts?: AnimationOptions

22

): Promise<void>;

23

```

24

25

**Usage Examples:**

26

27

```javascript

28

import Plotly from 'plotly.js-dist';

29

30

// Basic animation between two states

31

const frames = [

32

{

33

name: 'frame1',

34

data: [{

35

x: [1, 2, 3],

36

y: [1, 4, 9],

37

type: 'scatter'

38

}]

39

},

40

{

41

name: 'frame2',

42

data: [{

43

x: [1, 2, 3],

44

y: [2, 8, 18],

45

type: 'scatter'

46

}]

47

}

48

];

49

50

// Add frames first

51

await Plotly.addFrames('chart', frames);

52

53

// Animate to specific frame

54

await Plotly.animate('chart', 'frame2', {

55

transition: { duration: 1000, easing: 'cubic-in-out' },

56

frame: { duration: 500, redraw: false }

57

});

58

59

// Animate through multiple frames

60

await Plotly.animate('chart', ['frame1', 'frame2'], {

61

transition: { duration: 800 },

62

frame: { duration: 1000 }

63

});

64

65

// Advanced animation with custom easing

66

await Plotly.animate('chart', frames, {

67

transition: {

68

duration: 2000,

69

easing: 'elastic-out'

70

},

71

frame: {

72

duration: 1500,

73

redraw: true

74

},

75

mode: 'afterall'

76

});

77

```

78

79

### addFrames

80

81

Adds animation frames to a plot at specified positions. Frames define different states of the plot for animation.

82

83

```javascript { .api }

84

/**

85

* Adds animation frames to a plot

86

* @param graphDiv - DOM element ID (string) or element reference

87

* @param frameList - Array of frame objects defining animation states

88

* @param indices - Position(s) to insert frames (optional, defaults to end)

89

* @returns Promise that resolves to the graph div element

90

*/

91

function addFrames(

92

graphDiv: string | HTMLElement,

93

frameList: Frame[],

94

indices?: number | number[]

95

): Promise<HTMLElement>;

96

```

97

98

**Usage Examples:**

99

100

```javascript

101

// Basic frame creation

102

const frames = [

103

{

104

name: 'year2020',

105

data: [{

106

x: countries,

107

y: gdp2020,

108

type: 'bar'

109

}],

110

layout: {

111

title: 'GDP by Country - 2020'

112

}

113

},

114

{

115

name: 'year2021',

116

data: [{

117

x: countries,

118

y: gdp2021,

119

type: 'bar'

120

}],

121

layout: {

122

title: 'GDP by Country - 2021'

123

}

124

}

125

];

126

127

await Plotly.addFrames('chart', frames);

128

129

// Frames with custom traces and layout changes

130

const evolutionFrames = [

131

{

132

name: 'step1',

133

data: [{

134

x: [1, 2, 3],

135

y: [1, 4, 2],

136

mode: 'markers',

137

marker: { size: 10, color: 'red' }

138

}],

139

traces: [0], // Apply to first trace only

140

layout: {

141

xaxis: { range: [0, 5] },

142

annotations: [{

143

text: 'Step 1',

144

x: 2.5,

145

y: 4

146

}]

147

}

148

},

149

{

150

name: 'step2',

151

data: [{

152

x: [1, 2, 3, 4],

153

y: [1, 4, 2, 6],

154

mode: 'lines+markers',

155

marker: { size: 8, color: 'blue' }

156

}],

157

traces: [0],

158

layout: {

159

annotations: [{

160

text: 'Step 2',

161

x: 2.5,

162

y: 6

163

}]

164

}

165

}

166

];

167

168

await Plotly.addFrames('evolution-chart', evolutionFrames);

169

170

// Add frames at specific positions

171

await Plotly.addFrames('chart', newFrames, [0, 2]); // Insert at positions 0 and 2

172

```

173

174

### deleteFrames

175

176

Removes animation frames from a plot by their names or indices.

177

178

```javascript { .api }

179

/**

180

* Removes animation frames from a plot

181

* @param graphDiv - DOM element ID (string) or element reference

182

* @param frameList - Array of frame names or indices to remove

183

* @returns Promise that resolves to the graph div element

184

*/

185

function deleteFrames(

186

graphDiv: string | HTMLElement,

187

frameList: string[] | number[]

188

): Promise<HTMLElement>;

189

```

190

191

**Usage Examples:**

192

193

```javascript

194

// Remove frames by name

195

await Plotly.deleteFrames('chart', ['frame1', 'frame3']);

196

197

// Remove frames by index

198

await Plotly.deleteFrames('chart', [0, 2, 4]);

199

200

// Remove all frames

201

const chartDiv = document.getElementById('chart');

202

const frameNames = chartDiv._transitionData._frames.map(f => f.name);

203

await Plotly.deleteFrames('chart', frameNames);

204

```

205

206

## Animation Patterns

207

208

### Time Series Animation

209

210

```javascript

211

// Animate through time series data

212

async function createTimeSeriesAnimation(data, timeField, valueField) {

213

const timePoints = [...new Set(data.map(d => d[timeField]))].sort();

214

215

const frames = timePoints.map(time => ({

216

name: time.toString(),

217

data: [{

218

x: data.filter(d => d[timeField] <= time).map(d => d.x),

219

y: data.filter(d => d[timeField] <= time).map(d => d[valueField]),

220

type: 'scatter',

221

mode: 'lines+markers'

222

}],

223

layout: {

224

title: `Data as of ${time}`,

225

xaxis: { range: [minX, maxX] },

226

yaxis: { range: [minY, maxY] }

227

}

228

}));

229

230

await Plotly.addFrames('timeseries-chart', frames);

231

232

// Auto-play animation

233

await Plotly.animate('timeseries-chart', frames.map(f => f.name), {

234

transition: { duration: 300 },

235

frame: { duration: 500 }

236

});

237

}

238

```

239

240

### Scatter Plot Evolution

241

242

```javascript

243

// Animate scatter plot data evolution

244

const scatterFrames = years.map(year => ({

245

name: `year-${year}`,

246

data: [{

247

x: countries.map(country => getGDP(country, year)),

248

y: countries.map(country => getLifeExpectancy(country, year)),

249

text: countries,

250

mode: 'markers',

251

marker: {

252

size: countries.map(country => getPopulation(country, year) / 1000000),

253

color: countries.map(country => getRegionColor(country)),

254

sizemode: 'diameter',

255

sizeref: 0.1

256

},

257

type: 'scatter'

258

}],

259

layout: {

260

title: `World Development Indicators - ${year}`,

261

xaxis: { title: 'GDP per Capita' },

262

yaxis: { title: 'Life Expectancy' }

263

}

264

}));

265

266

await Plotly.addFrames('world-chart', scatterFrames);

267

```

268

269

### Bar Chart Race Animation

270

271

```javascript

272

// Create animated bar chart race

273

function createBarRace(data, categories, timePoints) {

274

const frames = timePoints.map(time => {

275

const timeData = data.filter(d => d.time === time)

276

.sort((a, b) => b.value - a.value)

277

.slice(0, 10); // Top 10

278

279

return {

280

name: time.toString(),

281

data: [{

282

x: timeData.map(d => d.value),

283

y: timeData.map(d => d.category),

284

type: 'bar',

285

orientation: 'h',

286

marker: {

287

color: timeData.map(d => getCategoryColor(d.category))

288

}

289

}],

290

layout: {

291

title: `Rankings - ${time}`,

292

xaxis: { range: [0, Math.max(...timeData.map(d => d.value)) * 1.1] },

293

yaxis: {

294

categoryorder: 'array',

295

categoryarray: timeData.map(d => d.category).reverse()

296

}

297

}

298

};

299

});

300

301

return frames;

302

}

303

```

304

305

### Morphing Shapes Animation

306

307

```javascript

308

// Animate between different shape configurations

309

const shapeFrames = [

310

{

311

name: 'circle',

312

data: [{

313

x: circleX,

314

y: circleY,

315

mode: 'markers',

316

marker: { size: 20, color: 'blue' }

317

}]

318

},

319

{

320

name: 'square',

321

data: [{

322

x: squareX,

323

y: squareY,

324

mode: 'markers',

325

marker: { size: 20, color: 'red' }

326

}]

327

},

328

{

329

name: 'triangle',

330

data: [{

331

x: triangleX,

332

y: triangleY,

333

mode: 'markers',

334

marker: { size: 20, color: 'green' }

335

}]

336

}

337

];

338

339

await Plotly.addFrames('morph-chart', shapeFrames);

340

341

// Smooth morphing animation

342

await Plotly.animate('morph-chart', ['circle', 'square', 'triangle'], {

343

transition: {

344

duration: 2000,

345

easing: 'cubic-in-out'

346

},

347

frame: {

348

duration: 500,

349

redraw: false

350

}

351

});

352

```

353

354

## Interactive Animation Controls

355

356

### Animation Slider

357

358

```javascript

359

// Create animation with slider control

360

const layout = {

361

title: 'Animated Plot with Slider',

362

sliders: [{

363

active: 0,

364

steps: frames.map((frame, i) => ({

365

label: frame.name,

366

method: 'animate',

367

args: [[frame.name], {

368

mode: 'immediate',

369

transition: { duration: 300 },

370

frame: { duration: 300, redraw: false }

371

}]

372

})),

373

x: 0.1,

374

len: 0.9,

375

xanchor: 'left',

376

y: 0,

377

yanchor: 'top',

378

pad: { t: 50, b: 10 },

379

currentvalue: {

380

visible: true,

381

prefix: 'Year:',

382

xanchor: 'right',

383

font: { size: 20, color: '#666' }

384

}

385

}]

386

};

387

```

388

389

### Play/Pause Controls

390

391

```javascript

392

// Add play/pause buttons

393

const layout = {

394

updatemenus: [{

395

type: 'buttons',

396

direction: 'left',

397

buttons: [{

398

label: 'Play',

399

method: 'animate',

400

args: [null, {

401

mode: 'immediate',

402

fromcurrent: true,

403

transition: { duration: 300 },

404

frame: { duration: 500, redraw: false }

405

}]

406

}, {

407

label: 'Pause',

408

method: 'animate',

409

args: [[null], {

410

mode: 'immediate',

411

transition: { duration: 0 },

412

frame: { duration: 0, redraw: false }

413

}]

414

}],

415

pad: { r: 10, t: 87 },

416

showactive: false,

417

x: 0.011,

418

xanchor: 'right',

419

y: 0,

420

yanchor: 'top'

421

}]

422

};

423

```

424

425

## Animation Events

426

427

```javascript { .api }

428

interface AnimationEvents {

429

'plotly_animating': (eventData: { frame: Frame }) => void;

430

'plotly_animationinterrupted': (eventData: { frame: Frame }) => void;

431

'plotly_transitioned': () => void;

432

'plotly_transitioninterrupted': () => void;

433

}

434

```

435

436

**Usage Examples:**

437

438

```javascript

439

const chartDiv = document.getElementById('animated-chart');

440

441

chartDiv.on('plotly_animating', (eventData) => {

442

console.log('Animating to frame:', eventData.frame.name);

443

});

444

445

chartDiv.on('plotly_animationinterrupted', () => {

446

console.log('Animation was interrupted');

447

});

448

449

chartDiv.on('plotly_transitioned', () => {

450

console.log('Transition completed');

451

});

452

```

453

454

## Performance Optimization

455

456

### Efficient Frame Management

457

458

```javascript

459

// Pre-calculate all frame data for smooth animation

460

function precomputeFrames(rawData, timePoints) {

461

return timePoints.map(time => {

462

const frameData = processDataForTime(rawData, time);

463

return {

464

name: time.toString(),

465

data: frameData,

466

layout: { title: `Time: ${time}` }

467

};

468

});

469

}

470

471

// Use redraw: false for better performance

472

const animationOpts = {

473

transition: { duration: 300 },

474

frame: {

475

duration: 200,

476

redraw: false // Skip full redraw between frames

477

}

478

};

479

```

480

481

### Memory Management

482

483

```javascript

484

// Clean up frames when animation is complete

485

async function runAnimationSequence(chartId, frames) {

486

await Plotly.addFrames(chartId, frames);

487

488

try {

489

await Plotly.animate(chartId, frames.map(f => f.name));

490

} finally {

491

// Clean up frames to free memory

492

await Plotly.deleteFrames(chartId, frames.map(f => f.name));

493

}

494

}

495

```

496

497

## Types

498

499

```javascript { .api }

500

interface Frame {

501

name?: string;

502

group?: string;

503

data?: Partial<PlotlyTrace>[];

504

layout?: Partial<Layout>;

505

traces?: number[];

506

baseframe?: string;

507

}

508

509

interface AnimationOptions {

510

mode?: 'immediate' | 'next' | 'afterall';

511

direction?: 'forward' | 'reverse';

512

fromcurrent?: boolean;

513

transition?: TransitionOptions;

514

frame?: FrameOptions;

515

}

516

517

interface TransitionOptions {

518

duration?: number;

519

easing?: 'linear' | 'quad' | 'cubic' | 'sin' | 'exp' | 'circle' | 'elastic' | 'back' | 'bounce' | string;

520

ordering?: 'layout first' | 'traces first';

521

}

522

523

interface FrameOptions {

524

duration?: number;

525

redraw?: boolean;

526

}

527

528

interface SliderStep {

529

label?: string;

530

method?: 'animate' | 'relayout' | 'restyle' | 'update';

531

args?: any[];

532

value?: string;

533

visible?: boolean;

534

execute?: boolean;

535

}

536

537

interface SliderConfig {

538

active?: number;

539

bgcolor?: string;

540

bordercolor?: string;

541

borderwidth?: number;

542

currentvalue?: {

543

font?: FontConfig;

544

offset?: number;

545

prefix?: string;

546

suffix?: string;

547

visible?: boolean;

548

xanchor?: 'left' | 'center' | 'right';

549

};

550

font?: FontConfig;

551

len?: number;

552

lenmode?: 'fraction' | 'pixels';

553

steps?: SliderStep[];

554

tickcolor?: string;

555

ticklen?: number;

556

tickwidth?: number;

557

transition?: TransitionOptions;

558

visible?: boolean;

559

x?: number;

560

xanchor?: 'auto' | 'left' | 'center' | 'right';

561

y?: number;

562

yanchor?: 'auto' | 'top' | 'middle' | 'bottom';

563

}

564

```