import { ImageTracer, Options } from "@image-tracer-ts/core"; //@ts-ignore import {SVGLoader, SVGResult} from "three/examples/jsm/loaders/SVGLoader"; import {Color, ShapePath, Shape} from "three"; export interface TracedLayer { id: string; name: string; color: Color; paths: Shape[]; } export interface PathData { points: Point[]; isClosed: boolean; } export interface Point { x: number; y: number; } export interface TraceResult { width: number; height: number; layers: TracedLayer[]; } /** * 将图像转换为矢量路径 * @param image - 要追踪的图片元素 * @param options - 追踪选项 * @returns 追踪结果 */ export async function traceImage( image: HTMLImageElement, options?: Partial ): Promise { // 创建 canvas 来获取图片数据 const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); if (!ctx) { throw new Error("无法创建 canvas 上下文"); } // 设置 canvas 尺寸为图片原始尺寸 canvas.width = image.naturalWidth || image.width; canvas.height = image.naturalHeight || image.height; // 绘制图片到 canvas ctx.drawImage(image, 0, 0); // 获取图片数据 const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); // 默认配置 - 使用 detailed preset 作为基础 const defaultOptions: Partial = { ...Options.Presets.default, numberOfColors: 8, // 限制颜色数量以控制图层数 minColorQuota: 0.01, // 降低最小颜色占比阈值 strokeWidth: 0, // 不需要描边 lineFilter: true, ...options, }; // 创建追踪器 const tracer = new ImageTracer(defaultOptions); // 执行追踪,返回 SVG 字符串 const svgString = tracer.traceImage(imageData); // 解析 SVG 字符串 const loader = new SVGLoader(); const result = loader.parse(svgString) as SVGResult; const paths: ShapePath[] = result.paths; const layers: TracedLayer[] = paths.map((path, i,) => { return { id: `layer-${i}`, name: `颜色层 ${i + 1}`, color: path.color, paths: SVGLoader.createShapes(path), }; }); return { width: canvas.width, height: canvas.height, layers, }; }