因项目需求,写了一个不用组件的js裁剪图片,整理了一个例子。img标签会出现问题,请将图片转化为代码
<template>
<div class="infomation-manage">
<div v-drag>
<div class="header-item-content">
<span class="img-span">
<canvas id="picture" width="317px" height="330px" class="canvas-ho"></canvas>
<canvas id="picture2" width="222px" height="231px" class="canvas-ho"></canvas>
<i class="el-icon-ts-add add-icon" ref="addimg" v-if="!canCut" @click="toUpload"></i>
</span>
<input type="file" ref="uploadFile" style="display:none" accept="image/*" @change="upload"/>
<div class="options">
<li @click="showCut" v-show="canCut">裁剪图片</li>
<!-- <li>更换头像</li> -->
</div>
</div>
<div style="margin-left:48px;color: #425B77;font-size: 12px;"></div>
<div class="mongolia" ref="monogolia" style="display:none;">
<div class="overlay"></div>
<div class="allimg" id="allimg">
<div>
<div class="mainBox">
<div class="left-up minBox left-up"></div>
<div class="up minBox up"></div>
<div class="right-up minBox right-up"></div>
<div class="left minBox left"></div>
<div class="right minBox right"></div>
<div class="left-down minBox left-down"></div>
<div class="down minBox down"></div>
<div class="right-down minBox right-down"></div>
</div>
</div>
<div>
<button id="cancel">取消</button>
<button type="info" id="comfirm">确定</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Test',
directives:{
drag(el, update){
const defaultImg = el.querySelector('.img-span').querySelector('img')
//定义该元素的 top left width height
let x, y, w, h;
//鼠标的起始和结束坐标
let cx_start, cy_start, cx_end, cy_end;
//获取要裁剪的图片
let imgEl = el.lastElementChild.querySelector('#allimg').firstElementChild.firstElementChild;
//获取选择框
let mainEl = el.lastElementChild.querySelector('#allimg').firstElementChild.lastElementChild;
// console.log(mainEl,'main');
//获取默认的canvas画布
let cavsEl = document.querySelector('.infomation-manage').querySelector('#picture2');//默认用原图的画图大小
// console.log(cavsEl,'canvas');
//获取确定按钮
let comfirmBtn = el.lastElementChild.querySelector('#allimg').lastElementChild.querySelector('#comfirm');
// console.log(comfirmBtn,'combtn');
//获取取消按钮
let cancelBtn = el.lastElementChild.querySelector('#allimg').lastElementChild.querySelector('#cancel');
// console.log(cancelBtn,'canbtn');
//拖拽框移动过程
mainEl.onmousemove = e => {
//获取div相对浏览器的位置
let {
top: mainEl_top,
left: mainEl_left,
width: mainEl_width,
height: mainEl_height
} = mainEl.getBoundingClientRect();
mainEl.style.cursor = "move"; //表示可拖动
};
//拖拽框鼠标按住
mainEl.onmousedown = e => {
let mouse = mainEl.style.cursor;
//更改默认样式
mainEl.style.backgroundColor = "rgba(0,0,0,.5)";
mainEl.style.zIndex = 99;
//对象解构赋值
let { left: el_x, top: el_y, width: el_w, height: el_h } = window.getComputedStyle(mainEl);
x = el_x;
y = el_y;
w = el_w;
h = el_h;
// console.log(x,y,w,h)
cx_start = e.clientX;//记住开始x位置
cy_start = e.clientY;//记住开始y位置
// console.log(cx_start,cy_end,'start,end')
//绑定移动事件
document.onmousemove = e => {
cx_end = e.clientX;
cy_end = e.clientY;
//默认左下方向配置
let x_move = cx_end - cx_start;//减法获得右移量
let y_move = cy_end - cy_start;//减法获得下移量
let direct = ["left", "top"];//配置方向
let pos = [x, y];
let move = [x_move, y_move];//偏移量
let limit = 0;//限制选择框框选范围
//判断鼠标的类型进行对应的操作,此处重复,课添加别的操作
switch (mouse) {
case "move":
direct = ["left", "top"];
pos = [x, y];
limit = 0;
break;
}
handle_div(direct, pos, move, limit);//处理移动
};
//取消移动事件
document.onmouseup = (e) => {
//还原默认样式
mainEl.style.zIndex = 9;
document.onmousemove = null;
};
function handle_div(direct, pos, move, limit) {
for (let i = 0; i < direct.length; i++) {
let val = parseInt(pos[i]) + move[i];//开始时坐标加偏移量
if(val<=limit){//<=0则不能左移
val = limit
}else{
let t_width = imgEl.clientWidth;//获取图片宽高
let t_height = imgEl.clientHeight;
// console.log(t_width,t_height,'widthheight')
if(i==0&&val+222>=t_width){//水平移动时左边+选择框宽度不能超过图片宽
val=t_width-222;
}
if(i==1&&val+231>=t_height){//上下移动时上边+选择框高度不能超过图片高
val=t_height-231;
}
}
mainEl.style[direct[i]] = val + "px";//设置偏移sylte
}
}
};
//确定按钮事件
comfirmBtn.onclick = e => {
let { left: el_x, top: el_y, width: el_w, height: el_h } = window.getComputedStyle(mainEl);
x = el_x;
y = el_y;
cut_canvas(x,y);//进行图片裁剪
function cut_canvas(x,y){
// console.log(cavsEl)
if (!cavsEl) {//默认画布大小为222*231px
cavsEl = document.querySelector('.infomation-manage').querySelector('#picture2')
}
const img = imgEl;
x = parseInt(x)
y = parseInt(y)
// console.log(x,y,'weizhi')
const cssText = img.style.cssText
let judge = cssText.indexOf('width')>-1 //首先判断图片大小是否设置*0.7,若设置了width则不是原图,就选择较大的画布
if(judge){//选择画布大小较大的画布
cavsEl = document.querySelector('.infomation-manage').querySelector('#picture')
}
const ctx = cavsEl.getContext("2d");
if(judge)
ctx.drawImage(img,x/0.7,y/0.7,222/0.7,231/0.7,0,0,222/0.7,231/0.7);
else{
ctx.drawImage(img,x,y,222,231,0,0,222,231);
}
// console.log(cavsEl.toDataURL())
el.lastElementChild.style.display = 'none';
// console.log(defaultImg)
defaultImg.setAttribute('src', cavsEl.toDataURL())//裁剪后返回裁剪的图片
// defaultImg.style.display = 'none';
// cavsEl.style.visibility = 'visible'
}
};
//取消按钮事件,隐藏裁剪
cancelBtn.onclick = e => {
el.lastElementChild.style.display = 'none';
}
}
},
data () {
return {
msg: 'Welcome to Your Vue.js App',
headImg: { src: 'https://hlwyy-10001356.image.myqcloud.com/c8c6ea5c-6a19-41a9-8480-2c9765c7ab91', name: ''},
canCut: false,
}
},
methods: {
toUpload(){
this.$refs.uploadFile.click();
},
upload (event) {
let files = event.target.files || event.dataTransfer.files;
if (!files.length) {
return;
}
let formData = new FormData();
// console.log(files[0])
formData.append('file', files[0]);
const fileName = files[0].name
const reader = new FileReader()
reader.readAsDataURL(files[0])
reader.onload = (event) => {
const img = new Image()
img.src = event.target.result
img.onload = (e) => {
// 打印
if (img.width < 222 || img.height < 231) {
// this.canCut = false
alert('个人头像照片需为222*231大小')
formData = ''
} else {
this.canCut = true
if(img.width >= 1000 || img.height >= 900){//如果图片大小过大,则调整宽高为原来的0.7
console.log(img.width,img.height,'width,height')
this.$refs.totalimg.style.width = img.width*0.7 + 'px'
this.$refs.totalimg.style.height = img.height*0.7 + 'px'
}
this.headImg = { src: event.target.result, name: fileName }
}
};
document.querySelector('.infomation-manage').querySelector('.img-span').querySelector('img').style.display = 'block'
document.querySelector('.infomation-manage').querySelector('.img-span').querySelector('#picture').style.visibility = 'hidden'
document.querySelector('.infomation-manage').querySelector('.img-span').querySelector('#picture2').style.visibility = 'hidden'
}
this.$refs.uploadFile.value = null; // 移除文件,可以保证上传同样的文件时,也会触发change事件
},
showCut(){
this.$refs.monogolia.style.display = 'block'
},
},
}
</script>
<style>
.header-item-content{
display: flex;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
.img-span {
width: 90px; height: 90px; border: 1px dashed #aaa; margin: 0 8px;
position: relative;
left: 50%;
top: 50%;
}
.add-icon {
position: absolute;
left: 50%;
margin-left: -7.5px;
top: 50%;
margin-top: -7.5px;
transform: scale(2);
-webkit-transform: scale(2);
-moz-transform: scale(2);
-o-transform: scale(2);
font-weight: bold;
opacity: 0.6;
}
.canvas-ho:hover {
cursor: auto;
}
.img-span:hover {
cursor: pointer;
border: 1px dashed rgba(21, 186, 154, 1);
}
.options {
width: 210px;
display: inline-block;
left: 50%;
position: relative;
}
li {
padding-left: 16px;
text-align: left;
color: #539CDB;
width: 100%;
line-height: 20px;
position: absolute;
}
li:hover {
cursor: pointer;
text-decoration: underline;
color: rgb(51, 153, 255);
}
.overlay{
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,.8);
}
.allimg{
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
position: fixed;
z-index: 2009;
}
.mainBox{
border: 1px solid white;
position: absolute;
top: 0;
left: 0;
width: 222px;
height: 231px;
cursor: move;
}
.minBox {
position: absolute;
height: 8px;
width: 8px;
background-color: white;
}
.left-up {
top: -4px;
left: -4px;
cursor: nw-resize;
}
.up {
left: 50%;
margin-left: -4px;
top: -4px;
cursor: n-resize;
}
.right-up {
right: -4px;
top: -4px;
cursor: ne-resize;
}
.left {
top: 50%;
margin-top: -4px;
left: -4px;
cursor: w-resize;
}
.right {
top: 50%;
margin-top: -4px;
right: -4px;
cursor: w-resize;
}
.left-down {
bottom: -4px;
left: -4px;
cursor: sw-resize;
}
.down {
bottom: -4px;
left: 50%;
margin-left: -4px;
cursor: s-resize;
}
.right-down {
bottom: -4px;
right: -4px;
cursor: se-resize;
}
.canvas-ho:hover {
cursor: auto;
}
</style>