ASEView.js - JavaScript Module
Standalone JavaScript library for molecular visualization. Use it in any web page without Python.
The JavaScript module uses the same templates as the Python package, ensuring identical UI and features.
A focused walkthrough of the 4 viewer classes with editable code. For a full sandbox to load your own files, see the Playground.
Quick Start
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ASEView Example</title>
<style>
#viewer { width: 100%; height: 500px; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.MolecularViewer('#viewer', {
viewPreset: 'top-c'
});
viewer.setData({
symbols: ['O', 'H', 'H'],
positions: [
[0.0, 0.0, 0.117],
[0.0, 0.757, -0.469],
[0.0, -0.757, -0.469]
]
});
</script>
</body>
</html>
Available Viewers
MolecularViewer
Full-featured molecular structure viewer with sidebar controls.
Features:
- Style selector (Cartoon, Glossy, Metallic, Neon, etc.)
- Bond/Cell display toggles
- Atom size and bond thickness sliders
- Trajectory animation with playback controls
- Energy and max-force plot visualization
- Radius contrast control for element-size differences
- Fixed atom highlighting from constraint metadata
- Clipboard copy as
xyz,extxyz,cif, orPOSCAR - Screenshot and GIF export
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MolecularViewer Example</title>
<style>
#viewer { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.MolecularViewer('#viewer');
// Single structure (Ethanol)
viewer.setData({
symbols: ['C', 'C', 'O', 'H', 'H', 'H', 'H', 'H', 'H'],
positions: [
[-0.047, 0.666, 0.000],
[-0.047, -0.866, 0.000],
[1.204, 1.144, 0.000],
[1.869, 0.485, 0.000],
[-0.570, 1.035, 0.889],
[-0.570, 1.035, -0.889],
[0.982, -1.162, 0.000],
[-0.557, -1.222, 0.889],
[-0.557, -1.222, -0.889]
]
});
</script>
</body>
</html>
const viewer = new ASEView.MolecularViewer('#viewer');
// Single structure
viewer.setData({
symbols: ['C', 'C', 'O', 'H', 'H', 'H', 'H', 'H', 'H'],
positions: [
[-0.047, 0.666, 0.000],
[-0.047, -0.866, 0.000],
[1.204, 1.144, 0.000],
// ... more positions
]
});
// Trajectory (array of structures)
viewer.setData([
{ symbols: [...], positions: [...], energy: -10.5 },
{ symbols: [...], positions: [...], energy: -10.3 },
// ... more frames
]);
NormalModeViewer
Viewer for molecular vibration animations.
Features:
- Mode selector dropdown
- Amplitude control slider
- Animation speed control
- Play/Pause toggle
- Frequency display
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>NormalModeViewer Example</title>
<style>
#viewer { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.NormalModeViewer('#viewer');
// Equilibrium structure
const atoms = {
symbols: ['O', 'H', 'H'],
positions: [
[0.0, 0.0, 0.117],
[0.0, 0.757, -0.469],
[0.0, -0.757, -0.469]
]
};
// Vibration data (3 modes for water)
const vibrationData = {
modeVectors: [
[[0, 0, -0.07], [0, 0.42, 0.56], [0, -0.42, 0.56]],
[[0, 0.07, 0], [0, -0.56, 0.42], [0, 0.56, 0.42]],
[[0.07, 0, 0], [-0.56, 0, 0], [-0.56, 0, 0]]
],
frequencies: ["1595.32", "3657.05", "3755.93"],
isImaginary: [false, false, false]
};
viewer.setVibrationData(atoms, vibrationData);
</script>
</body>
</html>
const viewer = new ASEView.NormalModeViewer('#viewer');
const atoms = {
symbols: ['O', 'H', 'H'],
positions: [[0, 0, 0.117], [0, 0.757, -0.469], [0, -0.757, -0.469]]
};
const vibrationData = {
modeVectors: [
[[0, 0, -0.07], [0, 0.42, 0.56], [0, -0.42, 0.56]], // Mode 1
[[0, 0.07, 0], [0, -0.56, 0.42], [0, 0.56, 0.42]], // Mode 2
[[0.07, 0, 0], [-0.56, 0, 0], [-0.56, 0, 0]] // Mode 3
],
frequencies: ["1595.32", "3657.05", "3755.93"],
isImaginary: [false, false, false]
};
viewer.setVibrationData(atoms, vibrationData);
OverlayViewer
Compare multiple molecular structures by overlaying them.
Features:
- Per-structure opacity controls
- Multi-structure visualization
- Per-structure visibility and color controls
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>OverlayViewer Example</title>
<style>
#viewer { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.OverlayViewer('#viewer');
// Structure 1: Original water
const water1 = {
symbols: ['O', 'H', 'H'],
positions: [
[0.0, 0.0, 0.117],
[0.0, 0.757, -0.469],
[0.0, -0.757, -0.469]
]
};
// Structure 2: Stretched water
const water2 = {
symbols: ['O', 'H', 'H'],
positions: [
[0.0, 0.0, 0.050],
[0.0, 0.900, -0.400],
[0.0, -0.900, -0.400]
]
};
viewer.setStructures(water1, water2);
</script>
</body>
</html>
const viewer = new ASEView.OverlayViewer('#viewer');
const structure1 = {
symbols: ['O', 'H', 'H'],
positions: [[0, 0, 0.117], [0, 0.757, -0.469], [0, -0.757, -0.469]]
};
const structure2 = {
symbols: ['O', 'H', 'H'],
positions: [[0, 0, 0.050], [0, 0.900, -0.400], [0, -0.900, -0.400]]
};
viewer.setStructures(structure1, structure2);
// Or use setData with an array
viewer.setData([structure1, structure2]);
FragSelector
Interactive fragment selector with synchronized 2D and 3D views.
Features:
- Click, rectangle, and lasso atom selection
- Synchronized 2D/3D fragment picking
- Copy selected or unselected atom indices
- Structure copy using the same
xyz,extxyz,cif, andPOSCARformats as the main viewer
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>FragSelector Example</title>
<style>
#viewer { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.FragSelector('#viewer');
viewer.setData({
symbols: ['O', 'C', 'N', 'C', 'H', 'H', 'H', 'H', 'H'],
positions: [
[ 0.424546, 1.327024, 0.008034],
[ 0.077158, 0.149789, -0.004249],
[ 0.985518, -0.878537, -0.048910],
[-1.371475, -0.288665, -0.000144],
[ 0.707952, -1.824249, 0.169942],
[-1.997229, 0.584922, -0.175477],
[-1.560842, -1.039270, -0.771686],
[-1.632113, -0.723007, 0.969814],
[ 1.953133, -0.631574, 0.111866]
]
});
viewer.setSelection([1, 2, 4, 8]);
</script>
</body>
</html>
const viewer = new ASEView.FragSelector('#viewer');
viewer.setData({
symbols: ['O', 'C', 'N', 'C', 'H', 'H', 'H', 'H', 'H'],
positions: [
[ 0.424546, 1.327024, 0.008034],
[ 0.077158, 0.149789, -0.004249],
[ 0.985518, -0.878537, -0.048910],
[-1.371475, -0.288665, -0.000144],
[ 0.707952, -1.824249, 0.169942],
[-1.997229, 0.584922, -0.175477],
[-1.560842, -1.039270, -0.771686],
[-1.632113, -0.723007, 0.969814],
[ 1.953133, -0.631574, 0.111866]
]
});
viewer.setSelection([1, 2, 4, 8]);
API Reference
Methods
All Viewers
| Method | Description |
|---|---|
setData(data) |
Set molecular data (single structure or array of structures) |
setSettings(options) |
Update viewer settings at runtime |
dispose() |
Clean up and remove viewer |
NormalModeViewer Only
| Method | Description |
|---|---|
setVibrationData(atoms, vibrationData) |
Set equilibrium structure and vibration modes |
OverlayViewer Only
| Method | Description |
|---|---|
setStructures(...structures) |
Set two or more structures for overlay comparison |
FragSelector Only
| Method | Description |
|---|---|
setSelection(indices) |
Select atoms programmatically |
getSelection() |
Resolve the currently selected atom indices |
clearSelection() |
Clear all selected atoms |
Data Format
// Single structure
{
symbols: ['C', 'H', 'O', ...], // Required: atom symbols
positions: [[x, y, z], ...], // Required: atom positions (Å)
cell: [[a1, a2, a3], [b1, b2, b3], ...], // Optional: unit cell vectors (3x3)
pbc: [true, true, true], // Optional: periodic boundary flags
energy: -123.456, // Optional: energy value (eV)
forces: [[fx, fy, fz], ...], // Optional: force vectors
charges: [0.1, -0.2, ...], // Optional: atomic charges
fixed: [1, 4, ...], // Optional: fixed atom index list, not a boolean mask
arrays: {
fixed: [true, false, ...], // Optional: fixed atom boolean mask
move_mask: [[true, true, true], ...] // Optional: selective dynamics mask
},
name: "Molecule 1" // Optional: display name
}
// Trajectory (array of structures)
viewer.setData([
{ symbols: [...], positions: [...], energy: -10.5 },
{ symbols: [...], positions: [...], energy: -10.3 },
// ... more frames
]);
NormalModeViewer vibration data:
viewer.setVibrationData(atoms, {
modeVectors: [ // Displacement vectors per mode [nModes][nAtoms][3]
[[dx, dy, dz], ...], // Mode 0
[[dx, dy, dz], ...], // Mode 1
// ...
],
frequencies: ["1595.32", "3657.05", ...], // Frequency labels (cm⁻¹)
isImaginary: [false, false, ...], // Imaginary mode flags
nFrames: 30 // Animation frames per cycle (default: 30)
});
Theming
Select a visual theme via the theme option or the global setTheme() helper:
// Per-viewer
const viewer = new ASEView.MolecularViewer('#container', { theme: 'spring' });
// Global (affects all viewers created afterwards)
ASEView.setTheme('spring');
ASEView.getTheme(); // 'spring'
const v1 = new ASEView.MolecularViewer('#c1'); // spring
const v2 = new ASEView.NormalModeViewer('#c2'); // spring
| Theme | Description |
|---|---|
dark |
Dark theme with deep grey background |
spring |
Spring theme (default) with bright, airy colors |
glass |
Glassmorphism theme with frosted translucent panels |
darkgreen |
Dark GitHub-style theme with green accent |
simple |
Light macOS-style theme with colorful gradient background |
Settings (Constructor Options)
All viewers accept an options object as the second argument:
Settings can also be updated at runtime:
Camera Control
Initial camera settings can be passed in the constructor, and runtime camera
changes use setView(viewSpec):
const viewer = new ASEView.MolecularViewer('#viewer', {
viewPreset: 'top-c',
viewFit: 1.1
});
await viewer.setView({ preset: 'side-a', up: [0, 0, 1] });
await viewer.setView({ direction: [1, 1, 1], fit: 1.2 });
await viewer.setView({ euler: [45, 0, 30] });
await viewer.resetView();
viewDirection and preset directions are target-to-camera vectors. The camera
is placed along the normalized direction and looks back at the fitted structure
center. viewEuler is [rx, ry, rz] in degrees, XYZ order, applied to the
canonical target-to-camera vector [0, 0, 1]. viewUp is an optional up-vector
hint; invalid or parallel hints use a stable fallback. viewFit is a fit
multiplier.
Supported Cartesian presets are top, bottom, front, back, left, and
right. Cell-aware presets are top-c, bottom-c, side-a, and side-b.
Aliases c and top prefer the cell c axis when a valid cell exists, while
a and b prefer side views along the cell a and b vectors. Missing,
non-periodic, zero-length, or degenerate cells fall back to the Cartesian
direction for the requested preset.
setView(viewSpec) resolves with
{ ok: true, type: 'view', view: object }. Invalid runtime vectors reject with
an Error carrying code, message, type, and when applicable requestId.
Image Export
Browser viewers can export the rendered canvas:
const png = await viewer.savePNG({
filename: 'structure.png',
download: false,
returnDataUrl: true,
scale: 2,
transparent: true
});
const gif = await viewer.saveGIF({
filename: 'vibration.gif',
frames: 30,
delay: 40,
sampleInterval: 20,
download: false,
returnDataUrl: true
});
Common export options are filename, download (default true),
returnDataUrl (default false), scale (default 1), width, height,
transparent, and backgroundColor. GIF-only options are frames, delay,
and sampleInterval.
PNG exports default to transparent backgrounds. GIF exports default to an
opaque viewer background and pre-compose each frame over backgroundColor to
avoid transparent-frame trails in GIF encoders.
Successful export promises resolve with
{ ok: true, type: 'png' | 'gif', filename, dataUrl?, width?, height? }.
dataUrl is present when returnDataUrl: true. Failures reject with an
Error carrying code, message, type, and when applicable requestId.
MolecularViewer and NormalModeViewer support PNG and GIF.
OverlayViewer supports PNG only; saveGIF() rejects with
code: 'unsupported_export'.
Python viewers also expose headless save_png() and save_gif() when installed
with the optional export dependency:
viewer.save_png("structure.png", scale=2, transparent=False)
viewer.save_gif("trajectory.gif", frames=30, quality="high")
PNG quality is controlled by scale, width, and height. GIF
quality="low" | "medium" | "high" maps to the encoder sample interval.
PNG exports default to transparent backgrounds; GIF exports default to an
opaque viewer background to avoid transparent-frame trails.
The export extra pins Playwright below 1.15 for CentOS 7/glibc 2.17
compatibility; newer Playwright browser builds may require newer glibc.
The CLI still does not provide --save-png or --save-gif.
Common Settings (All Viewers)
| Parameter | Type | Default | Description |
|---|---|---|---|
theme |
string | 'spring' |
Visual theme ('dark', 'spring', 'glass', 'darkgreen', 'simple', …) |
style |
string | 'cartoon' |
Rendering style |
backgroundColor |
string | theme default ('#ffffff' for Spring) |
Background color (hex) |
atomSize |
float | 0.4 |
Atom radius scale |
bondThreshold |
float | 1.2 |
Bond cutoff (multiple of covalent radii) |
bondThickness |
float | 0.09 |
Bond cylinder radius |
showBond |
boolean | true |
Show bonds |
showCell |
boolean | true |
Show unit cell box |
showShading |
boolean | true |
Enable directional lighting |
showAxis |
boolean | true |
Show XYZ axis helper |
showForces |
boolean | false |
Show force vectors |
hideHydrogens |
boolean | false |
Hide hydrogen atoms and their bonds without removing them from the data |
showBlur |
boolean | false |
Apply blur to the rendered molecule canvas |
blurStrength |
float | 1.5 |
Blur radius in pixels when showBlur is enabled |
showEnergyPlot |
boolean | false |
Show energy vs frame plot |
showForceMaxPlot |
boolean | true |
Include max force trace when forces are available |
radiusContrast |
float | 1.0 |
Atom radius contrast (0.0 uniform, 1.0 element radii) |
radiusContrastMode |
string | 'log' |
'linear' or 'log' radius mapping |
animationSpeed |
int | 30 |
Animation playback rate in frames per second (FPS) |
forceScale |
float | 0.5 |
Force vector scale |
viewMode |
string | 'Orthographic' |
'Orthographic' or 'Perspective' |
viewPreset |
string | null | null |
Initial named camera view ('top-c', 'side-a', 'front', etc.) |
viewDirection |
number[] | null | null |
Explicit target-to-camera direction vector |
viewEuler |
number[] | null | null |
XYZ Euler degrees applied to [0, 0, 1] |
viewUp |
number[] | null | null |
Optional camera up-vector hint |
viewFit |
number | 1.7 |
Camera fit multiplier |
rotationMode |
string | 'TrackBall' |
'TrackBall' or 'Orbit' |
Available styles: default, 2d, cartoon, neon, glossy, metallic, cinematic, rowan, bubble, grey
MolecularViewer Settings
| Parameter | Type | Default | Description |
|---|---|---|---|
cellColor |
string | '#808080' |
Unit cell line color (hex) |
colorBy |
string | 'Element' |
'Element' or 'Charge' |
chargeColormap |
string | 'coolwarm' |
Colormap for charge coloring |
normalizeCharges |
boolean | false |
Normalize charge color range |
showChargeLabels |
boolean | false |
Display charge values on atoms |
showConstraint |
boolean | false |
Highlight fixed atoms with a yellow overlay |
NormalModeViewer Settings
Inherits all common settings, plus:
| Parameter | Type | Default | Description |
|---|---|---|---|
showModeVector |
boolean | false |
Display vibration displacement arrows |
showShadow |
boolean | false |
Show shadow beneath molecule |
Vibration playback parameters (set via setVibrationData):
| Parameter | Type | Default | Description |
|---|---|---|---|
amplitude |
float | 0.75 |
Displacement amplitude scale |
nFrames |
int | 30 |
Animation frames per cycle |
OverlayViewer Settings
| Parameter | Type | Default | Description |
|---|---|---|---|
colorBy |
string | 'Atom' |
'Atom', 'Molecule', or 'Colormap' |
colormap |
string | 'viridis' |
Colormap name (when colorBy: 'Colormap') |
showShading |
boolean | false |
Shading (default differs from other viewers) |
allVisible |
boolean | false |
Show every overlay structure initially |
visibleIndices |
number[] | null | null |
Structure indices to show initially |
Available colormaps: viridis, plasma, coolwarm, jet, rainbow, grayscale
Jekyll / GitHub Pages
---
title: My Molecule
---
<!DOCTYPE html>
<html>
<head>
<style>
#viewer { width: 100%; height: 500px; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.MolecularViewer('#viewer');
viewer.setData({
symbols: ['C', 'C', 'O', 'H', 'H', 'H', 'H', 'H', 'H'],
positions: [
[-0.047, 0.666, 0.000], [-0.047, -0.866, 0.000],
[1.204, 1.144, 0.000], [1.869, 0.485, 0.000],
[-0.570, 1.035, 0.889], [-0.570, 1.035, -0.889],
[0.982, -1.162, 0.000], [-0.557, -1.222, 0.889],
[-0.557, -1.222, -0.889]
]
});
</script>
</body>
</html>
---
title: My Molecule
---
# My Research
Some text about the molecule...
<div id="viewer" style="width:100%; height:500px;"></div>
<script src="https://cdn.jsdelivr.net/gh/kangmg/aseview@main/aseview/static/js/aseview.js"></script>
<script>
const viewer = new ASEView.MolecularViewer('#viewer');
viewer.setData({
symbols: ['O', 'H', 'H'],
positions: [[0, 0, 0.117], [0, 0.757, -0.469], [0, -0.757, -0.469]]
});
</script>
Architecture
The JavaScript module uses the same HTML templates as the Python package.
The full themed template set has five viewer templates:
molecular_viewer.html, normal_viewer.html, overlay_viewer.html,
frag_selector.html, and surface_viewer.html.
aseview.js (thin wrapper)
↓
iframe loads template from CDN
↓
postMessage sends data to template
↓
Template renders (same code as Python viewer)
This ensures:
- Consistent UI: Web and Python viewers look identical
- Single source of truth: One template, no duplicate code
- Automatic updates: Python template improvements apply to web