npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tuoyuan/img-map-container

v1.2.11

Published

Vue 3 图片地图容器组件,支持在图片上展示和管理资源位置(点、线、面)

Readme

@tuoyuan/img-map-container

Vue 3 图片地图容器组件,支持在图片上展示和管理资源位置(点、线、面)。

特性

  • 🗺️ 基于图片的地图展示
  • 📍 支持点、线、面三种几何类型的资源
  • 🎨 可自定义资源样式
  • 🔍 支持缩放和拖拽
  • 🎯 资源点击事件
  • 📦 开箱即用,零配置
  • 🎭 TypeScript 支持
  • 🔄 自动加载资源类型列表

安装

npm install @tuoyuan/img-map-container
# 或
pnpm add @tuoyuan/img-map-container
# 或
yarn add @tuoyuan/img-map-container

快速开始

1. 安装插件

main.ts 中注册插件:

import { createApp } from 'vue'
import App from './App.vue'
import ImgMapPlugin from '@tuoyuan/img-map-container'

const app = createApp(App)

// 注册插件,配置 API 基础路径和认证信息
app.use(ImgMapPlugin, {
  baseUrl: '/gateway-api',  // 你的 API 网关地址
  appId: 'your-app-id',     // 地图管理平台的 app_id
  appKey: 'your-app-key',   // 地图管理平台的 app_key
  getToken: (callback) => {
    // 提供 access_token
    callback('your-access-token')
  }
})

app.mount('#app')

重要说明:

  • appIdappKey:地图管理平台分配的应用凭证,用于 API 认证
  • getToken:提供用户的 access_token,用于权限验证
  • baseUrl:API 网关地址,默认为 /gateway-api

2. 使用组件

<template>
  <div style="width: 100vw; height: 100vh;">
    <ImgMapContainer
      ref="mapRef"
      :map-id="mapId"
      @resource-click="handleResourceClick"
      @map-loaded="handleMapLoaded"
      @resources-loaded="handleResourcesLoaded"
      @resource-types-loaded="handleResourceTypesLoaded"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ImgMapContainer } from '@tuoyuan/img-map-container'
import type { 
  MapInfo, 
  ResourcePlacement, 
  ResourceClickEvent,
  ResourceType 
} from '@tuoyuan/img-map-container'

const mapRef = ref()
const mapId = ref('your-map-id')

function handleMapLoaded(mapInfo: MapInfo) {
  console.log('地图加载成功:', mapInfo)
}

function handleResourceTypesLoaded(types: ResourceType[]) {
  console.log('资源类型列表:', types)
  // 地图加载后会自动获取资源类型列表
  // 你可以在这里展示资源类型选择器
}

function handleResourcesLoaded(placements: ResourcePlacement[]) {
  console.log('资源加载完成,共', placements.length, '个')
}

function handleResourceClick(event: ResourceClickEvent) {
  console.log('点击了资源:', event.resource)
}

// 加载指定类型的资源
function loadResourceType(typeKey: string) {
  mapRef.value?.loadResources(typeKey)
}
</script>

核心概念

工作流程

1. 组件初始化
   ↓
2. 加载地图信息(自动)
   ↓
3. 加载资源类型列表(自动)
   ↓
4. 触发 resource-types-loaded 事件
   ↓
5. 用户选择资源类型
   ↓
6. 调用 loadResources(typeKey) 加载资源
   ↓
7. 资源自动渲染到地图上

数据流

后端 API
  ↓
ImgMapContainer (组件内部)
  ├─ 地图信息 (mapInfo)
  ├─ 资源类型列表 (resourceTypes) 
  └─ 资源位置列表 (placements)
       ↓
  计算属性自动分类
  ├─ pointPlacements (点资源)
  ├─ linePlacements (线资源)
  └─ polygonPlacements (面资源)
       ↓
  SVG 自动渲染
  ├─ <circle> 渲染点
  ├─ <polyline> 渲染线
  └─ <polygon> 渲染面

API 文档

Props

| 属性 | 类型 | 必填 | 说明 | |------|------|------|------| | map-id | string | 是 | 地图 ID,用于加载地图信息和资源 |

