效果图

npm地址https://www.npmjs.com/package/vue-image-crop-upload

git地址https://github.com/dai-siki/vue-image-crop-upload

样例地址https://dai-siki.github.io/vue-image-crop-upload/example/demo.html

代码实现

拖拽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
upload() {
let that = this,
{
lang,
imgFormat,
mime,
url,
params,
headers,
field,
ki,
createImgUrl,
withCredentials
} = this,
fmData = new FormData();
fmData.append(field, data2blob(createImgUrl, mime), field + '.' + imgFormat);

// 添加其他参数
if (typeof params == 'object' && params) {
Object.keys(params).forEach((k) => {
fmData.append(k, params[k]);
});
}

// 监听进度回调
const uploadProgress = function(event) {
if (event.lengthComputable) {
that.progress = 100 * Math.round(event.loaded) / event.total;
}
};

// 上传文件
that.reset();
that.loading = 1;
that.setStep(3);
new Promise(function(resolve, reject) {
let client = new XMLHttpRequest();
client.open('POST', url, true);
client.withCredentials = withCredentials;
client.onreadystatechange = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200 || this.status === 201) {
resolve(JSON.parse(this.responseText));
} else {
reject(this.status);
}
};
client.upload.addEventListener('progress', uploadProgress, false); //监听进度
// 设置header
if (typeof headers == 'object' && headers) {
Object.keys(headers).forEach((k) => {
client.setRequestHeader(k, headers[k]);
});
}
client.send(fmData);
}).then(
// 上传成功
function(resData) {
if (that.value) {
that.loading = 2;
that.$emit('crop-upload-success', resData, field, ki);
}
},
// 上传失败
function(sts) {
if (that.value) {
that.loading = 3;
that.hasError = true;
that.errorMsg = lang.fail;
that.$emit('crop-upload-fail', sts, field, ki);
}
});
}
}

点击波纹效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
export default function(e, arg_opts) {
var opts = Object.assign({
ele: e.target, // 波纹作用元素
type: 'hit', // hit点击位置扩散 center中心点扩展
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
}, arg_opts),
target = opts.ele;
if (target) {
var rect = target.getBoundingClientRect(),
ripple = target.querySelector('.e-ripple');
if (!ripple) {
ripple = document.createElement('span');
ripple.className = 'e-ripple';
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px';
target.appendChild(ripple);
} else {
ripple.className = 'e-ripple';
}
switch (opts.type) {
case 'center':
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px';
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px';
break;
default:
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px';
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px';
}
ripple.style.backgroundColor = opts.bgc;
ripple.className = 'e-ripple z-active';
return false;
}
};

base64转2进制

1
2
3
4
5
6
7
8
9
10
11
12
export default function(data, mime) {
data = data.split(',')[1];
data = window.atob(data);
var ia = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {
ia[i] = data.charCodeAt(i);
};
// canvas.toDataURL 返回的默认格式就是 image/png
return new Blob([ia], {
type: mime
});
};