MCP Integration Guide
This guide covers integrating PinePaper with Model Context Protocol (MCP) servers for AI-powered animation and graphics creation.
Quick Start: Install the official MCP server with
npm install -g @pinepaper.studio/mcp-serverSee MCP Server Installation for complete setup instructions.
New in v0.3: Use Agent Mode for streamlined MCP workflows. Agent Mode provides
quickExport()with smart format detection, platform presets for 16 platforms, andreset()for batch processing.
Overview
PinePaper exposes its complete API via window.PinePaper (aliased as app). The three core registries provide the foundation for programmatic control:
| Registry | Purpose | Key Methods |
|---|---|---|
| ItemRegistry | Track canvas items | register, getAll, getByType, query |
| RelationRegistry | Behavior rules & animation | addAssociation, getAssociations, exportTrainingData |
| GeneratorRegistry | Background patterns | executeGenerator, register, getAll |
Animation Philosophy: Relations First
Important: For MCP tools, always prefer relations over direct keyframe animation.
Relations are the declarative, natural language-friendly way to animate in PinePaper:
| Approach | Description | Training Data |
|---|---|---|
| Relations (Recommended) | Describe behavior: “moon orbits earth” | Natural language templates |
| Keyframes (Low-level) | Specify exact property values at times | No natural language |
Relations internally use keyframes and the animation system, but they:
- Are described in natural language (“orbits”, “follows”, “attached_to”)
- Generate training data for LLM fine-tuning
- Compose together (multiple relations on one item)
- Are easier to understand and modify
// RECOMMENDED: Use relations
app.addRelation(moonId, earthId, 'orbits', { radius: 100, speed: 0.5 });
// NOT RECOMMENDED: Direct keyframes (use only when relations don't fit)
app.modify(moon, {
animationType: 'keyframe',
keyframes: [...]
});
MCP Tool Categories
| Category | Tools | Description |
|---|---|---|
| Item | pinepaper_create_item, pinepaper_modify_item, pinepaper_delete_item, pinepaper_batch_create, pinepaper_batch_modify |
Create and modify canvas items |
| Relation | pinepaper_add_relation, pinepaper_remove_relation, pinepaper_query_relations |
Behavioral relationships (orbits, follows, attached_to) |
| Animation | pinepaper_animate, pinepaper_keyframe_animate, pinepaper_play_timeline |
Simple and keyframe animations |
| Generator | pinepaper_execute_generator, pinepaper_list_generators |
Background generators (sunburst, waves, circuit) |
| Query | pinepaper_query_items, pinepaper_hit_test, pinepaper_layer_info |
Find and inspect items |
| Effect | pinepaper_apply_effect |
Visual effects (sparkle, blast) |
| Export | pinepaper_export_svg, pinepaper_export_training_data |
SVG and training data export |
| Map | pinepaper_load_map, pinepaper_highlight_regions, pinepaper_apply_data_colors, pinepaper_add_marker, pinepaper_export_map, pinepaper_import_custom_map |
Geographic visualizations |
1. Item Creation Tools
Create interactive elements on the canvas.
// Tool: pinepaper_create_item
const item = app.create(type, params);
// Returns: Paper.js item with data.registryId
// Supported types:
// 'text', 'circle', 'star', 'rectangle', 'triangle',
// 'polygon', 'ellipse', 'path', 'line', 'arc'
Item Data Flags:
When creating items, you can set behavior flags via the data parameter:
| Flag | Type | Default | Description |
|---|---|---|---|
selectable |
boolean | true |
Whether item can be selected by clicking |
isDraggable |
boolean | true |
Whether item can be dragged when selected |
isDecorative |
boolean | false |
Mark as non-interactive decoration (skips selection) |
// Create a selectable, draggable planet
const planet = app.create('circle', {
x: 400, y: 300, radius: 20, color: '#3b82f6',
data: { selectable: true, isDraggable: true, isPlanet: true }
});
// Create a non-interactive orbit path
const orbit = app.create('circle', {
x: 400, y: 300, radius: 100,
strokeColor: 'rgba(255,255,255,0.2)', strokeWidth: 1,
data: { isDecorative: true, selectable: false }
});
Example MCP Tool Definition:
{
"name": "pinepaper_create_item",
"description": "Create an item on the canvas",
"inputSchema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["text", "circle", "star", "rectangle", "triangle", "polygon", "ellipse", "path", "line", "arc"],
"description": "Type of item to create"
},
"params": {
"type": "object",
"description": "Item-specific parameters (position, size, color, etc.)"
},
"data": {
"type": "object",
"description": "Item behavior flags (selectable, isDraggable, isDecorative)",
"properties": {
"selectable": { "type": "boolean", "description": "Whether item can be selected" },
"isDraggable": { "type": "boolean", "description": "Whether item can be dragged" },
"isDecorative": { "type": "boolean", "description": "Mark as non-interactive decoration" }
}
}
},
"required": ["type", "params"]
}
}
2. Item Modification Tools
Modify existing items with app.modify().
Sizing: width/height vs scale:
| Property | Type | Description |
|---|---|---|
width |
number | Set item width in pixels (absolute) |
height |
number | Set item height in pixels (absolute) |
scale |
number | Scale relative to current size (compounds on repeated use) |
// RECOMMENDED: Pixel-based sizing for predictable results
app.modify(item, { width: 200, height: 150 });
// Relative scaling (compounds if called multiple times)
app.modify(item, { scale: 1.5 }); // 50% larger each time
Why prefer width/height:
width: 200always results in 200px widthscale: 2doubles current size - calling twice = 4x original- Pixel values are predictable and reproducible
Other modifiable properties:
| Property | Type | Description |
|---|---|---|
position |
[x, y] | Set item position |
x, y |
number | Set individual coordinates |
rotation |
number | Rotation in degrees |
opacity |
number | Transparency (0-1) |
fillColor |
string | Fill color (hex, rgb, named) |
strokeColor |
string | Stroke color |
strokeWidth |
number | Stroke width in pixels |
fontSize |
number | Font size for text items |
content |
string | Text content for text items |
3. Animation Tools (Simple Presets)
For quick, preset-based animations:
// Tool: pinepaper_animate
app.animate(item, { animationType, animationSpeed });
// Animation types: pulse, rotate, bounce, fade, wobble, slide, typewriter
Note: For complex animations, use Relations instead (see below). Relations provide natural language descriptions and generate training data.
4. Relation Tools (Recommended for Animation)
This is the primary way to add animation in PinePaper. Relations describe behavior in natural language and automatically animate items.
// Tool: pinepaper_add_relation
app.addRelation(sourceId, targetId, relationType, params);
// Core relation types:
// 'orbits' - Circular motion around target
// 'follows' - Move toward target with smoothing
// 'attached_to' - Fixed offset from target
// 'maintains_distance' - Stay fixed distance from target
// 'points_at' - Rotate to face target
// 'mirrors' - Mirror position across axis
// 'parallax' - Move relative to target by depth
// 'bounds_to' - Stay within target's bounds
// 'animates' - Keyframe animation (self-referential)
// Manim-inspired animation relations:
// 'grows_from' - Scale from zero to full size (like GrowFromPoint)
// 'staggered_with' - Staggered group animation (like LaggedStart)
// 'indicates' - Temporary highlight pulse (like Indicate)
// 'circumscribes' - Draw shape around target (like Circumscribe)
// 'wave_through' - Wave distortion effect (like ApplyWave)
// 'camera_follows' - View pans to follow target (like MovingCameraScene)
// 'camera_animates' - Keyframe-based camera zoom and pan animation
// 'morphs_to' - Shape morphing animation (like Transform)
Manim-Inspired Animation Examples:
// Staggered reveal - items appear one after another
items.forEach((item, index) => {
app.addRelation(item.data.id, null, 'staggered_with', {
index: index,
stagger: 0.15,
effect: 'popIn'
});
});
// Indicate/highlight an important item
app.addRelation(itemId, null, 'indicates', {
scale: 1.3,
color: '#fbbf24',
duration: 0.6,
repeat: 2
});
// Circumscribe - draw attention with animated shape
app.addRelation(sourceId, targetId, 'circumscribes', {
shape: 'circle',
color: '#ef4444',
duration: 1.0
});
// Morph one shape into another
app.addRelation(circle.data.id, star.data.id, 'morphs_to', {
duration: 1.5,
morphColor: true
});
// Camera follows a moving target
app.addRelation(null, playerId, 'camera_follows', {
smoothing: 0.1,
deadzone: 50
});
// Camera keyframe animation - zoom in, pan, zoom out
app.addRelation('camera', null, 'camera_animates', {
duration: 4,
loop: true,
keyframes: [
{ time: 0, zoom: 1, center: [400, 300] },
{ time: 2, zoom: 2, center: [200, 200], easing: 'easeInOut' },
{ time: 4, zoom: 1, center: [400, 300], easing: 'easeInOut' }
]
});
// Or use camera helper API
app.camera.zoomIn(2, 0.5);
app.camera.panTo(200, 200, 0.5);
app.camera.moveTo(200, 200, 2, 0.5);
app.camera.reset(0.5);
Example MCP Tool Definition:
{
"name": "pinepaper_add_relation",
"description": "Create a behavior relationship between two items. Relations automatically animate items based on their relationship to other items.",
"inputSchema": {
"type": "object",
"properties": {
"sourceId": {
"type": "string",
"description": "Registry ID of the source item (e.g., 'item_1'), use 'camera' for camera_animates, can be null for camera_follows"
},
"targetId": {
"type": "string",
"description": "Registry ID of the target item, can be null for self-animations"
},
"relationType": {
"type": "string",
"enum": ["orbits", "follows", "attached_to", "maintains_distance", "points_at", "mirrors", "parallax", "bounds_to", "grows_from", "staggered_with", "indicates", "circumscribes", "wave_through", "camera_follows", "camera_animates", "morphs_to"],
"description": "Type of relationship"
},
"params": {
"type": "object",
"description": "Relation-specific parameters"
}
},
"required": ["relationType"]
}
}
5. Generator Tools
Create procedural backgrounds.
// Tool: pinepaper_execute_generator
await app.executeGenerator(generatorName, params);
// Built-in generators:
// 'drawSunburst', 'drawSunsetScene', 'drawGrid',
// 'drawStackedCircles', 'drawCircuit', 'drawWaves', 'drawPattern'
6. Query Tools
Find and inspect items.
// Tool: pinepaper_query_items (via ItemRegistry)
const items = app.itemRegistry.getAll();
const textItems = app.itemRegistry.getByType('text');
const animated = app.itemRegistry.query(entry => entry.item.data?.animationType);
// Tool: pinepaper_query_items (via Project - Paper.js native query)
const circles = app.queryItems({ data: { shapeType: 'circle' } });
const named = app.queryItems({ name: /^planet/ });
const inBounds = app.queryItems({ inside: new paper.Rectangle(0, 0, 400, 300) });
// Tool: pinepaper_hit_test
const hit = app.hitTest([400, 300]);
const allHits = app.hitTestAll([400, 300]); // All overlapping items
// Tool: pinepaper_query_relations
const relations = app.getRelations(itemId);
const orbiters = app.queryByRelationTarget(targetId, 'orbits');
// Tool: pinepaper_layer_info
const layers = app.getLayerInfo();
7. Effect Tools
Apply visual effects.
// Tool: pinepaper_apply_effect
app.applyEffect(item, effectType, params);
// Effect types: 'sparkle', 'blast'
8. Export Tools
Export animations and training data.
// Tool: pinepaper_export_svg
const svgString = app.exportAnimatedSVG();
// Tool: pinepaper_export_training_data
const trainingData = app.exportRelationTrainingData();
9. Map Tools
Create data-driven geographic visualizations with the MapSystem.
// Tool: pinepaper_load_map
const mapResult = await app.mapSystem.loadMap(mapId, options);
// Built-in maps:
// 'world' - World 110m resolution
// 'worldHighRes' - World 50m resolution (recommended for quality)
// 'usa' - US states map
// Returns: { group, paths, bounds, center }
Map Loading Options:
| Option | Type | Description |
|---|---|---|
projection |
string | Map projection: ‘mercator’, ‘equalEarth’, ‘naturalEarth’, ‘orthographic’, ‘albers’, ‘stereographic’ |
quality |
string | Rendering quality: ‘fast’, ‘balanced’, ‘professional’ (no simplification) |
fillColor |
string | Default fill color for regions |
strokeColor |
string | Border color |
strokeWidth |
number | Border width |
scale |
number | Scale multiplier |
center |
[lon, lat] | Center coordinates |
rotate |
[x, y, z] | Rotation angles |
enableHover |
boolean | Enable hover effects |
enableClick |
boolean | Enable click events |
hoverFill |
string | Hover fill color |
hoverStroke |
string | Hover stroke color |
Example MCP Tool Definition:
{
"name": "pinepaper_load_map",
"description": "Load a geographic map onto the canvas with specified projection and styling",
"inputSchema": {
"type": "object",
"properties": {
"mapId": {
"type": "string",
"enum": ["world", "worldHighRes", "usa"],
"description": "Map to load"
},
"options": {
"type": "object",
"properties": {
"projection": {
"type": "string",
"enum": ["mercator", "equalEarth", "naturalEarth", "orthographic", "albers", "stereographic"],
"description": "Map projection type"
},
"quality": {
"type": "string",
"enum": ["fast", "balanced", "professional"],
"description": "Rendering quality"
},
"fillColor": { "type": "string" },
"strokeColor": { "type": "string" },
"strokeWidth": { "type": "number" },
"enableHover": { "type": "boolean" },
"enableClick": { "type": "boolean" }
}
}
},
"required": ["mapId"]
}
}
Region Highlighting:
// Tool: pinepaper_highlight_regions
app.mapSystem.highlightRegions(regionIds, options);
// Region ID formats:
// - World maps: Full country names ("United States of America", "France", "Japan")
// - USA map: State codes ("CA", "TX", "NY")
// Options:
// { fillColor: '#22c55e', strokeColor: '#16a34a', strokeWidth: 2, animate: true }
Example MCP Tool Definition:
{
"name": "pinepaper_highlight_regions",
"description": "Highlight specific regions on a loaded map",
"inputSchema": {
"type": "object",
"properties": {
"regionIds": {
"type": "array",
"items": { "type": "string" },
"description": "Array of region IDs to highlight (country names or state codes)"
},
"options": {
"type": "object",
"properties": {
"fillColor": { "type": "string", "description": "Highlight fill color" },
"strokeColor": { "type": "string", "description": "Highlight stroke color" },
"strokeWidth": { "type": "number", "description": "Highlight stroke width" },
"animate": { "type": "boolean", "description": "Animate the highlight" }
}
}
},
"required": ["regionIds"]
}
}
Data-Driven Coloring:
// Tool: pinepaper_apply_data_colors
app.mapSystem.applyDataColors(data, options);
// data format: { 'California': 85, 'Texas': 72, 'New York': 90 }
// options: {
// colorScale: 'blues', // 'blues', 'greens', 'reds', 'oranges', 'purples', 'heat'
// minValue: 0,
// maxValue: 100,
// showLegend: true,
// legendPosition: 'bottom-right'
// }
Example MCP Tool Definition:
{
"name": "pinepaper_apply_data_colors",
"description": "Apply data-driven coloring to map regions (choropleth)",
"inputSchema": {
"type": "object",
"properties": {
"data": {
"type": "object",
"description": "Object mapping region IDs to numeric values"
},
"options": {
"type": "object",
"properties": {
"colorScale": {
"type": "string",
"enum": ["blues", "greens", "reds", "oranges", "purples", "heat"],
"description": "Color scale to use"
},
"minValue": { "type": "number" },
"maxValue": { "type": "number" },
"showLegend": { "type": "boolean" },
"legendPosition": {
"type": "string",
"enum": ["top-left", "top-right", "bottom-left", "bottom-right"]
}
}
}
},
"required": ["data"]
}
}
Map Markers:
// Tool: pinepaper_add_marker
app.mapSystem.addMarker(options);
// options: {
// lat: 37.7749,
// lon: -122.4194,
// label: 'San Francisco',
// color: '#ef4444',
// size: 8,
// pulse: true
// }
Example MCP Tool Definition:
{
"name": "pinepaper_add_marker",
"description": "Add a marker to the map at specified coordinates",
"inputSchema": {
"type": "object",
"properties": {
"lat": { "type": "number", "description": "Latitude" },
"lon": { "type": "number", "description": "Longitude" },
"label": { "type": "string", "description": "Marker label text" },
"color": { "type": "string", "description": "Marker color" },
"size": { "type": "number", "description": "Marker size in pixels" },
"pulse": { "type": "boolean", "description": "Enable pulse animation" }
},
"required": ["lat", "lon"]
}
}
Map Labels:
// Tool: pinepaper_add_map_labels
app.mapSystem.addLabels(options);
// options: {
// regions: ['California', 'Texas'], // Or null for all visible
// fontSize: 10,
// fontColor: '#374151',
// labelType: 'name' // 'name', 'code', 'value'
// }
Map Export:
// Tool: pinepaper_export_map
const mapData = app.mapSystem.exportMap();
// Returns: { mapId, projection, regions, markers, dataColors, ... }
Map Events:
// Maps emit events for interactivity
app.mapSystem.on('regionClick', (event) => {
console.log('Clicked:', event.regionId, event.properties);
});
app.mapSystem.on('regionHover', (event) => {
console.log('Hovering:', event.regionId);
});
app.mapSystem.on('markerClick', (event) => {
console.log('Marker clicked:', event.marker);
});
Custom Map Import:
// Tool: pinepaper_import_custom_map
await app.mapSystem.importCustomMap(geoJson, options);
// Supports GeoJSON and TopoJSON formats
// Useful for detailed country maps from GADM or custom boundaries
Example: Data Visualization Map
// Create a choropleth map showing population data
const mapResult = await app.mapSystem.loadMap('usa', {
projection: 'albers',
quality: 'professional',
fillColor: '#e5e7eb',
strokeColor: '#9ca3af',
strokeWidth: 0.5,
enableHover: true
});
// Apply population data
app.mapSystem.applyDataColors({
'California': 39538223,
'Texas': 29145505,
'Florida': 21538187,
'New York': 20201249,
// ... more states
}, {
colorScale: 'blues',
showLegend: true,
legendPosition: 'bottom-right'
});
// Add major city markers
app.mapSystem.addMarker({ lat: 34.0522, lon: -118.2437, label: 'Los Angeles', pulse: true });
app.mapSystem.addMarker({ lat: 40.7128, lon: -74.0060, label: 'New York', pulse: true });
Relation-Based Animation
Relations are the declarative way to create animations. Instead of specifying frame-by-frame movements, you describe relationships and the system animates automatically.
Why Relations for MCP?
- Declarative: Describe “what” not “how”
- Composable: Multiple relations combine
- Training-friendly: Natural language templates
Example: Solar System
// Create celestial bodies
const sun = app.create('circle', { x: 400, y: 300, radius: 50, color: '#fbbf24' });
const earth = app.create('circle', { x: 550, y: 300, radius: 20, color: '#3b82f6' });
const moon = app.create('circle', { x: 580, y: 300, radius: 8, color: '#9ca3af' });
// Get IDs
const sunId = sun.data.registryId;
const earthId = earth.data.registryId;
const moonId = moon.data.registryId;
// Define relationships (animation happens automatically)
app.addRelation(earthId, sunId, 'orbits', { radius: 150, speed: 0.1 });
app.addRelation(moonId, earthId, 'orbits', { radius: 30, speed: 0.3 });
Compositional Relations
Items can have multiple relations:
// Planet orbits AND stays in bounds
app.addRelation(planetId, starId, 'orbits', { radius: 200 });
app.addRelation(planetId, canvasId, 'bounds_to', { padding: 50 });
// Label follows AND points at target
app.addRelation(labelId, targetId, 'follows', { offset: [0, -30] });
app.addRelation(labelId, targetId, 'points_at', { offset_angle: 0 });
Training Data Generation
PinePaper can export relation data for LLM fine-tuning.
Export Format
const trainingData = app.exportRelationTrainingData();
// Output:
[
{
instruction: "moon orbits earth at radius 100",
code: "app.addRelation('item_1', 'item_2', 'orbits', {\"radius\":100})",
relation: "orbits",
params: { radius: 100 }
}
]
Convert to JSONL for Fine-Tuning
const jsonl = trainingData.map(entry => JSON.stringify({
messages: [
{ role: 'user', content: entry.instruction },
{ role: 'assistant', content: entry.code }
]
})).join('\n');
Template Customization
Custom relations can include training templates:
app.relationRegistry.registerRule('bounces_off', {
description: 'Item bounces off target',
params: {
elasticity: { type: 'number', default: 0.8 }
},
compute: (ctx) => { /* physics calc */ },
apply: (item, target, computed, params) => { /* update position */ },
templates: [
'{item} bounces off {target}',
'make {item} bounce off {target}',
'{item} collides with {target}'
]
});
Paper.js Integration
For advanced graphics not covered by app.create(), use Paper.js directly:
// Create complex shape
const path = new paper.Path();
path.add([100, 100]);
path.arcTo([200, 50], [300, 100]);
path.closePath();
path.fillColor = '#3b82f6';
// Register with PinePaper (required for relations, selection, export)
const itemId = app.registerItem(path, 'customPath', { source: 'mcp' });
// Now can use in relations
app.addRelation(itemId, targetId, 'follows', { smoothing: 0.2 });
Boolean Operations
const outer = new paper.Path.Circle({ center: [200, 200], radius: 80 });
const inner = new paper.Path.Circle({ center: [200, 200], radius: 40 });
const ring = outer.subtract(inner);
ring.fillColor = '#8b5cf6';
app.registerItem(ring, 'ring');
outer.remove();
inner.remove();
MCP Server Implementation Example
// Example MCP server tool handler
async function handlePinePaperTool(toolName, args) {
switch (toolName) {
case 'create_item':
const item = app.create(args.type, args.params);
return { itemId: item.data.registryId, success: true };
case 'add_relation':
const success = app.addRelation(
args.sourceId,
args.targetId,
args.relationType,
args.params || {}
);
return { success };
case 'query_items':
const items = app.itemRegistry.getAll().map(entry => ({
id: entry.itemId,
type: entry.type,
position: entry.item.position ? {
x: entry.item.position.x,
y: entry.item.position.y
} : null
}));
return { items };
case 'export_training_data':
const data = app.exportRelationTrainingData();
return { trainingData: data };
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
Best Practices for MCP Integration
- Use registryId: All items have
item.data.registryIdfor tracking - Prefer relations over keyframes: Relations are more declarative and composable
- Save state after batches: Call
app.historyManager.saveState()after operations - Check item existence: Use
app.itemRegistry.has(id)before operations - Use view.center: Access canvas center with
app.view.center - Register Paper.js items: Use
app.registerItem()for directly created items - Export training data: Capture examples for model improvement
- Use width/height over scale: Pixel values are predictable; scale compounds on repeated calls
- Set data flags for interactivity: Use
selectable,isDraggable,isDecorativeto control item behavior - Mark decorations appropriately: Use
isDecorative: truefor orbits, guides, or other non-interactive elements
API Quick Reference
Core Methods
| Method | Description |
|---|---|
app.create(type, params) |
Create item (supports data flags) |
app.modify(item, params) |
Modify item (supports width, height, scale) |
app.deleteSelected() |
Remove selected items |
item.remove() |
Remove specific item (Paper.js) |
app.select(query) |
Select items |
app.animate(item, params) |
Apply simple animation |
app.registerItem(item, type, props) |
Register Paper.js item |
Item Data Flags
| Flag | Default | Description |
|---|---|---|
selectable |
true |
Can be selected by clicking |
isDraggable |
true |
Can be dragged when selected |
isDecorative |
false |
Non-interactive decoration (skips selection) |
Relation Methods
| Method | Description |
|---|---|
app.addRelation(from, to, type, params) |
Add relation |
app.removeRelation(from, to, type?) |
Remove relation |
app.getRelations(itemId, type?) |
Get item’s relations |
app.queryByRelationTarget(targetId, type) |
Find items relating to target |
app.getRelationStats() |
Get relation statistics |
app.exportRelationTrainingData() |
Export training data |
Registry Methods
| Method | Description |
|---|---|
app.itemRegistry.getAll() |
Get all items |
app.itemRegistry.getByType(type) |
Get items by type |
app.itemRegistry.query(predicate) |
Query with function |
app.itemRegistry.has(id) |
Check if item exists |
app.generatorRegistry.getAll() |
Get all generators |
app.executeGenerator(name, params) |
Run generator |
Project Query Methods
| Method | Description |
|---|---|
app.queryItems(match) |
Query items by Paper.js match criteria |
app.queryItem(match) |
Get single item by match |
app.hitTest(point, options) |
Hit test at point |
app.hitTestAll(point, options) |
All items at point |
app.isEmpty() |
Check if canvas has content |
app.getLayerInfo() |
Get layer information |
Symbol Methods
| Method | Description |
|---|---|
app.getSymbols() |
Get all symbol definitions |
app.createSymbol(item) |
Create symbol from item |
app.placeSymbol(symbol, pos) |
Place symbol instance |
Export Methods
| Method | Description |
|---|---|
app.exportAnimatedSVG() |
Export as animated SVG |
app.exportTemplate() |
Export as PinePaper template |
app.exportProjectJSON() |
Export full project state |
app.importProjectJSON(json) |
Import project state |
app.exportRelationTrainingData() |
Export training pairs |
app.relationRegistry.exportForSave() |
Export relations for save |
Map Methods
| Method | Description |
|---|---|
app.mapSystem.loadMap(mapId, options) |
Load geographic map (world, worldHighRes, usa) |
app.mapSystem.highlightRegions(ids, options) |
Highlight specific regions |
app.mapSystem.unhighlightRegions(ids) |
Remove region highlights |
app.mapSystem.applyDataColors(data, options) |
Apply choropleth data coloring |
app.mapSystem.addMarker(options) |
Add marker at lat/lon coordinates |
app.mapSystem.addLabels(options) |
Add region labels |
app.mapSystem.getRegionAtPoint(point) |
Get region at canvas point |
app.mapSystem.panTo(lat, lon) |
Pan map to coordinates |
app.mapSystem.zoomTo(level) |
Set map zoom level |
app.mapSystem.exportMap() |
Export map configuration |
app.mapSystem.importCustomMap(geoJson, options) |
Import custom GeoJSON/TopoJSON |
app.mapSystem.on(event, callback) |
Listen to map events (regionClick, regionHover, markerClick) |