如何保存并重新加载Forge Viewer中基于SVG的Pushpin标记至数据库?
Great job getting those SVG-based pushpins working in the Viewer! Saving and reloading them is totally doable—here's a step-by-step breakdown to make it happen:
Step 1: Collect the Pushpin Data You Need to Persist
First, extract the critical information from your existing pushpins that you'll need to recreate them later. The core data points include:
- World-space position: Ensures the pin stays anchored to the correct spot on the model, regardless of camera angle or window size.
- Custom SVG content: The actual SVG markup defining the pin's appearance.
- Optional extras: Associated model
dbId(if the pin is tied to a specific component), a unique pin ID, user metadata, etc.
Here's how to grab this data from the MarkupsCore extension:
// Get the MarkupsCore extension instance const markupsExt = viewer.getExtension('Autodesk.Viewing.MarkupsCore'); // Filter only pushpin markups const pushpins = markupsExt.getMarkups().filter(markup => markup.type === 'pushpin'); // Map pushpins to a serializable data structure const serializablePushpins = pushpins.map(pin => ({ id: pin.id, position: pin.position, // 3D world coordinate array [x, y, z] svgContent: pin.svgContent, // Your custom SVG string dbId: pin.dbId, // Optional: if linked to a model component // Add any other custom properties you want to save (e.g., notes, color) }));
Step 2: Save the Data to Your Database
Send this serialized data to your backend API to store in a database (like PostgreSQL, MongoDB, etc.). Be sure to associate the pushpins with the model's URN so you can retrieve the correct pins for the right model later.
Example frontend code to send the data:
// Send data to your backend endpoint fetch('/api/pushpins/save', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ modelUrn: viewer.model.id, // Tie pins to the specific model pushpins: serializablePushpins }) }) .then(res => res.json()) .then(() => console.log('Pushpins saved successfully!')) .catch(err => console.error('Failed to save pushpins:', err));
On the backend, handle this request by storing the modelUrn and pushpin data in your database. The exact implementation depends on your tech stack, but the key is keeping pins linked to their associated model.
Step 3: Reload the Pushpins into the Viewer
When the model finishes loading in the Viewer, fetch the saved pushpin data from your backend and recreate each pin using the MarkupsCore extension.
First, fetch the data and recreate the pins:
// Fetch pins for the current model fetch(`/api/pushpins/get?modelUrn=${viewer.model.id}`) .then(res => res.json()) .then(data => { const markupsExt = viewer.getExtension('Autodesk.Viewing.MarkupsCore'); // Enter edit mode to create new markups markupsExt.enterEditMode(); // Recreate each pushpin from the saved data data.pushpins.forEach(pinData => { // Create the pushpin using the saved position and SVG const newPushpin = markupsExt.createPushpin(pinData.position, pinData.svgContent); // Restore optional properties if needed if (pinData.dbId) newPushpin.dbId = pinData.dbId; newPushpin.id = pinData.id; // Add back any other custom properties you saved }); // Exit edit mode to make pins interactive markupsExt.leaveEditMode(); }) .catch(err => console.error('Failed to load pushpins:', err));
Key Notes & Troubleshooting
- Always use world coordinates: Avoid saving screen coordinates—they change with camera position and window size. World coordinates keep pins anchored correctly.
- SVG string integrity: Ensure your SVG isn't truncated or escaped incorrectly when saving/loading. Use
JSON.stringifyon the frontend to preserve the string, and make sure your backend stores it as raw text. - Extension readiness: Guarantee the MarkupsCore extension is fully loaded before creating or fetching pins. You can wrap your code in
viewer.loadExtension('Autodesk.Viewing.MarkupsCore')to ensure availability. - Edit mode requirement: You must enter edit mode before creating new markups, and exit it afterward to make pins interactive for users.
内容的提问来源于stack exchange,提问作者Trung Tran