Events

| 事件名 | 参数 | 触发时机 | 说明 | |--------|------|----------|------| | map-loaded | (mapInfo: MapInfo) | 地图信息加载完成 | 返回地图的基本信息(名称、尺寸等) | | resource-types-loaded | (types: ResourceType[]) | 资源类型列表加载完成 | 地图加载后自动获取,返回所有可用的资源类型 | | resources-loaded | (placements: ResourcePlacement[]) | 资源位置列表加载完成 | 调用 loadResources 后触发 | | resource-click | (event: ResourceClickEvent) | 用户点击资源 | 返回被点击的资源详情 |

暴露的方法

通过 ref 可以调用以下方法:

loadResources(typeKeyOrId, append)

加载指定类型的资源并显示在地图上。

参数:

  • typeKeyOrId (string): 资源类型的 key 或 ID
  • append (boolean, 可选): 是否追加模式,默认 false
    • false: 替换模式,清空现有资源后加载新资源
    • true: 追加模式,保留现有资源,追加新资源(自动去重)

返回值: Promise<string | null> - 返回实际使用的 type_id,失败返回 null

示例:

// 替换模式:清空现有资源,只显示停车位
await mapRef.value.loadResources('parking-space')

// 追加模式:保留现有资源,追加建筑物
await mapRef.value.loadResources('building', true)

// 加载多种类型的资源
await mapRef.value.loadResources('parking-space', false)  // 先加载停车位
await mapRef.value.loadResources('building', true)        // 追加建筑物
await mapRef.value.loadResources('camera', true)          // 追加摄像头

toggleResourceType(typeKeyOrId)

切换资源类型的显示/隐藏状态。如果该类型已加载则隐藏,如果未加载则显示。

参数:

  • typeKeyOrId (string): 资源类型的 key 或 ID

返回值: Promise<boolean> - 返回切换后的状态,true 表示已加载,false 表示已隐藏

示例:

// 切换停车位的显示/隐藏
const isLoaded = await mapRef.value.toggleResourceType('parking-space')
console.log(isLoaded ? '已显示' : '已隐藏')

// 实现多选资源类型
async function handleTypeToggle(typeKey: string) {
  const isLoaded = await mapRef.value.toggleResourceType(typeKey)
  console.log(`资源类型 ${typeKey} 现在${isLoaded ? '可见' : '隐藏'}`)
}

使用场景:

  • 多选资源类型展示(类似图层控制)
  • 资源类型的开关切换
  • 复选框控制资源显示

isTypeLoaded(typeId)

检查指定资源类型是否已加载。

参数:

  • typeId (string): 资源类型 ID

返回值: boolean - true 表示已加载,false 表示未加载

示例:

// 检查停车位是否已加载
const isLoaded = mapRef.value.isTypeLoaded('parking-space-type-id')
console.log(isLoaded ? '已加载' : '未加载')

// 在 UI 中显示加载状态
<button 
  v-for="type in resourceTypes" 
  :key="type.id"
  @click="toggleType(type)"
  :class="{ active: mapRef?.isTypeLoaded(type.id) }"
>
  {{ type.name }}
</button>

clearResources()

清空地图上的所有资源(不影响后端数据)。

参数:

返回值: void

示例:

mapRef.value.clearResources()

deleteResource(placementId)

从地图上删除指定资源(仅前端删除,不调用后端 API)。

参数:

  • placementId (string): 资源位置 ID

返回值: boolean - 删除是否成功

示例:

const success = mapRef.value.deleteResource('placement-id-123')
if (success) {
  console.log('删除成功')
}

注意: 此方法只从前端的 placements 数组中移除资源,后端数据不受影响。

zoomIn()

放大地图。

参数:

返回值: void

示例:

mapRef.value.zoomIn()

zoomOut()

缩小地图。

参数:

返回值: void

示例:

mapRef.value.zoomOut()

resetView()

重置地图视图到初始状态(cover 模式)。

参数:

返回值: void

示例:

mapRef.value.resetView()

类型定义

