# Jcrop - 图片裁剪插件

Jcrop 是一个强大的 jQuery 图片裁剪插件，支持实时预览、固定比例、动画效果等功能。

## 特性

- ✅ 实时裁剪预览
- ✅ 固定裁剪比例
- ✅ 动画效果
- ✅ 键盘支持
- ✅ 触摸设备支持
- ✅ 多实例支持

## 加载方式

```javascript
// 加载 CSS
Wind.css('jcrop');

// 加载 JS
Wind.use('jcrop', function() {
    // Jcrop 加载完成，可以使用了
});
```

## 基础用法

### 1. 基础裁剪

```html
<img src="image.jpg" id="target" />
```

```javascript
Wind.use('jcrop', function() {
    $('#target').Jcrop();
});
```

### 2. 固定比例裁剪（如头像 1:1）

```html
<img src="avatar.jpg" id="avatar" />
```

```javascript
Wind.use('jcrop', function() {
    $('#avatar').Jcrop({
        aspectRatio: 1,  // 1:1 比例
        onSelect: function(c) {
            // 获取裁剪坐标
            console.log('x: ' + c.x);
            console.log('y: ' + c.y);
            console.log('宽: ' + c.w);
            console.log('高: ' + c.h);
        }
    });
});
```

### 3. 头像上传裁剪完整示例

```html
<div class="avatar-upload">
    <input type="file" id="avatarInput" accept="image/*" />
    <div class="avatar-preview">
        <img src="" id="avatarImg" />
    </div>
    <button id="saveAvatar">保存头像</button>
</div>
```

```javascript
Wind.use('jcrop', 'ajaxfileupload', 'noty', function() {
    var jcropApi = null;
    var cropData = null;
    
    // 文件选择后上传并裁剪
    $('#avatarInput').on('change', function() {
        var file = this.files[0];
        if (!file) return;
        
        // 验证文件
        if (!file.type.match(/image\/(jpeg|png)/)) {
            noty({ text: '请上传 JPG 或 PNG 格式的图片', type: 'error' });
            return;
        }
        
        if (file.size > 2 * 1024 * 1024) {
            noty({ text: '图片大小不能超过 2MB', type: 'error' });
            return;
        }
        
        // 使用 imgReady 快速获取图片尺寸
        var url = URL.createObjectURL(file);
        imgReady(url, function() {
            $('#avatarImg').attr('src', url);
            
            // 销毁之前的裁剪实例
            if (jcropApi) {
                jcropApi.destroy();
            }
            
            // 初始化裁剪
            $('#avatarImg').Jcrop({
                aspectRatio: 1,           // 1:1 正方形
                trueSize: [this.width, this.height], // 真实尺寸
                setSelect: [0, 0, 100, 100], // 默认选区
                allowSelect: false,       // 不允许新建选区
                allowMove: true,          // 允许移动选区
                allowResize: true,        // 允许调整大小
                onSelect: function(c) {
                    cropData = c;         // 保存裁剪数据
                }
            }, function() {
                jcropApi = this;          // 保存 API 实例
            });
        });
    });
    
    // 保存裁剪后的头像
    $('#saveAvatar').on('click', function() {
        if (!cropData) {
            noty({ text: '请先选择裁剪区域', type: 'error' });
            return;
        }
        
        $.ajax({
            url: '/user/avatar/crop',
            type: 'POST',
            data: {
                x: cropData.x,
                y: cropData.y,
                w: cropData.w,
                h: cropData.h
            },
            success: function(res) {
                if (res.code == 1) {
                    noty({ text: '头像保存成功', type: 'success' });
                }
            }
        });
    });
});
```

## 配置选项

```javascript
Wind.use('jcrop', function() {
    $('#target').Jcrop({
        // 是否允许新建选区
        allowSelect: true,
        
        // 是否允许移动选区
        allowMove: true,
        
        // 是否允许调整选区大小
        allowResize: true,
        
        // 是否允许调整选区大小（旧版本）
        canResize: true,
        
        // 是否允许拖动选区（旧版本）
        canDrag: true,
        
        // 裁剪比例（宽度/高度）
        // 1 = 正方形, 16/9 = 16:9, 4/3 = 4:3
        aspectRatio: 0,
        
        // 设置初始选区 [x, y, x2, y2]
        setSelect: null,
        
        // 最小选区尺寸 [width, height]
        minSize: [0, 0],
        
        // 最大选区尺寸 [width, height]
        maxSize: [0, 0],
        
        // 创建动画效果
        bgFade: false,
        
        // 背景颜色
        bgColor: 'black',
        
        // 背景透明度 (0-1)
        bgOpacity: 0.6,
        
        // 图片真实尺寸 [width, height]
        // 用于缩放图片时保持裁剪坐标正确
        trueSize: null,
        
        // 选区边框颜色
        borderOpacity: 0.4,
        
        // 选区手柄大小
        handleOpacity: 0.5,
        
        // 选区手柄大小
        handleSize: 9,
        
        // 动画持续时间（毫秒）
        fadeTime: 400,
        
        // 键盘支持
        keySupport: true,
        
        // 选区创建时的回调
        onSelect: null,
        
        // 选区变化时的回调
        onChange: null,
        
        // 选区释放时的回调
        onRelease: null,
        
        // 插件加载完成时的回调
        onDblClick: null
    });
});
```

## 回调函数参数

