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

v-avatar-cropper

v1.0.0

Published

Support cutting of avatars of PC and mobile phones.

Readme

V Avatar Cropper

演示动图

一个支持 PC 端和移动端的 Vue 3 头像裁剪组件,提供直观的拖拽、缩放和裁剪功能。

✨ 特性

  • 🖱️ 直观操作 - 支持鼠标拖拽和触摸手势
  • 🔍 灵活缩放 - 双指缩放和滑块缩放
  • 📱 响应式设计 - 自适应不同屏幕尺寸
  • 🎨 现代 UI - 简洁美观的用户界面
  • 📦 轻量级 - 无外部依赖,体积小巧
  • 🔧 易于集成 - 简单的 API 设计

📦 安装

npm install v-avatar-cropper --save

🚀 快速开始

全局注册

import {createApp} from 'vue'
import avatar from 'v-avatar-cropper'
import App from './App.vue'

const app = createApp(App)
app.use(avatar)
app.mount('#app')

局部引入

import VAvatarCropper from 'v-avatar-cropper'

export default {
  components: {
    VAvatarCropper,
  },
}

基础用法

<template>
  <div>
    <!-- 文件选择 -->
    <input type="file" @change="handleFileChange" accept="image/*" />

    <!-- 头像裁剪组件 -->
    <v-avatar-cropper v-if="selectedFile" :file="selectedFile" @cancel="handleCancel" @done="handleDone" />
  </div>
</template>

<script setup>
import {ref} from 'vue'

const selectedFile = ref(null)

function handleFileChange(event) {
  selectedFile.value = event.target.files[0]
}

function handleCancel() {
  selectedFile.value = null
}

function handleDone(result) {
  console.log('裁剪完成:', result)
  // result.base64 - base64格式图片
  // result.img - Blob格式图片
  // result.url - Blob URL地址

  selectedFile.value = null
}
</script>

📖 API 文档

Props

| 参数 | 类型 | 默认值 | 说明 | | ---- | -------------- | ------ | ---------------------------------- | | file | File | String | null | 要裁剪的图片文件或图片 URL | | edit | Boolean | true | 是否显示编辑界面(操作按钮和滑块) |

Events

| 事件名 | 参数 | 说明 | | ------ | -------------- | ---------------------- | | cancel | - | 用户点击取消按钮时触发 | | done | result: Object | 用户确认裁剪时触发 | | touch | - | 用户触摸图片时触发 |

Done 事件返回值

{
  base64: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...', // base64格式图片
  img: Blob,                                                    // Blob格式图片对象
  url: 'blob:http://localhost:3000/xxx-xxx-xxx'               // Blob URL地址
}

🎮 使用示例

完整示例

<template>
  <div class="avatar-demo">
    <!-- 上传区域 -->
    <div v-if="!currentFile" class="upload-area">
      <label for="file-input" class="upload-button"> 选择头像图片 </label>
      <input id="file-input" type="file" @change="selectFile" accept="image/*" style="display: none;" />
    </div>

    <!-- 裁剪组件 -->
    <v-avatar-cropper v-if="currentFile" :file="currentFile" @cancel="cancelCrop" @done="completeCrop" @touch="onImageTouch" />

    <!-- 结果展示 -->
    <div v-if="croppedResult" class="result-area">
      <h3>裁剪结果</h3>
      <img :src="croppedResult.url" alt="裁剪后的头像" class="result-image" />
      <div class="result-actions">
        <button @click="downloadImage">下载图片</button>
        <button @click="resetDemo">重新选择</button>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref} from 'vue'

const currentFile = ref(null)
const croppedResult = ref(null)

// 选择文件
function selectFile(event) {
  const file = event.target.files[0]
  if (file) {
    currentFile.value = file
  }
}

// 取消裁剪
function cancelCrop() {
  currentFile.value = null
}

// 完成裁剪
function completeCrop(result) {
  croppedResult.value = result
  currentFile.value = null

  // 可以在这里上传到服务器
  // uploadToServer(result.img)
}

// 图片触摸事件
function onImageTouch() {
  console.log('用户触摸了图片')
}

// 下载图片
function downloadImage() {
  if (croppedResult.value) {
    const link = document.createElement('a')
    link.download = 'avatar.jpg'
    link.href = croppedResult.value.url
    link.click()
  }
}

// 重置演示
function resetDemo() {
  croppedResult.value = null
  // 清空文件输入
  const input = document.getElementById('file-input')
  if (input) input.value = ''
}
</script>

<style scoped>
.avatar-demo {
  max-width: 500px;
  margin: 0 auto;
  padding: 20px;
}

.upload-area {
  text-align: center;
  padding: 40px;
  border: 2px dashed #ddd;
  border-radius: 8px;
}

.upload-button {
  display: inline-block;
  padding: 12px 24px;
  background: #007bff;
  color: white;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.3s;
}

.upload-button:hover {
  background: #0056b3;
}

.result-area {
  text-align: center;
  margin-top: 20px;
}

.result-image {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #007bff;
}

.result-actions {
  margin-top: 15px;
}

.result-actions button {
  margin: 0 10px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>

仅预览模式

<template>
  <v-avatar-cropper :file="imageUrl" :edit="false" />
</template>

<script setup>
const imageUrl = 'https://example.com/avatar.jpg'
</script>

🎯 操作指南

PC 端操作

  • 拖拽移动: 鼠标按住图片拖拽
  • 缩放调节: 使用底部滑块调节缩放比例
  • 确认裁剪: 点击"确认"按钮完成裁剪
  • 取消操作: 点击"取消"按钮退出裁剪

移动端操作

  • 单指拖拽: 单指触摸拖拽移动图片位置
  • 双指缩放: 双指捏合/展开调节图片大小
  • 滑块缩放: 使用底部滑块精确调节缩放
  • 触摸确认: 点击"确认"按钮完成裁剪

⚙️ 技术特性

核心功能

  • 智能适配: 自动适配图片尺寸和屏幕大小
  • 边界检测: 防止图片移出裁剪区域
  • 平滑动画: 流畅的交互动画效果
  • 内存管理: 自动清理 Blob URL,防止内存泄漏

兼容性

  • Vue 版本: Vue 3.x
  • 浏览器: 现代浏览器 (Chrome, Firefox, Safari, Edge)
  • 移动端: iOS Safari, Android Chrome
  • 触摸支持: 完整的触摸手势支持

🔧 开发指南

本地开发

# 克隆项目
git clone https://github.com/varjay/avatar-crop.git

# 安装依赖
cd avatar-crop
npm install

# 启动开发服务器
npm run dev

# 构建项目
npm run build

# 代码检查
npm run lint

项目结构

avatar-crop/
├── lib/                    # 组件源码
│   ├── index.js           # 入口文件
│   └── components/
│       └── avatar.vue     # 主组件
├── src/                   # 示例代码
│   ├── App.vue           # 示例应用
│   └── main.js           # 入口文件
├── public/               # 静态资源
└── package.json          # 项目配置

🤝 贡献指南

欢迎提交 Issue 和 Pull Request 来帮助改进这个项目!

提交 Issue

  • 详细描述问题和复现步骤
  • 提供浏览器和设备信息
  • 如果可能,请提供最小复现示例

提交 PR

  • Fork 项目并创建特性分支
  • 确保代码通过 ESLint 检查
  • 添加必要的测试用例
  • 更新相关文档

📄 许可证

ISC License

👨‍💻 作者

virjay - GitHub


如果这个项目对你有帮助,请给个 ⭐️ 支持一下!