MapInfo

地图基本信息。

interface MapInfo {
  id: string                    // 地图 ID
  name: string                  // 地图名称
  description?: string          // 地图描述
  image_url: string             // 地图图片 URL
  image_width: number           // 图片宽度(像素)
  image_height: number          // 图片高度(像素)
  center_x?: number             // 中心点 X 坐标
  center_y?: number             // 中心点 Y 坐标
  zoom_range?: [number, number] // 缩放范围
  default_zoom?: number         // 默认缩放级别
  status: number                // 状态
  created_at?: string           // 创建时间
  updated_at?: string           // 更新时间
}

ResourceType

资源类型信息。

interface ResourceType {
  id: string                              // 资源类型 ID
  name: string                            // 资源类型名称
  key: string                             // 资源类型唯一标识
  geometry_type: 'point' | 'line' | 'polygon'  // 几何类型
  is_external: boolean                    // 是否为外部引用
  icon_url?: string                       // 图标 URL
  style?: Record<string, any>             // 默认样式
  updated_at?: string                     // 更新时间
}

ResourcePlacement

资源位置信息。

interface ResourcePlacement {
  id: string                              // 位置 ID
  map_id: string                          // 地图 ID
  resource_id?: string                    // 资源 ID(内部资源)
  external_ref_id?: string                // 外部引用 ID
  geometry_type: 'point' | 'line' | 'polygon'  // 几何类型
  geometry: {                             // 几何数据
    coordinates: number[] | number[][] | number[][][]
    [key: string]: any
  }
  label_override?: string                 // 自定义标签
  style_override?: Record<string, any>    // 自定义样式
  resource?: any                          // 关联的资源对象
  externalRef?: any                       // 外部引用对象
}

坐标格式说明:

  • 点 (point): [x, y] - 例如 [100, 200]
  • 线 (line): [[x1, y1], [x2, y2], ...] - 例如 [[100, 200], [150, 250]]
  • 面 (polygon): [[[x1, y1], [x2, y2], ...]] - 外环 + 可选的内环

ResourceClickEvent

资源点击事件数据。

interface ResourceClickEvent {
  placement: ResourcePlacement  // 资源位置信息
  resource: any                 // 资源对象(resource 或 externalRef)
  event: MouseEvent             // 原始鼠标事件
}

完整示例

基础示例:多选资源类型(图层控制)

<template>
  <div class="map-container">
    <ImgMapContainer
      ref="mapRef"
      :map-id="mapId"
      @map-loaded="handleMapLoaded"
      @resource-types-loaded="handleResourceTypesLoaded"
      @resource-click="handleResourceClick"
    />
    
    <!-- 资源类型多选控制器 -->
    <div class="type-selector">
      <h3>资源图层</h3>
      <label 
        v-for="type in resourceTypes" 
        :key="type.id"
        class="type-checkbox"
      >
        <input 
          type="checkbox"
          :checked="isTypeLoaded(type.id)"
          @change="toggleType(type)"
        />
        <span>{{ type.name }}</span>
      </label>
      <button @click="clearAll" class="clear-btn">清空全部</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ImgMapContainer } from '@tuoyuan/img-map-container'
import type { MapInfo, ResourceType, ResourceClickEvent } from '@tuoyuan/img-map-container'

const mapRef = ref()
const mapId = ref('your-map-id')
const resourceTypes = ref<ResourceType[]>([])

function handleMapLoaded(mapInfo: MapInfo) {
  console.log('地图加载成功:', mapInfo.name)
}

function handleResourceTypesLoaded(types: ResourceType[]) {
  console.log('资源类型加载完成:', types)
  resourceTypes.value = types
}

function handleResourceClick(event: ResourceClickEvent) {
  console.log('点击了资源:', event.placement)
}

async function toggleType(type: ResourceType) {
  if (!mapRef.value) return
  
  const isLoaded = await mapRef.value.toggleResourceType(type.key)
  console.log(`${type.name} 现在${isLoaded ? '可见' : '隐藏'}`)
}

function isTypeLoaded(typeId: string): boolean {
  return mapRef.value?.isTypeLoaded(typeId) || false
}

