npm.io
3.1.6 • Published 2 weeks agoCLI

vue3-sketch-ruler

Licence
MIT
Version
3.1.6
Deps
2
Size
347 kB
Vulns
0
Weekly
0
Stars
299

vue3-sketch-ruler

是一个基于 Vue 3 + TypeScript 的标尺组件库,适用于低代码平台、大屏可视化、做图工具等场景,提供类似 Photoshop 的缩放与标尺辅助线体验。

build status

Cloud Studio Template

Features

  • Vue 3 Composition API / <script setup>
  • 基于 TypeScript,类型完整
  • 内置 TransformEngine 变换引擎,零外部依赖
  • 多种缩放模式:鼠标中心、视口中心、内容中心
  • 可配置参考线(拖拽创建、吸附、锁定)
  • 内置 Minimap 缩略图导航(支持拖拽视口、点击跳转)
  • 插件系统(生命周期钩子 + 自定义渲染器)
  • 动画支持:ease-out / damped / exponential / direct
  • 平台与业务代码通过插槽分离,专注业务即可

Demo

案例浏览: https://kakajun.github.io/vue3-sketch-ruler image

CodePen 示例

安装

npm install --save vue3-sketch-ruler

# 或
yarn add vue3-sketch-ruler

# 或
pnpm add vue3-sketch-ruler

引入方式

ESM
import { SketchRuler, Minimap } from 'vue3-sketch-ruler'
import type { SketchRulerProps, SketchRulerPlugin } from 'vue3-sketch-ruler'
import 'vue3-sketch-ruler/lib/style.css'
CDN (IIFE)

通过 <script> 标签直接引入,挂载到全局变量 SketchRuler

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue3-sketch-ruler/lib/index.iife.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vue3-sketch-ruler/lib/style.css" />

<script>
  const { SketchRuler: SketchRulerComp } = SketchRuler

  Vue.createApp({
    components: { SketchRuler: SketchRulerComp }
  }).mount('#app')
</script>
CDN (UMD)

UMD 格式兼容 CommonJS、AMD 和浏览器全局变量三种环境:

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue3-sketch-ruler/lib/index.umd.cjs"></script>
<link rel="stylesheet" href="https://unpkg.com/vue3-sketch-ruler/lib/style.css" />

<script>
  const { SketchRuler: SketchRulerComp } = SketchRuler

  Vue.createApp({
    components: { SketchRuler: SketchRulerComp }
  }).mount('#app')
</script>

使用

基础用法
<template>
  <div class="wrapper" :style="{ width: width + 'px', height: height + 'px' }">
    <SketchRuler
      ref="sketchRef"
      v-model:scale="state.scale"
      :width="width"
      :height="height"
      :canvas-width="canvasWidth"
      :canvas-height="canvasHeight"
      :thick="state.thick"
      :lines="state.lines"
      :is-show-refer-line="state.isShowReferLine"
      :enable-animation="true"
      animation-mode="ease-out"
      @zoomchange="handleZoomChange"
      @update:lines="handleLinesChange"
    >
      <template #default>
        <div data-type="page" :style="canvasStyle">
          <img :src="bgImg" style="width:100%;height:100%" />
        </div>
      </template>

      <template #toolbar="{ tools, state }">
        <div class="btns">
          <button @click="tools.reset">还原</button>
          <button @click="tools.zoomIn">放大</button>
          <button @click="tools.zoomOut">缩小</button>
          <button @click="tools.zoomToPreset(1)">100%</button>
          <span>{{ (state.scale * 100).toFixed(0) }}%</span>
        </div>
      </template>
    </SketchRuler>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import { SketchRuler } from 'vue3-sketch-ruler'
import 'vue3-sketch-ruler/lib/style.css'

const sketchRef = ref()
const width = 1470
const height = 700
const canvasWidth = 1000
const canvasHeight = 500

const state = reactive({
  scale: 1,
  thick: 20,
  isShowReferLine: true,
  lines: { h: [0, 250], v: [0, 500] }
})

const canvasStyle = {
  width: canvasWidth + 'px',
  height: canvasHeight + 'px'
}

const handleZoomChange = (detail: { scale: number; x: number; y: number }) => {
  console.log('zoomchange', detail)
}

const handleLinesChange = (lines: { h: number[]; v: number[] }) => {
  console.log('lines changed', lines)
}
</script>
配合 Minimap
<template>
  <SketchRuler ref="sketchRef" v-model:scale="state.scale" ...>
    <template #default>...</template>
  </SketchRuler>

  <Minimap
    :content-width="canvasWidth"
    :content-height="canvasHeight"
    :viewport-x="viewportOffset.x"
    :viewport-y="viewportOffset.y"
    :viewport-width="width"
    :viewport-height="height"
    :scale="state.scale"
    :width="200"
    :height="150"
    @navigate="handleNavigate"
  />
</template>

<script setup>
import { SketchRuler, Minimap } from 'vue3-sketch-ruler'

const sketchRef = ref()
const viewportOffset = reactive({ x: 0, y: 0 })

