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

@wbiokr/arrow

v1.3.0

Published

Arrow editor for drawing arrows on web pages

Downloads

1,597

Readme

@wbiokr/arrow

箭头绘制编辑器 - 在网页上绘制可编辑的箭头

环境要求

  • Node.js >= 20.19.0 或 >= 22.12.0

安装

npm install @wbiokr/arrow

快速开始

HTML

<div id="container"></div>

CSS(可选)

#container {
  position: relative;
  width: 1000px;
  height: 600px;
  background: #fff;
  margin: 50px auto;
}

JavaScript

import { ArrowEditor } from '@wbiokr/arrow'

const editor = new ArrowEditor('#container')

使用方法

绘制箭头

  1. 点击空白处开始绘制
  2. 移动鼠标添加拐点
  3. 双击或按 Enter 完成绘制
  4. Esc 取消绘制

移动箭头

  1. 点击箭头选中
  2. 拖拽移动箭头

旋转箭头

  1. 点击箭头选中
  2. 拖拽顶部的橙色旋转手柄

缩放箭头

  1. 点击箭头选中
  2. 拖拽右下角的蓝色缩放手柄

删除箭头

  1. 点击箭头选中
  2. DeleteBackspace
  3. 或在工具条上点击"删除箭头"按钮

切换选中

点击其他箭头可快速切换选中状态。

取消选中

点击空白处或按 Esc

配置选项

const editor = new ArrowEditor('#container', {
  // 是否只在按 Ctrl 键时绘制(默认 false)
  isCtrl: false,

  // 是否阻止事件冒泡(默认 false)
  stopPropagation: false,

  // 是否阻止默认行为(默认 false)
  preventDefault: false,

  // 默认颜色(默认 '#2b8cff')
  defaultColor: '#2b8cff',

  // 默认粗细(默认 8)
  defaultStrokeWidth: 8,

  // 默认曲线率(默认 0)
  defaultCurveRate: 0,

  // 绘制完成回调
  onDrawEnd(data) {
    // data = { arrow: 当前箭头,arrows: 所有箭头数据 }
    console.log('绘制完成:', data)
  },

  // 删除回调
  onRemove(data) {
    // data = { arrow: 被删除的箭头,arrows: 剩余箭头数据 }
    console.log('删除:', data)
  },

  // 变更回调(颜色、粗细、曲线率、旋转、缩放)
  onChange(data) {
    // data = { type, arrow, value?, arrows }
    // type: 'color' | 'strokeWidth' | 'curveRate' | 'rotate' | 'scale'
    console.log('变更:', data)
  }
})

配置说明

| 选项 | 类型 | 默认值 | 说明 | |------|------|--------|------| | isCtrl | Boolean | false | 是否只在按 Ctrl 键时绘制 | | stopPropagation | Boolean | false | 是否阻止事件冒泡 | | preventDefault | Boolean | false | 是否阻止默认行为 | | defaultColor | String | '#2b8cff' | 默认箭头颜色 | | defaultStrokeWidth | Number | 8 | 默认箭头粗细 | | defaultCurveRate | Number | 0 | 默认曲线率(0=直线,1=最弯曲) | | defaultArrowLength | Number | 22 | 默认箭头长度(5-50) | | defaultArrowWidth | Number | 20 | 默认箭头宽度(5-50) | | onDrawEnd | Function | null | 绘制完成回调,接收 { arrow, arrows } | | onRemove | Function | null | 删除回调,接收 { arrow, arrows } | | onChange | Function | null | 变更回调,接收 { type, arrow, value?, arrows } |

API

实例化

const editor = new ArrowEditor(container, options)
  • container: CSS 选择器字符串或 DOM 元素
  • options: 配置对象(可选)

方法

getData()

获取所有箭头数据

const data = editor.getData()
// 返回:[{ points: [{x, y}, ...], curveRate, strokeWidth, arrowLength, arrowWidth, color }, ...]

setData(data)

设置箭头数据

editor.setData([
  {
    points: [{ x: 100, y: 100 }, { x: 200, y: 200 }],
    curveRate: 0.5,
    strokeWidth: 8,
    color: '#2b8cff'
  }
])

clear()

清空所有箭头

editor.clear()

destroy()

销毁编辑器,移除所有事件监听器和 DOM 元素

editor.destroy()

工具条