function clearAll() {
  mapRef.value?.clearResources()
}
</script>

<style scoped>
.map-container {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.type-selector {
  position: absolute;
  top: 20px;
  left: 20px;
  background: white;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  z-index: 100;
  min-width: 200px;
}

.type-selector h3 {
  margin: 0 0 10px 0;
  font-size: 16px;
}

.type-checkbox {
  display: flex;
  align-items: center;
  padding: 8px 0;
  cursor: pointer;
  user-select: none;
}

.type-checkbox input {
  margin-right: 8px;
}

.clear-btn {
  width: 100%;
  margin-top: 10px;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: white;
  cursor: pointer;
}

.clear-btn:hover {
  background: #f5f5f5;
}
</style>

基础示例:单选资源类型

<template>
  <div class="map-container">
    <ImgMapContainer
      ref="mapRef"
      :map-id="mapId"
      @map-loaded="handleMapLoaded"
      @resource-types-loaded="handleResourceTypesLoaded"
      @resources-loaded="handleResourcesLoaded"
      @resource-click="handleResourceClick"
    />
    
    <!-- 资源类型选择器 -->
    <div class="type-selector">
      <h3>资源类型</h3>
      <button 
        v-for="type in resourceTypes" 
        :key="type.id"
        @click="loadType(type)"
        :class="{ active: currentTypeKey === type.key }"
      >
        {{ type.name }}
      </button>
      <button @click="clearAll">清空</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ImgMapContainer } from '@tuoyuan/img-map-container'
import type { MapInfo, ResourceType, ResourcePlacement, ResourceClickEvent } from '@tuoyuan/img-map-container'

const mapRef = ref()
const mapId = ref('your-map-id')
const resourceTypes = ref<ResourceType[]>([])
const currentTypeKey = ref('')

function handleMapLoaded(mapInfo: MapInfo) {
  console.log('地图加载成功:', mapInfo.name)
}

function handleResourceTypesLoaded(types: ResourceType[]) {
  console.log('资源类型加载完成:', types)
  resourceTypes.value = types
}

function handleResourcesLoaded(placements: ResourcePlacement[]) {
  console.log('资源加载完成,共', placements.length, '个')
}

function handleResourceClick(event: ResourceClickEvent) {
  console.log('点击了资源:', event.placement)
}

function loadType(type: ResourceType) {
  currentTypeKey.value = type.key
  mapRef.value?.loadResources(type.key)
}

function clearAll() {
  currentTypeKey.value = ''
  mapRef.value?.clearResources()
}
</script>

<style scoped>
.map-container {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.type-selector {
  position: absolute;
  top: 20px;
  left: 20px;
  background: white;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  z-index: 100;
}

.type-selector button {
  display: block;
  width: 100%;
  margin: 5px 0;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: white;
  cursor: pointer;
}

.type-selector button.active {
  background: #1890ff;
  color: white;
  border-color: #1890ff;
}
</style>

高级示例:资源详情弹窗 + 删除功能

<template>
  <div class="map-page">
    <ImgMapContainer
      ref="mapRef"
      :map-id="currentMapId"
      @resource-click="handleResourceClick"
      @map-loaded="handleMapLoaded"
      @resources-loaded="handleResourcesLoaded"
      @resource-types-loaded="handleResourceTypesLoaded"
    />
    
    <!-- 控制面板 -->
    <div class="control-panel">
      <button @click="clearResources" class="clear-btn">清空资源</button>
      
      <div v-if="resourceTypes.length > 0" class="resource-types">
        <div class="types-title">可用资源类型:</div>
        <button 
          v-for="type in resourceTypes" 
          :key="type.id" 
          @click="loadResourcesByType(type)"
          class="type-btn"
          :class="{ active: currentTypeKey === type.key }"
        >
          {{ type.name }}
        </button>
      </div>
      
      <!-- 缩放控制 -->
      <div class="zoom-controls">
        <button @click="zoomIn">放大</button>
        <button @click="zoomOut">缩小</button>
        <button @click="resetView">重置</button>
      </div>
    </div>
    
    <!-- 资源详情弹窗 -->
    <div v-if="selectedResource && selectedPlacement" class="modal" @click.self="closeModal">
      <div class="modal-content">
        <div class="modal-header">
          <h3>资源详情</h3>
          <button class="close" @click="closeModal">×</button>
        </div>
        <div class="modal-body">
          <div class="info-row">
            <span class="label">Placement ID:</span>
            <span class="value">{{ selectedPlacement.id }}</span>
          </div>
          <div class="info-row">
            <span class="label">名称:</span>
            <span class="value">{{ selectedResource.name }}</span>
          </div>
          <div class="info-row">
            <span class="label">几何类型:</span>
            <span class="value">{{ selectedPlacement.geometry_type }}</span>
          </div>
          <div class="info-row">
            <span class="label">坐标:</span>
            <span class="value">{{ formatCoordinates(selectedPlacement.geometry?.coordinates) }}</span>
          </div>
        </div>
        <div class="modal-footer">
          <button @click="deleteSelectedResource" class="delete-btn">删除此资源</button>
          <button @click="closeModal" class="cancel-btn">取消</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ImgMapContainer } from '@tuoyuan/img-map-container'
