Preview Updated 2026-05-10

ImageAnnotator 图像标注

图像 + 钉点标注。点击空白添加、拖动钉点修改坐标、点选弹出删除按钮。坐标用 0–1 归一化以便不同尺寸下复用。

English translation pending This page hasn't been translated yet — falling back to Chinese. PRs welcome on GitHub.

基础用法

annotations 数组用 { id, x, y, label?, tone? }x / y 是图片归一化坐标(0–1)。点击图片空白处自动添加新钉;拖动钉更新坐标;选中后可点 × 删除。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfImageAnnotator, type ImageAnnotation } from '@chufix-design/vue';

const svg =
  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 360">' +
  '<rect width="100%" height="100%" fill="#26272a"/>' +
  '<rect x="80" y="80" width="180" height="180" fill="#404048" stroke="#656571" stroke-width="2" rx="8"/>' +
  '<rect x="300" y="150" width="220" height="50" fill="#404048" stroke="#656571" stroke-width="2" rx="4"/>' +
  '<text x="170" y="350" fill="#99999f" font-family="sans-serif" font-size="14" text-anchor="middle">主板示意图(点击空白添加,拖动钉点)</text>' +
  '</svg>';
const imgSrc = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;

const annotations = ref<ImageAnnotation[]>([
  { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
  { id: 'mem', x: 0.55, y: 0.48, label: '内存条', tone: 'info' },
]);
const selectedId = ref<string | undefined>('cpu');
</script>
<template>
  <div class="ia-demo">
    <CfImageAnnotator
      :src="imgSrc"
      alt="主板示意"
      :annotations="annotations"
      :selected-id="selectedId"
      @update:annotations="annotations = $event"
      @select="(id) => (selectedId = id)"
    />
    <code class="ia-demo__meta">
      {{ annotations.length }} 个标记 · selected = {{ selectedId ?? '-' }}
    </code>
  </div>
</template>
<style scoped>
.ia-demo {
  display: grid;
  gap: 8px;
}
.ia-demo__meta {
  padding: 4px 8px;
  background: var(--bg-inset);
  border-radius: var(--r-2);
  font-size: var(--t-12);
  color: var(--fg-2);
}
</style>
<script setup>
import { ref } from 'vue';
import { CfImageAnnotator } from '@chufix-design/vue';

const svg =
  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 360">' +
  '<rect width="100%" height="100%" fill="#26272a"/>' +
  '<rect x="80" y="80" width="180" height="180" fill="#404048" stroke="#656571" stroke-width="2" rx="8"/>' +
  '<rect x="300" y="150" width="220" height="50" fill="#404048" stroke="#656571" stroke-width="2" rx="4"/>' +
  '<text x="170" y="350" fill="#99999f" font-family="sans-serif" font-size="14" text-anchor="middle">主板示意图(点击空白添加,拖动钉点)</text>' +
  '</svg>';
const imgSrc = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;

const annotations = ref<ImageAnnotation[]>([
  { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
  { id: 'mem', x: 0.55, y: 0.48, label: '内存条', tone: 'info' },
]);
const selectedId = ref<string | undefined>('cpu');
</script>
<template>
  <div class="ia-demo">
    <CfImageAnnotator
      :src="imgSrc"
      alt="主板示意"
      :annotations="annotations"
      :selected-id="selectedId"
      @update:annotations="annotations = $event"
      @select="(id) => (selectedId = id)"
    />
    <code class="ia-demo__meta">
      {{ annotations.length }} 个标记 · selected = {{ selectedId ?? '-' }}
    </code>
  </div>
</template>
<style scoped>
.ia-demo {
  display: grid;
  gap: 8px;
}
.ia-demo__meta {
  padding: 4px 8px;
  background: var(--bg-inset);
  border-radius: var(--r-2);
  font-size: var(--t-12);
  color: var(--fg-2);
}
</style>
import { useState } from 'react';
import { CfImageAnnotator } from '@chufix-design/react';

export default function Demo() {
  const [annotations, setAnnotations] = useState([
    { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
    { id: 'mem', x: 0.55, y: 0.48, label: '内存条', tone: 'info' },
  ]);
  const [annotations, setAnnotations] = useState([
    { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
    { id: 'mem', x: 0.55, y: 0.48, label: '内存条', tone: 'info' },
  ]);
  const [selectedId, setSelectedId] = useState('cpu');
  const [selectedId, setSelectedId] = useState('cpu');
  const [annotations, setAnnotations] = useState([
  { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
  ]);
  const [selectedId, setSelectedId] = useState<string>('cpu');
  return (
    <>
      <CfImageAnnotator
      src="/board.png"
      annotations={annotations}
      selectedId={selectedId}
      onChange={setAnnotations}
      onSelect={setSelectedId}
      />
    </>
  );
}
import { useState } from 'react';
import { CfImageAnnotator } from '@chufix-design/react';

export default function Demo() {
  const [annotations, setAnnotations] = useState([
    { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
    { id: 'mem', x: 0.55, y: 0.48, label: '内存条', tone: 'info' },
  ]);
  const [annotations, setAnnotations] = useState([
    { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
    { id: 'mem', x: 0.55, y: 0.48, label: '内存条', tone: 'info' },
  ]);
  const [selectedId, setSelectedId] = useState('cpu');
  const [selectedId, setSelectedId] = useState('cpu');
  const [annotations, setAnnotations] = useState([
  { id: 'cpu', x: 0.22, y: 0.34, label: 'CPU 散热片', tone: 'success' },
  ]);
  const [selectedId, setSelectedId] = useState<string>('cpu');
  return (
    <>
      <CfImageAnnotator
      src="/board.png"
      annotations={annotations}
      selectedId={selectedId}
      onChange={setAnnotations}
      onSelect={setSelectedId}
      />
    </>
  );
}

API

Props

属性类型默认说明
srcstring图片 URL
altstring''alt 文本
annotationsImageAnnotation[]钉点数组
readonlybooleanfalse只读:禁止添加 / 拖动 / 删除
addMode'click' | 'manual''click'点击空白处是否自动加钉
selectedIdstring当前选中的钉 id
defaultToneAnnotationTone'info'新加钉默认 tone

Events

事件载荷说明
update:annotationsImageAnnotation[]列表变更(增 / 改 / 删)
addImageAnnotation新加钉
updateImageAnnotation钉坐标更新
deleteid: string删钉
selectid: string选中

反馈与讨论

ImageAnnotator 图像标注 · Discussion

0
0 / 600
正在加载评论...