选中箭头后会弹出工具条,可以调整:

  • 颜色:点击颜色选择器
  • 粗细:拖动滑块(1-60px)
  • 曲线率:拖动滑块(0-1,0=直线,1=最弯曲)
  • 箭头长度:拖动滑块(5-50px,默认 22px)
  • 箭头宽度:拖动滑块(5-50px,默认 20px)
  • 缩放
    • X 缩放:仅水平方向缩放
    • Y 缩放:仅垂直方向缩放
  • 3D 旋转
    • X 轴旋转:上下拖动,模拟绕 X 轴旋转的透视效果
    • Y 轴旋转:左右拖动,模拟绕 Y 轴旋转的透视效果
  • 2.5D 挤出
    • 上挤出:向上方挤出立体阴影
    • 下挤出:向下方挤出立体阴影
    • 左挤出:向左方挤出立体阴影
    • 右挤出:向右方挤出立体阴影
    • 重置:恢复原始形状
  • 2.5D 透视
    • 上透视:上方缩小,下方放大(灭点在上方)
    • 下透视:下方缩小,上方放大(灭点在下方)
    • 左透视:左方缩小,右方放大(灭点在左方)
    • 右透视:右方缩小,左方放大(灭点在右方)
  • 倾斜
    • 左倾斜:向左倾斜
    • 右倾斜:向右倾斜
    • 上倾斜:向上倾斜
    • 下倾斜:向下倾斜
    • 重置:恢复原始形状

工具条可以拖拽到任意位置。

缩放手柄

选中箭头后,箭头周围会显示三个缩放手柄:

  • 右下角手柄:同时 X 和 Y 方向缩放(等比缩放)
  • 右边中间手柄:仅 X 方向缩放
  • 底部中间手柄:仅 Y 方向缩放

3D 旋转说明

  • X 轴旋转:绕 X 轴旋转,上下拖动鼠标控制角度,Y 坐标会根据旋转角度缩放(模拟透视效果)
  • Y 轴旋转:绕 Y 轴旋转,左右拖动鼠标控制角度,X 坐标会根据旋转角度缩放(模拟透视效果)
  • Z 轴旋转:现有的顶部橙色手柄,绕 Z 轴(垂直于屏幕)旋转

注:由于 SVG 是 2D 平面,X/Y 轴旋转使用余弦缩放模拟 3D 透视效果,旋转角度范围为 -90°到 90°。

2.5D 挤出效果

  • 上/下/左/右挤出:通过绘制多层灰色阴影,模拟箭头立体挤出的 2.5D 效果
  • 重置:清除挤出效果,恢复原始 2D 形状

2.5D 挤出效果是一种伪 3D 效果,通过沿指定方向绘制多层半透明阴影层来模拟立体深度感。

2.5D 透视效果

  • 上透视:灭点在上方,上方缩小下方放大,产生仰视效果
  • 下透视:灭点在下方,下方缩小上方放大,产生俯视效果
  • 左透视:灭点在左方,左方缩小右方放大
  • 右透视:灭点在右方,右方缩小左方放大

透视效果通过近大远小的原理,根据各点距离灭点的距离动态调整缩放比例,模拟真实的 3D 透视感。

倾斜效果

  • 左倾斜:向左方向倾斜(平行四边形效果)
  • 右倾斜:向右方向倾斜
  • 上倾斜:向上方向倾斜
  • 下倾斜:向下方向倾斜

倾斜效果通过错切变换(Skew Transform),根据点的位置偏移坐标,产生倾斜的视觉效果。

键盘快捷键

| 快捷键 | 功能 | |--------|------| | Enter | 完成绘制 | | Esc | 取消绘制 / 取消选中 | | Delete / Backspace | 删除选中的箭头 | | Space | 绘制中添加拐点 | | | 选中箭头时微调位置(1 像素) |

数据存储示例

// 保存数据
const editor = new ArrowEditor('#container', {
  onDrawEnd(data) {
    localStorage.setItem('arrows', JSON.stringify(data.arrows))
  },
  onChange(data) {
    localStorage.setItem('arrows', JSON.stringify(data.arrows))
  },
  onRemove(data) {
    localStorage.setItem('arrows', JSON.stringify(data.arrows))
  }
})

// 加载数据
editor.setData(JSON.parse(localStorage.getItem('arrows')) || [])

开发

npm install
npm run dev

打包

npm run build

License

MIT