const handleZoomChange = (detail) => {
  viewportOffset.x = detail.x
  viewportOffset.y = detail.y
}

const handleNavigate = (x, y) => {
  sketchRef.value?.setTransform({ x, y })
}
</script>
插件系统
import type { SketchRulerPlugin } from 'vue3-sketch-ruler'

const plugins: SketchRulerPlugin[] = [
  {
    name: 'demo-logger',
    onLineCreate: (ctx) => console.log('line created', ctx.line.id),
    onLineDelete: (ctx) => console.log('line deleted', ctx.line.id)
  }
]

API

Props
属性 描述 类型 默认值
width 容器宽度 number 1400
height 容器高度 number 800
canvasWidth 画布宽度 number 700
canvasHeight 画布高度 number 700
thick 标尺厚度 number 16
scale 缩放值(支持 v-model:scale number 1
showRuler 是否显示标尺 boolean true
isShowReferLine 是否显示参考线 boolean true
lines 初始化参考线 { h: number[]; v: number[] } { h: [], v: [] }
palette 标尺样式配置 Partial<RulerPalette> {}
shadow 阴影高亮区域 { x, y, width, height } { x:0, y:0, width:0, height:0 }
zoomMode 缩放原点模式 'pointer' | 'viewport-center' | 'content-center' 'pointer'
zoomStep 缩放步长 number 0.25
minZoom 最小缩放 number 0.1
maxZoom 最大缩放 number 10
enableAnimation 是否启用动画 boolean false
animationMode 动画模式 'direct' | 'ease-out' | 'damped' | 'exponential' 'ease-out'
autoCenter 初始化自动居中 boolean true
paddingRatio 自动居中边距比(0~0.5 number 0.2
initialOffset 初始偏移(autoCenter=false 时生效) { x: number; y: number } { x:0, y:0 }
snapThreshold 吸附阈值 number 5
lockLine 是否锁定参考线 boolean false
selfHandle 自行处理输入事件 boolean false
showMinorTicks 是否显示次刻度线 boolean false
eyeIcon 左上角眼睛图标 base64 string 内置图标
closeEyeIcon 左上角闭眼图标 base64 string 内置图标
deleteLabel 参考线拖出画布时的删除提示 string '放开删除'
plugins 插件列表 SketchRulerPlugin[] []
Events
事件 描述 回调参数
update:scale 缩放值双向绑定 number
update:offset 偏移值双向绑定 { x: number; y: number }
zoomchange 缩放/平移变化 { scale, x, y }
update:lines 参考线变化 { h: number[]; v: number[] }
update:lockLine 参考线锁定状态变化 boolean
onCornerClick 左上角按钮点击 boolean(参考线显示状态)
Slots
插槽名 描述 作用域参数
default 画布内容(必须用 <template #default> 包裹
toolbar 右下角工具栏 { tools: { reset, zoomIn, zoomOut, zoomToPreset, setZoomMode, toggleReferLine }, state: { scale, offset, zoomMode, showReferLine } }
Expose

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

方法 描述
setTransform({ x?, y?, scale? }) 设置变换状态
zoomIn() 放大
zoomOut() 缩小
reset() 重置到初始状态
zoomToPreset(scale) 缩放到预设比例
setZoomMode(mode) 设置缩放模式
engine TransformEngine 实例
guideLines 当前参考线数组
cursorClass 当前光标类名
Palette
属性 描述 默认值
bgColor 画布背景 #f6f7f9
tickColor 刻度颜色 #BABBBC
labelColor 刻度标签颜色 #7D8694
guideLineColor 参考线颜色 #51d6a9
guideLineLockedColor 锁定参考线颜色 #d4d7dc
hoverBg 标签背景色 transparent
hoverColor 标签文字色 #000
borderColor 尺子边框颜色 #eeeeef
shadowColor 阴影高亮色 #e9f7fe
guideLineStyle 参考线样式 'dashed'
guideLineWidth 参考线宽度 1
labelEnabled 是否显示标签 true

Minimap API

属性 描述 类型 默认值
contentWidth 内容宽度 number
contentHeight 内容高度 number
viewportX 视口 X 偏移 number
viewportY 视口 Y 偏移 number
viewportWidth 视口宽度 number
viewportHeight 视口高度 number
scale 缩放比例 number
width 缩略图宽度 number 200
height 缩略图高度 number 150
事件 描述 回调参数
navigate 导航到指定位置 (x: number, y: number)
dragstart 开始拖拽
dragend 结束拖拽

2.x → 3.x 迁移指南

v3.x 是架构重构版本,内置 TransformEngine 替代了外部 simple-panzoom 依赖,并引入了 Minimap、插件系统、动画系统等全新能力。以下是核心差异与迁移要点:

主要 Breaking Changes
变更项 2.x 写法 3.x 写法 说明
组件名 <SketchRule> / <sketch-rule> <SketchRuler> 统一为 PascalCase 完整拼写
导入方式 import SketchRule from 'vue3-sketch-ruler' import { SketchRuler } from 'vue3-sketch-ruler' 改为命名导出,同时仍保留默认导出兼容
工具栏插槽 #btn="{ reset, zoomIn, zoomOut }" #toolbar="{ tools, state }" tools 包含 resetzoomInzoomOutzoomToPresetsetZoomModetoggleReferLinestate 包含 scaleoffsetzoomModeshowReferLine
缩放事件 @zoomStart v-model:scale / @update:scale 支持双向绑定,无需手动监听缩放开始
参考线事件 @handleLine @update:lines 统一为 update: 风格事件
偏移事件 @update:offset / @zoomchange 3.x 新增,返回 { scale, x, y }
锁定事件 v-model:lockLine / @update:lockLine 3.x 新增双向绑定
缩放控制 panzoomOption zoomModezoomStepminZoommaxZoom 移除 panzoomOption,改为内置引擎直接配置
动画系统 enableAnimationanimationMode 3.x 新增,支持 ease-outdampedexponentialdirect
自动居中 依赖 panzoom 的 startX/startY autoCenterpaddingRatioinitialOffset autoCentertrue 时按 paddingRatio 留白后自动居中
阴影文字 showShadowText 移除 3.x 已移除该属性
palette 属性 lineTypelineColorlongfgColorfontColor guideLineStyleguideLineColortickColorlabelColor 命名规范化
Expose panzoomInstance engine(TransformEngine) 直接暴露内置引擎实例
Expose 方法 zoomIn()zoomOut()reset() 同上,并新增 setTransform()zoomToPreset()setZoomMode() 方法更丰富
外部依赖 simple-panzoom 零外部 panzoom 依赖 需从项目中移除 simple-panzoom
快速迁移示例

2.x 代码:

<template>
  <sketch-rule
    ref="sketchruleRef"
    v-model:scale="state.scale"
    :panzoomOption="panzoomOption"
    :palette="{ lineType: 'dashed', lineColor: '#51d6a9' }"
    @handleLine="handleLinesChange"
  >
    <template #default>...</template>
    <template #btn="{ reset, zoomIn, zoomOut }">
      <button @click="reset">还原</button>
      <button @click="zoomIn">放大</button>
      <button @click="zoomOut">缩小</button>
    </template>
  </sketch-rule>
</template>

<script setup>
import SketchRule from 'vue3-sketch-ruler'
import { simplePanzoom } from 'simple-panzoom' // 需移除
</script>

3.x 代码:

<template>
  <SketchRuler
    ref="sketchRef"
    v-model:scale="state.scale"
    v-model:offset="state.offset"
    :zoom-mode="'pointer'"
    :enable-animation="true"
    animation-mode="ease-out"
    :palette="{ guideLineStyle: 'dashed', guideLineColor: '#51d6a9' }"
    @update:lines="handleLinesChange"
    @zoomchange="handleZoomChange"
  >
    <template #default>...</template>
    <template #toolbar="{ tools }">
      <button @click="tools.reset">还原</button>
      <button @click="tools.zoomIn">放大</button>
      <button @click="tools.zoomOut">缩小</button>
      <button @click="tools.zoomToPreset(1)">100%</button>
      <span>{{ (tools.state.scale * 100).toFixed(0) }}%</span>
    </template>
  </SketchRuler>
</template>

<script setup>
import { SketchRuler } from 'vue3-sketch-ruler'
</script>
自动化迁移脚本

项目提供了官方迁移脚本,可自动处理大部分替换:

npx vue3-sketch-ruler-migrate <path>

脚本会自动处理:

  • 组件名 SketchRuleSketchRuler
  • 插槽 #btn#toolbar
  • 事件 zoomStartupdate:scalehandleLineupdate:lines
  • 检测 simple-panzoomuseLine 等需手动移除的依赖并发出警告

脚本仅为辅助工具,执行后请务必 review 变更并运行测试。

新增能力速览
  • Minimap 缩略图:独立组件,支持拖拽视口与点击跳转
  • 插件系统:通过 plugins 属性注入生命周期钩子
  • 多画布管理器CanvasManager + BUILTIN_TEMPLATES
  • 吸附引擎snapThreshold 配置参考线吸附阈值
  • 动画引擎enableAnimation + animationMode 实现平滑缩放/平移
  • 纯原生零依赖:核心引擎 @sketch-ruler/core 纯原生实现,无需 panzoom 等第三方库

变更记录

  • v3.x 内置 TransformEngine 替代外部 panzoom,新增 Minimap、插件系统、多画布管理器、吸附引擎、动画系统
  • v2.4.x 多实例支持
  • v2.3.x 引用简化版 simple-panzoom,提升性能,更新全部依赖

Who is using this?

avue大屏可视化工具 image

GoView 高效拖拽式低代码数据可视化开发平台

open a PR to add your library ;)

QQ 技术交流群:

vue3-sketch-ruler

贡献者

最后

这是个开源业余做的功能,欢迎加强该插件的小伙伴加入。如果 vue3-sketch-ruler 对您有帮助,请给个 star,您的鼓励是我最大的动力。

Fork me on Gitee

引用

vue标尺组件 vue-sketch-ruler

Keywords