import type { MapInfo, ResourcePlacement, ResourceClickEvent, ResourceType } from '@tuoyuan/img-map-container'

const mapRef = ref()
const currentMapId = ref('your-map-id')
const selectedResource = ref<any>(null)
const selectedPlacement = ref<ResourcePlacement | null>(null)
const resourceTypes = ref<ResourceType[]>([])
const currentTypeKey = ref<string>('')

function handleMapLoaded(mapInfo: MapInfo) {
  console.log('地图加载成功:', mapInfo.name)
}

function handleResourcesLoaded(placements: ResourcePlacement[]) {
  console.log('资源加载完成,共', placements.length, '个')
}

function handleResourceTypesLoaded(types: ResourceType[]) {
  console.log('资源类型加载完成:', types)
  resourceTypes.value = types
}

function handleResourceClick(event: ResourceClickEvent) {
  selectedPlacement.value = event.placement
  selectedResource.value = {
    name: event.placement.label_override || 
          event.resource?.name || 
          '未命名',
    type: event.placement.geometry_type,
    id: event.placement.id
  }
}

function closeModal() {
  selectedResource.value = null
  selectedPlacement.value = null
}

function formatCoordinates(coordinates: any): string {
  if (!coordinates) return '-'
  if (Array.isArray(coordinates)) {
    if (typeof coordinates[0] === 'number') {
      return `[${coordinates[0]}, ${coordinates[1]}]`
    } else if (Array.isArray(coordinates[0])) {
      return `${coordinates.length} 个点`
    }
  }
  return JSON.stringify(coordinates)
}

function deleteSelectedResource() {
  if (!selectedPlacement.value || !mapRef.value) return

  const placementId = selectedPlacement.value.id
  const resourceName = selectedResource.value?.name || '未命名资源'

  if (!confirm(`确定要删除资源 "${resourceName}" 吗?\n(注意:仅从地图上移除,不会删除后端数据)`)) {
    return
  }

  const success = mapRef.value.deleteResource(placementId)
  
  if (success) {
    alert(`移除资源 "${resourceName}" 成功!`)
    closeModal()
  } else {
    alert(`移除资源 "${resourceName}" 失败!`)
  }
}

function loadResourcesByType(type: ResourceType) {
  if (!mapRef.value) return
  
  console.log('加载资源类型:', type.name, 'key:', type.key)
  currentTypeKey.value = type.key
  mapRef.value.loadResources(type.key)
}

function clearResources() {
  if (mapRef.value) {
    mapRef.value.clearResources()
    currentTypeKey.value = ''
  }
}

function zoomIn() {
  mapRef.value?.zoomIn()
}

function zoomOut() {
  mapRef.value?.zoomOut()
}

function resetView() {
  mapRef.value?.resetView()
}
</script>

<style scoped>
.map-page {
  width: 100%;
  height: 100%;
  position: relative;
}

