### Install @icraft/player using npm or pnpm Source: https://github.com/gantfdt/icraft/blob/main/docs/javascript/intro.en-US.mdx Instructions for installing the @icraft/player package using npm or pnpm. Note that some package managers might require manual installation of @icraft/engine if it's missing. ```bash # Using npm npm install @icraft/player --save # Or using pnpm pnpm install @icraft/player --save ``` -------------------------------- ### Install @icraft/player-react and engine packages Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/intro.en-US.mdx Instructions for installing the @icraft/player-react package using npm or pnpm. Includes a note about manually installing the @icraft/engine package if it's missing. ```bash # Using npm npm install @icraft/player-react --save # Or using pnpm pnpm install @icraft/player-react --save Note: Some package managers may not automatically install the @icraft/engine package. If it's missing, please install it manually: pnpm install @icraft/engine --save ``` -------------------------------- ### HTML Example: Playing Animations with ICraftPlayer Source: https://github.com/gantfdt/icraft/blob/main/docs/javascript/animation.zh-CN.mdx This example demonstrates how to initialize the `ICraftPlayer`, load a scene, and apply various animations (Rotate, HeartBeat, LoopFlow) to elements based on user interaction (clicks) or initial setup. It also shows how to cancel active animations. ```HTML ICraft Player Click Demo
``` -------------------------------- ### Manually install @icraft/engine dependency Source: https://github.com/gantfdt/icraft/blob/main/player-react.README.md Provides a command to manually install the @icraft/engine package, which might be required if not automatically installed by the package manager. ```bash pnpm install @icraft/engine --save ``` -------------------------------- ### Install @icraft/player-react package Source: https://github.com/gantfdt/icraft/blob/main/player-react.README.md Instructions for installing the @icraft/player-react component using npm or pnpm package managers. ```bash npm install @icraft/player-react --save ``` ```bash pnpm install @icraft/player-react --save ``` -------------------------------- ### Install Project Dependencies with pnpm Source: https://github.com/gantfdt/icraft/blob/main/demos/vue/README.md Installs all necessary project dependencies using pnpm, preparing the environment for development or production builds. ```sh pnpm install ``` -------------------------------- ### Install @icraft/player package with npm or pnpm Source: https://github.com/gantfdt/icraft/blob/main/player-javascript.README.md Install the @icraft/player package using npm or pnpm. This ensures the component is available in your project. Note that @icraft/engine might require separate manual installation. ```bash # Using npm npm install @icraft/player --save # Or using pnpm pnpm install @icraft/player --save ``` -------------------------------- ### E-commerce Data Simulation Utilities for iCraft Player Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.zh-CN.mdx This utility file provides interfaces and sample data for simulating e-commerce product, consumer, and order status information. It includes functions to generate random data points and format messages, serving as a data source for the iCraft Player visualization example. ```typescript interface Product { name: string; models: string[]; } interface Consumer { name: string; address?: string; } interface OrderStatus { key: string; icon: string; title: string; messageTemplate: string; } const ORDER_STATUS: OrderStatus[] = [ { key: "1", icon: "🛍️", title: "New Order", messageTemplate: "Customer placed order for {product} at {time}" }, { key: "2", icon: "🏭", title: "Processing", messageTemplate: "E-commerce platform transferred {product} order to overseas warehouse at {time}" }, { key: "3", icon: "📦", title: "Shipping Preparation", messageTemplate: "Overseas warehouse dispatched {product} to international courier at {time}" }, { key: "4", icon: "✈️", title: "International Transit", messageTemplate: "International courier sent {product} to customs at {time}" }, { key: "5", icon: "🛃", title: "Customs Cleared", messageTemplate: "Customs released {product} to local courier at {time}" }, { key: "6", icon: "🚚", title: "Out for Delivery", messageTemplate: "Local courier is delivering {product} to {consumer} at {time}" } ]; const PRODUCTS: Product[] = [ { name: 'iPhone', models: ['14 Pro Max', '14 Pro', '14 Plus', '14', '13 Pro', '13'] }, { name: 'MacBook', models: ['Pro 14"', 'Pro 16"', 'Air M2', 'Air M1'] }, { name: 'iPad', models: ['Pro 12.9"', 'Pro 11"', 'Air', 'mini'] }, { name: 'AirPods', models: ['Pro 2', 'Pro', '3rd Gen', 'Max'] }, { name: 'Apple Watch', models: ['Ultra', 'Series 8', 'SE 2nd Gen'] }, { name: 'Canon EOS', models: ['R5', 'R6', 'R7', 'R10', '90D'] } ]; const CONSUMERS: Consumer[] = [ { name: 'John Smith', address: 'New York' }, { name: 'Emma Wilson', address: 'Los Angeles' }, { name: 'Michael Brown', address: 'Chicago' }, { name: 'Sarah Davis', address: 'Houston' }, { name: 'James Johnson', address: 'Phoenix' }, { name: 'Emily Taylor', address: 'Philadelphia' } ]; const getRandomTime = (): string => { const now = new Date(); return now.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); }; const getRandomProduct = (): string => { const product = PRODUCTS[Math.floor(Math.random() * PRODUCTS.length)]; const model = product.models[Math.floor(Math.random() * product.models.length)]; return `${product.name} ${model}`; }; const getRandomConsumer = (): Consumer => { return CONSUMERS[Math.floor(Math.random() * CONSUMERS.length)]; }; const formatMessage = (template: string, data: Record): string => { ``` -------------------------------- ### Install @icraft/player-react Component Source: https://github.com/gantfdt/icraft/blob/main/blog/player-react-integrated.en-US.md Instructions on how to install the @icraft/player-react component using the pnpm package manager. This command adds the component to your project's dependencies. ```bash pnpm install @icraft/player-react --save ``` -------------------------------- ### HTML/JavaScript Example: Playing and Cancelling ICraft Player Animations Source: https://github.com/gantfdt/icraft/blob/main/docs/javascript/animation.en-US.mdx This example demonstrates how to initialize the ICraftPlayer, load a template, and control element animations. It shows how to use `playAnimationByElementKey` on `onReady` and `onClick` events, applying different animation types based on element properties, and how to use `cancelAnimation` when no element is clicked. ```html ICraft Player Click Demo
``` -------------------------------- ### iCraft Player Click Event Example with HTML and JavaScript Source: https://github.com/gantfdt/icraft/blob/main/docs/javascript/click.zh-CN.mdx This example demonstrates how to initialize the iCraft Player, load a template, and implement an `onClick` callback function. When an element within the player is clicked, its name is extracted and displayed on the page. It requires the `icraft-player.min.js` library for functionality. ```html ICraft Player Click Demo
} ``` -------------------------------- ### Start Development Server with Hot-Reload Source: https://github.com/gantfdt/icraft/blob/main/demos/vue/README.md Compiles the project and starts a local development server with hot-reloading enabled, suitable for active development. ```sh pnpm dev ``` -------------------------------- ### iCraft Player Integration with Dynamic Status Display Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/serverstatus.zh-CN.mdx This example demonstrates how to embed the iCraft Player in a React application, handle click events on 3D elements, and dynamically display real-time status information using React Portals. It includes the main application logic, styling, and a reusable status card component. ```tsx import { ClickParams, Element3D, ICraftPlayer, ICraftPlayerInstance } from "@icraft/player-react"; import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { getData } from "./utils"; import { StatusCardProps } from "./interface"; import StatusCard from "./StatusCard"; import styles from "./index.module.css"; export default () => { const playerRef = useRef(null); const [tipContainer, setTipContainer] = useState(null); const [activeService, setActiveService] = useState("DTS"); const [activeData, setActiveData] = useState(null); const [fixed, setFixed] = useState(false); const elementRef = useRef(null); const onReady = () => { const player = playerRef.current; if (!activeService) { return; } const element = player?.getElementsByName(activeService)?.[0]; if (!element) return; elementRef.current = element; if (element?.tip) { const container = document.createElement("div"); element.tip.updateInnerHTML(container); element.tip.updateVisible(true); setTipContainer(container); } }; const onClick = (params: ClickParams) => { const { instance: element } = params; const player = playerRef.current; // clear old tip elementRef.current?.tip?.reset(); // clear old fixed container if (fixed && tipContainer) { tipContainer.remove(); } elementRef.current = element; if (!element) { setActiveService(null); setTipContainer(null); return; } const activeName = element.options?.name; setActiveService(activeName || null); if (fixed) { const container = document.createElement("div"); container.style.position = "absolute"; container.style.top = "10px"; container.style.right = "10px"; container.style.zIndex = "100"; player?.getDom().appendChild(container); setTipContainer(container); } else { if (element?.tip) { const container = document.createElement("div"); element.tip.updateInnerHTML(container); element.tip.updateVisible(true); setTipContainer(container); } } }; useEffect(() => { if (!activeService) return; const interval = setInterval(() => { setActiveData(getData(activeService)); }, 100); return () => clearInterval(interval); }, [activeService]); return (
fixed
{tipContainer && activeData && createPortal( , tipContainer )}
); }; ``` ```css .container{ width: 100%; height: 100%; position: relative; overflow: hidden; } .checkbox { position: absolute; top: 10px; left: 10px; z-index: 1; display: flex; align-items: center; gap: 8px; } .switch { position: relative; display: inline-block; width: 40px; height: 20px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 20px; } .slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .slider { background-color: #2196F3; } input:checked + .slider:before { transform: translateX(20px); } ``` ```tsx import React from "react"; import styles from "./StatusCard.module.css"; import { StatusCardProps } from "./interface"; import { getProgressBarClassName, getStatusDisplay } from "./utils"; const StatusCard: React.FC = ({ serviceName, status, metrics }) => { const statusDisplay = getStatusDisplay(status); return (
``` -------------------------------- ### Include @icraft/player via CDN script tag Source: https://github.com/gantfdt/icraft/blob/main/player-javascript.README.md Integrate @icraft/player directly into your HTML by including a script tag from the unpkg CDN. This method provides a quick way to get started without a package manager. ```html ``` -------------------------------- ### Quickly Enable iCraft Player Addons with String Array Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/addon.zh-CN.mdx This example demonstrates how to quickly enable multiple iCraft Player addons by passing an array of addon keys to the `addons` prop. This method provides a straightforward way to integrate common functionalities like camera, zoom, sub-scene navigation, and player controls. ```tsx import { ICraftPlayer } from "@icraft/player-react"; const style = { width: "100%", height: "100%", position: "relative" as const, overflow: "hidden" as const, }; export default () => { return (
); }; ``` -------------------------------- ### Generate Mock E-commerce Order Status Data (JavaScript) Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.zh-CN.mdx This asynchronous function generates a list of mock e-commerce order statuses, dynamically formatting messages with random time, product, and consumer details. It returns an array of objects, each containing a key, icon, title, and an HTML-formatted message. ```javascript export const getEcommerceData = async () => { const time = getRandomTime(); const product = getRandomProduct(); const consumer = getRandomConsumer(); return ORDER_STATUS.map(({ key, icon, title, messageTemplate }) => ({ key, value: `
${icon} ${title}
${formatMessage(messageTemplate, { time, product, consumer: `${consumer.name} (${consumer.address})` })}
` })); }; ``` -------------------------------- ### Create Custom Tooltips with ICraftPlayer Source: https://github.com/gantfdt/icraft/blob/main/docs/javascript/tip.en-US.mdx This example demonstrates how to create a custom tooltip for an element within an ICraftPlayer instance using native HTML elements. It initializes a player, finds an element by name, and updates its tooltip content and visibility with dynamically generated HTML and CSS for a mini-profile card. ```html ICraft Player Tip Demo
``` -------------------------------- ### Define E-commerce Data Structures and Utility Functions Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.en-US.mdx This TypeScript file defines interfaces for Product, Consumer, and OrderStatus to structure e-commerce related data. It includes constant arrays for predefined order statuses, product lists, and consumer information. Additionally, it provides utility functions to generate random times, products, and consumers, and a formatMessage function (partially shown) for dynamic message creation. ```ts interface Product { name: string; models: string[]; } interface Consumer { name: string; address?: string; } interface OrderStatus { key: string; icon: string; title: string; messageTemplate: string; } const ORDER_STATUS: OrderStatus[] = [ { key: "1", icon: "🛍️", title: "New Order", messageTemplate: "Customer placed order for {product} at {time}" }, { key: "2", icon: "🏭", title: "Processing", messageTemplate: "E-commerce platform transferred {product} order to overseas warehouse at {time}" }, { key: "3", icon: "📦", title: "Shipping Preparation", messageTemplate: "Overseas warehouse dispatched {product} to international courier at {time}" }, { key: "4", icon: "✈️", title: "International Transit", messageTemplate: "International courier sent {product} to customs at {time}" }, { key: "5", icon: "🛃", title: "Customs Cleared", messageTemplate: "Customs released {product} to local courier at {time}" }, { key: "6", icon: "🚚", title: "Out for Delivery", messageTemplate: "Local courier is delivering {product} to {consumer} at {time}" } ]; const PRODUCTS: Product[] = [ { name: 'iPhone', models: ['14 Pro Max', '14 Pro', '14 Plus', '14', '13 Pro', '13'] }, { name: 'MacBook', models: ['Pro 14"', 'Pro 16"', 'Air M2', 'Air M1'] }, { name: 'iPad', models: ['Pro 12.9"', 'Pro 11"', 'Air', 'mini'] }, { name: 'AirPods', models: ['Pro 2', 'Pro', '3rd Gen', 'Max'] }, { name: 'Apple Watch', models: ['Ultra', 'Series 8', 'SE 2nd Gen'] }, { name: 'Canon EOS', models: ['R5', 'R6', 'R7', 'R10', '90D'] } ]; const CONSUMERS: Consumer[] = [ { name: 'John Smith', address: 'New York' }, { name: 'Emma Wilson', address: 'Los Angeles' }, { name: 'Michael Brown', address: 'Chicago' }, { name: 'Sarah Davis', address: 'Houston' }, { name: 'James Johnson', address: 'Phoenix' }, { name: 'Emily Taylor', address: 'Philadelphia' } ]; const getRandomTime = (): string => { const now = new Date(); return now.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); }; const getRandomProduct = (): string => { const product = PRODUCTS[Math.floor(Math.random() * PRODUCTS.length)]; const model = product.models[Math.floor(Math.random() * product.models.length)]; return `${product.name} ${model}`; }; const getRandomConsumer = (): Consumer => { return CONSUMERS[Math.floor(Math.random() * CONSUMERS.length)]; }; const formatMessage = (template: string, data: Record): string => { ``` -------------------------------- ### Format Message with Placeholders in JavaScript Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.en-US.mdx This JavaScript snippet demonstrates how to replace placeholders in a template string using an object's key-value pairs. It iterates over the data object, replacing each '{key}' in the template with its corresponding 'value'. ```JavaScript return Object.entries(data).reduce((message, [key, value]) => { return message.replace(`{${key}}`, value); }, template); ``` -------------------------------- ### Generate E-commerce Order Status Data in JavaScript Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.en-US.mdx This asynchronous JavaScript function generates a list of e-commerce order status items. It retrieves random time, product, and consumer data, then maps over an 'ORDER_STATUS' array to create formatted HTML content for each status, utilizing a 'formatMessage' helper. ```JavaScript export const getEcommerceData = async () => { const time = getRandomTime(); const product = getRandomProduct(); const consumer = getRandomConsumer(); return ORDER_STATUS.map(({ key, icon, title, messageTemplate }) => ({ key, value: `
${icon} ${title}
${formatMessage(messageTemplate, { time, product, consumer: `${consumer.name} (${consumer.address})` })}
` })); }; ``` -------------------------------- ### Format Message with Dynamic Data (JavaScript) Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.zh-CN.mdx This function replaces placeholders in a template string with corresponding values from a data object. It's useful for dynamic message generation where specific parts of a string need to be filled in at runtime. ```javascript const formatMessage = (template, data) => { return Object.entries(data).reduce((message, [key, value]) => { return message.replace(`{${key}}`, value); }, template); }; ``` -------------------------------- ### Visualize E-commerce Data with iCraft Player in React Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.zh-CN.mdx This React component integrates the `ICraftPlayer` to visualize simulated real-time e-commerce order status updates. It dynamically creates HTML cards as tips, uses `playAnimationByElementKey` to highlight scene elements with flow animations, and `changeCustomCamera` for scene transitions. Data updates are fetched and processed at regular intervals using `setInterval`. ```typescript import { AnimationType, ICraftPlayer, ICraftPlayerInstance } from "@icraft/player-react"; import React, { useRef } => "react"; import { getEcommerceData } from "./utils"; const style = { width: "100%", height: "100%", position: "relative" as const, overflow: "hidden" as const, }; const getCard = (value: string) => { const card = document.createElement("div"); card.innerHTML = value; card.style.cssText = ` padding: 12px 16px; background: rgba(255, 255, 255, 0.95); border-radius: 8px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); font-size: 14px; color: #333; max-width: 280px; line-height: 1.5; word-break: break-all; `; return card; }; export default () => { const playerRef = useRef(null); const timerRef = useRef(); const currentIndexRef = useRef(0); const receiveData = async () => { const player = playerRef.current; if (!player) return; const data = await getEcommerceData(); const { key, value } = data[currentIndexRef.current]; const line = player.getElementsByName(key)?.[0]; const card = getCard(value); if (line) { player.playAnimationByElementKey(line.key, { animationType: AnimationType.Flow, animationDuration: 3, tipContent: card, animationShowTip: true, flowLineColor: "#1a73e8", }); } currentIndexRef.current = (currentIndexRef.current + 1) % data.length; player.changeCustomCamera(currentIndexRef.current,3000); }; React.useEffect(() => { timerRef.current = setInterval(receiveData, 4000); return () => { if (timerRef.current) { clearInterval(timerRef.current); } }; }, []); return (
); }; ``` -------------------------------- ### CSS Styles for Status Card Component Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/serverstatus.zh-CN.mdx This CSS module (`StatusCard.module.css`) defines the visual styling for the `StatusCard` component. It includes styles for the card container, title section, metric rows, and dynamic progress bars, applying a frosted glass effect and responsive layouts. It also defines specific styles for warning and danger states of the progress bar. ```css .statusCard { width: 260px; padding: 12px; position: relative; border-radius: 12px; z-index: 1; } .statusCard::before { content: ''; position: absolute; inset: 0; background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.3); border-radius: inherit; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); z-index: -1; } .content { position: relative; display: flex; flex-direction: column; gap: 16px; z-index: 2; } .titleRow { display: flex; justify-content: space-between; align-items: center; width: 100%; } .titleLeft { display: flex; align-items: center; } .titleRight { display: flex; align-items: center; gap: 4px; font-weight: bold; } .title { font-size: 14px; color: #374151; font-weight: bold; } .checkmark { color: #22c55e; margin-right: 2px; } .status { font-size: 14px; font-weight: bold; } .lastUpdate { font-size: 13px; color: #6B7280; } .metrics { display: flex; flex-direction: column; gap: 8px; } .metricRow { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: #4B5563; } .metricLabel { display: flex; justify-content: space-between; align-items: center; } .progressWrapper { width: 100%; height: 4px; background: rgba(0, 0, 0, 0.05); border-radius: 2px; overflow: hidden; } .progressBar { height: 100%; background: #22c55e; border-radius: 2px; transition: all 0.3s ease; } .progressBar.warning { background: #f59e0b; } .progressBar.danger { background: #ef4444; } .footer { font-size: 13px; color: #6B7280; } .uptimeRow { display: flex; flex-direction: row; justify-content: space-between; gap: 4px; padding-top: 4px; font-size: 13px; color: #4B5563; } .uptimeValue { color: #6B7280; } ``` -------------------------------- ### Visualize E-commerce Data with iCraft Player in React Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/ecommerce.en-US.mdx This React component integrates the ICraftPlayer to display a dynamic e-commerce visualization. It fetches simulated order data using getEcommerceData from utils.ts and updates the player's animation and camera based on the current order status. Custom HTML cards are generated to show detailed tip content for each status update, with updates occurring at a set interval. ```tsx import { AnimationType, ICraftPlayer, ICraftPlayerInstance } from "@icraft/player-react"; import React, { useRef } from "react"; import { getEcommerceData } from "./utils"; const style = { width: "100%", height: "100%", position: "relative" as const, overflow: "hidden" as const, }; const getCard = (value: string) => { const card = document.createElement("div"); card.innerHTML = value; card.style.cssText = ` padding: 12px 16px; background: rgba(255, 255, 255, 0.95); border-radius: 8px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); font-size: 14px; color: #333; max-width: 280px; line-height: 1.5; word-break: break-all; `; return card; }; export default () => { const playerRef = useRef(null); const timerRef = useRef(); const currentIndexRef = useRef(0); const receiveData = async () => { const player = playerRef.current; if (!player) return; const data = await getEcommerceData(); const { key, value } = data[currentIndexRef.current]; const line = player.getElementsByName(key)?.[0]; const card = getCard(value); if (line) { player.playAnimationByElementKey(line.key, { animationType: AnimationType.Flow, animationDuration: 3, tipContent: card, animationShowTip: true, flowLineColor: "#1a73e8", }); } currentIndexRef.current = (currentIndexRef.current + 1) % data.length; player.changeCustomCamera(currentIndexRef.current,3000); }; React.useEffect(() => { timerRef.current = setInterval(receiveData, 4000); return () => { if (timerRef.current) { clearInterval(timerRef.current); } }; }, []); return (
); }; ``` -------------------------------- ### Create Custom iCraft Player Plugins by Interacting with Instance Methods Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/addon.zh-CN.mdx This example illustrates how to create a custom plugin by interacting with the iCraft Player instance methods. It demonstrates toggling the auto-rotate feature via a custom button, showcasing how to access and control player functionalities programmatically using `useRef` and `useState` hooks. ```tsx import { ICraftPlayer, ICraftPlayerInstance } from "@icraft/player-react"; import { useRef, useState } from "react"; const style = { width: "100%", height: "100%", position: "relative" as const, overflow: "hidden" as const, }; const ButtonStyle = { position: "absolute" as const, bottom: "10px", right: "10px", zIndex: 1000, backgroundColor: "white", color: "black", border: "1px solid #ccc", borderRadius: "6px", padding: "4px 8px", }; export default () => { const [autoRotate, setAutoRotate] = useState(false); const instanceRef = useRef(null); const handleToggleAutoRotate = () => { const value = !autoRotate; instanceRef.current?.toogleAutoRotate(value); setAutoRotate(value); }; return (
} />
); }; ``` -------------------------------- ### TypeScript Interface for Status Card Properties Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/serverstatus.zh-CN.mdx This TypeScript interface, `StatusCardProps`, defines the expected data structure for the properties passed to the `StatusCard` component. It specifies types for `serviceName`, `status` (a union type of 'running', 'stopped', or 'error'), and a nested `metrics` object containing `cpu`, `memory`, and `uptime` details. ```APIDOC export type StatusType = "running" | "stopped" | "error"; export interface StatusCardProps { // Service basic info serviceName: string; status: StatusType; // System metrics metrics: { cpu: number; memory: number; uptime: { days: number; hours: number; minutes: number; }; }; } ``` -------------------------------- ### Initialize ICraft Player and Display User Tip Source: https://github.com/gantfdt/icraft/blob/main/demos/javascript/tip.html Initializes the ICraftPlayer with a specified source and container. The `onReady` callback dynamically creates a user profile card, applies its styles, and updates the 'User' element's tip to display the generated card. ```JavaScript const player = new ICraftPlayer({ src: "/templates/AWSCloud.iplayer", container: document.getElementById("container"), onReady: (player) => { const user = player?.getElementsByName("User")?.[0]; const card = document.createElement("div"); card.innerHTML = getUserCard("John Doe", "Operations Engineer"); const cardStyle = getUserCardStyle(); card.appendChild(cardStyle); user?.tip?.updateInnerHTML(card); user?.tip?.updateVisible(true); }, }); ``` -------------------------------- ### Player Instance Methods API Reference Source: https://github.com/gantfdt/icraft/blob/main/docs/javascript/api.zh-CN.mdx Detailed API documentation for methods available on the `Player` instance, including their signatures, parameters, and descriptions for interacting with 3D scenes, elements, and animations. ```APIDOC Player Instance Methods: getDom: () => HTMLElement description: 获取 dom getElementByKey: (key: string) => Element3D | undefined description: 通过唯一标识获取元素实例 getElementsByName: (name: string) => Element3D[] description: 通过名称获取多个元素实例 getCurrentSceneElements: () => Element3D[] description: 获取当前场景所有元素实例(不包含子场景) getAllSceneElementsData: () => ElementData[] description: 获取当前场景所有元素数据(包含子场景) playAnimationByElementKey: (elementKey: string, animationOptions: AnimationActionOptions) => void description: 使元素执行内置动画 cancelAnimation: () => void description: 取消所有动画 toogleView: (is3D: boolean) => void description: 切换 2D/3D 视图 toogleCamera: (isPerspectiveCamera: boolean) => void description: 切换相机类型(透视 | 正交) toogleAutoRotate: (isAutoRotate: boolean) => void description: 切换自动旋转 updateAutoRotateSpeed: (speed: number) => void description: 更新自动旋转速度 changeCustomCamera: (index: number) => void description: 切换自定义相机 enterSubScene: () => void description: 进入当前选中元素的子场景 exitSubScene: () => void description: 退出子场景 tooglePlay: () => void description: 切换播放 prevStep: () => void description: 上一步 nextStep: () => void description: 下一步 replay: () => void description: 重播 reset: () => void description: 重置 toggleLoop: () => void description: 切换循环 zoomIn: () => void description: 视角放大 zoomOut: () => void description: 视角缩小 resetCamera: () => void description: 重置相机视角 exportImage: () => void description: 导出图片 openFileByUrl: (url: string, options?: RequestInit) => void description: 通过 url 打开文件 ``` -------------------------------- ### Importing Server Status Demo Components Source: https://github.com/gantfdt/icraft/blob/main/docs/player-react/example/serverstatus.en-US.mdx Imports the `Wrap` utility and `ServerStatusDemo` components from a local path to enable embedding the real-time server status visualization. ```JavaScript import { Wrap, ServerStatusDemo } from "../../../demos"; ```