vue 版本裁切工具, 包含预览功能
最终效果: https://qiuyaofan.github.io/vue-crop-demo/
源码地址: https://github.com/qiuyaofan/vue-crop
第一步: 先用 vue-cli 安装脚手架 (不会安装的看 vue-cli 官网 https://www.npmjs.com/package/vue-cli)
- // 初始化 vue-cli
- vue init webpack my-plugin
第二步: 创建文件
新建 src/views/validSlideDemo.vue,
src/components 里新建 VueCrop/index.js,VueCrop.vue,
在 routes/index.js 配置访问路由 (具体看 github 源码)
最终生成的文件结构如下图:
第三步: 注册组件
1. 引用所有插件: src/components/index.js
- // 导入插件入口文件
- import VueCrop from './VueCrop/index.js'
- const install = function (Vue, opts = {}) {
- /* 如果已安装就跳过 */
- if (install.installed) return
- // 注册插件
- Vue.component(VueCrop.name, VueCrop)
- }
- // 全局情况下注册插件
- if (typeof window !== 'undefined' && window.Vue) {
- install(window.Vue)
- }
- export {
- install,
- // 此处是为了兼容在 vue 内单独引入这个插件, 如果是 main.js 全局引入就可以去掉
- VueCrop
- }
2. 全局调用插件: src/main.js ( vue plugins 官方文档解说 install https://cn.vuejs.org/v2/guide/plugins.html )
- import Vue from 'vue'
- import App from './App'
- import router from './router'
- // 新加的: 导入入口文件
- import { install } from 'src/components/index.js'
- // 全局调用, 相当于调用 `MyPlugin.install(Vue)`
- Vue.use(install)
- Vue.config.productionTip = false
- /* eslint-disable no-new */
- new Vue({
- el: '#app',
- router,
- components: { App },
- template: '<App/>'
- })
3.VueCrop 入口文件调用 VueCrop.vue:src/components/VueCrop/index.js
- // 导入 vue
- import VueCrop from './VueCrop.vue'
- // vue.js 的插件应当有一个公开方法 install . 这个方法的第一个参数是 Vue 构造器
- VueCrop.install = function (Vue) {
- // 注册组件
- Vue.component(VueCrop.name, VueCrop)
- }
- export default VueCrop
小结: 我一开始一直有个误解, 以为 myPlugin.install 是 vue 的一个方法, 其实不是, 他只是我们构造 plugin 识的一个公开方法, 可以理解为原生 js 中的构造函数的方法:
- function MyPlugin(){
- console.info('构造函数')
- }
- MyPlugin.prototype.install=function(vue,options){
- console.info('构造器 vue:'+vue);
- }
而真正注册组件的是: Vue.component()
所以, vue 插件注册的过程是:
1. 调用 main.js 中:
- import { install } from 'src/components/index.js'
- vue.use(install)
2.index.js 添加 install 方法, 调用 Vue.component 注册组件
3. 组件内的 index.js 同所有组件的 index.js 一样
第四步: 设计开发自己的组件, 构建组件结构
在此之前, 可以先了解下组件的命名规范等, 可参考文章 掘金: Vue 前端开发规范, 其中第 2 点有详细讲解
首先, 确定自己的调用方式和需要暴露的参数
- <vue-crop
- :crop-url="cropUrl1"
- :ratio="ratio"
- :height="460"
- :width="460"
- :previewJson="previewJson1"
- class="c-crop--preview_right"
- @afterCrop="afterCrop"
- >
- >
其中,@afterCrop="afterCrop" 是裁切完成的回调函数, 其他是属性配置
在组件 src/components/VueCrop/VueCrop.vue 内, 可以用 this.$emit('afterCrop') 触发 demo 里的 afterCrop 事件
组件结构上, 主要分为: 裁切主要部分, 选框组件 (VueCropTool.vue), 裁切框宽度, 位置坐标等计算 (VueCropMove.js), 拖拽事件注册公共 js(components/utils/draggable.js)
draggable.js 是参照 element 里的, 修改了一部分, 源码如下
- export default function (element, options) {
- const moveFn = function (event) {
- if (options.drag) {
- options.drag(event)
- }
- }
- // mousedown fn
- const downFn = function (event) {
- if (options.start) {
- // 调用参数中 start 函数
- options.start(event)
- }
- }
- // mouseup fn
- const upFn = function (event) {
- document.removeEventListener('mousemove', moveFn)
- document.removeEventListener('mouseup', upFn)
- document.onselectstart = null
- document.ondragstart = null
- if (options.end) {
- // 调用参数中 end 函数
- options.end(event)
- }
- }
- // 绑定事件
- element.addEventListener('mousedown', event => {
- if (options.stop && options.stop(event, element) === false) {
- return false
- }
- document.onselectstart = function () {
- return false
- }
- document.ondragstart = function () {
- return false
- }
- document.addEventListener('mousedown', downFn)
- document.addEventListener('mousemove', moveFn)
- document.addEventListener('mouseup', upFn)
- })
- }
VueCropTool.vue 使用如下
- draggable(this.$el.querySelector('.c-crop--drap_screen'), {
- start: (event) => {
- this.startPos = [event.x, event.y]
- },
- drag: (event) => {
- this.handleDragLocation(event)
- },
- end: (event) => {
- this.handleDragLocation(event)
- }
- })
剩下的就是逻辑的事了, 今天就分享到这里啦~喜欢这个插件可以去 github star~ https://github.com/qiuyaofan/vue-crop
来源: https://juejin.im/post/5aead3aef265da0b91274741