.control-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 100;
  max-width: 300px;
}

.clear-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  background: white;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.resource-types {
  background: white;
  padding: 12px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.types-title {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 8px;
}

.type-btn {
  display: block;
  width: 100%;
  margin: 5px 0;
  padding: 10px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background: white;
  cursor: pointer;
  text-align: left;
}

.type-btn.active {
  background: #1890ff;
  color: white;
  border-color: #1890ff;
}

.zoom-controls {
  background: white;
  padding: 12px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  gap: 5px;
}

.zoom-controls button {
  flex: 1;
  padding: 8px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background: white;
  cursor: pointer;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-content {
  background: white;
  border-radius: 8px;
  width: 90%;
  max-width: 500px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #e0e0e0;
}

.close {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  font-size: 24px;
  cursor: pointer;
}

.modal-body {
  padding: 20px;
}

.info-row {
  display: flex;
  padding: 8px 0;
  border-bottom: 1px solid #f0f0f0;
}

.info-row .label {
  width: 120px;
  color: #666;
}

.info-row .value {
  flex: 1;
  color: #333;
}

.modal-footer {
  padding: 16px 20px;
  border-top: 1px solid #e0e0e0;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.delete-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background: #ff4d4f;
  color: white;
  cursor: pointer;
}

.cancel-btn {
  padding: 8px 16px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background: white;
  cursor: pointer;
}
</style>

常见问题

1. 样式没有生效?

组件的样式会自动加载,无需手动导入。如果样式没有生效,请检查:

  • 是否正确安装了插件
  • 是否在 main.ts 中调用了 app.use(ImgMapPlugin)

2. 图片显示不出来?

检查以下几点:

  • 确认 baseUrl 配置正确
  • 检查图片 URL 是否可访问
  • 查看浏览器控制台是否有跨域错误
  • 确认图片路径格式(相对路径会自动拼接 baseUrl

3. 资源类型列表为空?

可能的原因:

  • 后端数据库中没有资源类型数据
  • API 权限问题
  • 需要先在后台创建资源类型

打开浏览器控制台查看详细的 API 调用日志。

4. 资源坐标显示不正确?

确保:

  • 资源坐标基于图片的像素坐标系
  • 坐标原点在图片左上角
  • X 轴向右,Y 轴向下
  • 坐标值在图片尺寸范围内

5. 删除资源后刷新页面又出现了?

deleteResource 方法只从前端移除资源,不会删除后端数据。如果需要永久删除,需要调用后端的删除 API。

6. 如何自定义资源样式?

ResourcePlacementstyle_override 字段中设置:

{
  style_override: {
    color: '#ff0000',      // 颜色
    radius: 10,            // 点的半径
    width: 3,              // 线的宽度
    fillColor: '#00ff00',  // 面的填充色
    strokeColor: '#0000ff' // 边框颜色
  }
}

技术支持

如有问题,请提交 Issue 或联系技术支持。

更新日志

1.1.18

  • 🎉 新增 toggleResourceType 方法,支持切换资源类型的显示/隐藏
  • 🎉 新增 isTypeLoaded 方法,检查资源类型是否已加载
  • 🐛 修复图标 URL 重复添加 /gateway-api 前缀的问题
  • ✨ 支持多选资源类型展示(图层控制)
  • 📝 完善文档,添加多选和单选示例

1.1.17

  • 优化图标加载逻辑
  • 改进资源类型追踪机制

1.1.9

  • 添加详细的 API 调用日志
  • 优化资源类型加载逻辑
  • 完善文档说明

1.1.8

  • 资源类型管理移到组件内部
  • 自动加载资源类型列表
  • 添加 resource-types-loaded 事件

1.1.7

  • 修改删除资源逻辑为仅前端删除

1.1.6

  • 修复大尺寸地图显示问题
  • 优化图片缩放逻辑

1.1.5

  • 添加坐标验证
  • 过滤无效坐标的资源

1.1.4

  • 修改图片样式为 100% 宽高

1.1.3

  • 修复 CSS 样式自动加载问题

许可证

MIT