在Vue中使用自定义指令进行图片的裁剪

因项目需求,写了一个不用组件的js裁剪图片,整理了一个例子。img标签会出现问题,请将图片转化为代码

<template>
    <div class="infomation-manage">
        <div v-drag>
            <div class="header-item-content">
              <span class="img-span">
				

img标签

                <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>

img标签错误


                   

                    <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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值