```javascript
Wind.use('jcrop', function() {
    $('#target').Jcrop({
        onSelect: function(c) {
            // c 包含裁剪区域的坐标和尺寸
            console.log(c.x);   // 左上角 x 坐标
            console.log(c.y);   // 左上角 y 坐标
            console.log(c.x2);  // 右下角 x 坐标
            console.log(c.y2);  // 右下角 y 坐标
            console.log(c.w);   // 宽度
            console.log(c.h);   // 高度
        },
        onChange: function(c) {
            // 选区变化时实时触发
            updatePreview(c);
        },
        onRelease: function() {
            // 选区释放时触发
            console.log('选区已释放');
        }
    });
});
```

## 方法

```javascript
Wind.use('jcrop', function() {
    var jcropApi = null;
    
    $('#target').Jcrop({
        aspectRatio: 1
    }, function() {
        jcropApi = this;  // 获取 API 实例
    });
    
    // 设置选区
    jcropApi.setSelect([0, 0, 100, 100]);
    
    // 动画到指定选区
    jcropApi.animateTo([100, 100, 200, 200]);
    
    // 获取当前选区
    var coords = jcropApi.tellSelect();
    console.log(coords);
    
    // 获取当前选区（缩放后的）
    var scaledCoords = jcropApi.tellScaled();
    
    // 禁用裁剪
    jcropApi.disable();
    
    // 启用裁剪
    jcropApi.enable();
    
    // 销毁实例
    jcropApi.destroy();
    
    // 设置选项
    jcropApi.setOptions({
        aspectRatio: 16 / 9
    });
    
    // 获取图片尺寸
    var bounds = jcropApi.getBounds();
    console.log('宽: ' + bounds[0] + ', 高: ' + bounds[1]);
    
    // 获取图片容器
    var container = jcropApi.getWidgetSize();
    
    // 获取图片缩放比例
    var scale = jcropApi.getScaleFactor();
});
```

## 实时预览

```html
<img src="image.jpg" id="target" />

<div class="preview-container">
    <img src="image.jpg" id="preview" />
</div>
```

```css
.preview-container {
    width: 100px;
    height: 100px;
    overflow: hidden;
}

#preview {
    max-width: none;
}
```

```javascript
Wind.use('jcrop', function() {
    var $preview = $('#preview');
    var $target = $('#target');
    
    $target.Jcrop({
        onChange: updatePreview,
        onSelect: updatePreview,
        aspectRatio: 1
    });
    
    function updatePreview(c) {
        if (parseInt(c.w) > 0) {
            var rx = 100 / c.w;  // 预览容器宽度 / 选区宽度
            var ry = 100 / c.h;  // 预览容器高度 / 选区高度
            
            $preview.css({
                width: Math.round(rx * $target.width()) + 'px',
                height: Math.round(ry * $target.height()) + 'px',
                marginLeft: '-' + Math.round(rx * c.x) + 'px',
                marginTop: '-' + Math.round(ry * c.y) + 'px'
            });
        }
    }
});
```

## 实际应用场景

### 1. 文章封面裁剪

```javascript
Wind.use('jcrop', function() {
    $('#coverImg').Jcrop({
        aspectRatio: 16 / 9,  // 16:9 封面比例
        setSelect: [0, 0, 640, 360],
        minSize: [320, 180],
        onSelect: function(c) {
            $('#cropX').val(c.x);
            $('#cropY').val(c.y);
            $('#cropW').val(c.w);
            $('#cropH').val(c.h);
        }
    });
});
```

### 2. 商品图片裁剪

```javascript
Wind.use('jcrop', function() {
    $('#productImg').Jcrop({
        aspectRatio: 4 / 3,  // 4:3 商品图比例
        setSelect: [0, 0, 400, 300],
        bgFade: true,
        bgOpacity: 0.4,
        onChange: function(c) {
            // 实时更新预览
            updateProductPreview(c);
        }
    });
});
```

### 3. 多尺寸裁剪

```javascript
Wind.use('jcrop', function() {
    var jcropApi = null;
    
    // 切换裁剪比例
    $('#ratio1').on('click', function() {
        jcropApi.setOptions({
            aspectRatio: 1  // 1:1
        });
    });
    
    $('#ratio2').on('click', function() {
        jcropApi.setOptions({
            aspectRatio: 16 / 9  // 16:9
        });
    });
    
    $('#ratio3').on('click', function() {
        jcropApi.setOptions({
            aspectRatio: 4 / 3  // 4:3
        });
    });
    
    $('#target').Jcrop({
        aspectRatio: 1
    }, function() {
        jcropApi = this;
    });
});
```

## 常见问题

### 1. 图片加载后裁剪区域不正确

```javascript
// 确保图片完全加载后再初始化 Jcrop
var img = new Image();
img.onload = function() {
    $('#target').Jcrop({
        trueSize: [this.width, this.height]
    });
};
img.src = 'image.jpg';
```

### 2. 动态更换图片

```javascript
// 销毁旧实例，重新初始化
if (jcropApi) {
    jcropApi.destroy();
}

$('#target').attr('src', 'new-image.jpg').Jcrop({
    aspectRatio: 1
}, function() {
    jcropApi = this;
});
```

### 3. 响应式裁剪

```javascript
$(window).on('resize', function() {
    if (jcropApi) {
        // 重新计算尺寸
        var bounds = jcropApi.getBounds();
        jcropApi.setOptions({
            trueSize: bounds
        });
    }
});
```

## 浏览器兼容性

- Chrome 所有版本
- Firefox 所有版本
- Safari 所有版本
- Edge 所有版本
- IE 8+

## 更多文档

- 官方文档: https://github.com/tapmodo/Jcrop
- 示例: https://jcrop.org/
