• 撸一个 vue 的截图组件,按比例截取


    <template>
        <div class="clip-img" :style="imgStyle">
            <img :src="url" alt="" crossOrigin="anonymous" :style="imgStyle">
            <canvas ref="canvas" :style="imgStyle"  @mousedown="onmousedown" @mousemove="onmousemove"></canvas>
        </div>
    </template>
    <script>
    export default {
        name:"clip-image",
        props:{
            max:{ // 缩放基准宽度或高度
                type:Number,
                default:400
            }
        },
        data(){
            return {
                img:null,
                url:null,
                imgInfo: null, // 压缩前的信息
                imgCInfo:null, // 压缩后的信息
                clipInfo:null, // 压缩前的信息
                clipCinfo:null, // 压缩后的信息
                ctx:null, // 画板
                pos:{x:0,y:0},
                lock: "", // 锁住一个方向
                boundary:null
            }
        },
        computed:{
            imgStyle(){
                let imgCInfo = this.imgCInfo;
                if(imgCInfo){
                    return {
                         `${imgCInfo.w}px`,
                        height: `${imgCInfo.h}px`
                    }
                }
                return {height:"0px",height:"0px",display:"none"};
            }
        },
        async mounted(){
            this.clear();
            this.ctx = this.$refs.canvas.getContext("2d");
            window.addEventListener("mouseup",this.onmouseup);
        },
        methods:{
            init(src,bound){
                this.setSrc(src)
                this.setClip(bound);
            },
            // 外部调用
            async setSrc(src){
                let img = await this.loadImage(src,{crossOrigin:"anonymous"});
                this.img = img;
                this.setImg(img);
            },
            clear(){
                 let obj = {
                    img:null,
                    url:null,
                    imgInfo: null, // 压缩前的信息
                    imgCInfo:null, // 压缩后的信息
                    clipInfo:null, // 压缩前的信息
                    clipCinfo:null, // 压缩后的信息
                    ctx:null, // 画板
                    pos:{x:0,y:0},
                    lock: "", // 锁住一个方向
                    boundary:null
                 }
                 for(let i in obj){
                     this[i]  = obj[i];
                 }
            },
            loadImage(url,attrs){
                this.url = url;
                let img = new Image();
                img.src = url;
                attrs = attrs || {};
                for(let i in attrs){
                    img[i] = attrs[i];
                }
                return new Promise((resolve,reject)=>{
                    img.onload = function(){
                        resolve(img);
                    };
                    img.onerror  = reject;
                });
            },
            setImg(img){
                this.img = img;
                this.imgInfo = {
                    w:img.width,
                    h:img.height
                };
                
                // 压缩图的比例
                let w,h,scale;
                if(img.width > img.height){
                    w = this.max;
                    scale = w/img.width;
                    h = scale*img.height;
                }else{
                    h = this.max;
                    scale = (h/img.height);
                    w = scale * img.width;
                }
                this.imgCInfo = {
                    w,
                    h,
                    scale
                };
                let canvas =  this.$refs.canvas;
                canvas.width = w;
                canvas.height = h;
                this.setClip();
            },
            setClip(clipInfo){
                if(clipInfo){
                    this.clipInfo = {
                        w:clipInfo.width,
                        h:clipInfo.height
                    };
                }
                if(this.imgCInfo && this.clipInfo){
                    this.compressClip(this.imgCInfo,this.clipInfo);
                    this.fill();
                }
            },
            compressClip(imgCInfo,clipInfo){
                // 压缩缩放
                let w,h,scale;
                let imgR = imgCInfo.w/imgCInfo.h;
                let clipR = clipInfo.w / clipInfo.h;
    
                if(imgR > clipR){
                    // 图片的宽度偏大
                    h = imgCInfo.h;
                    scale = h/clipInfo.h;
                    w = scale * clipInfo.w;
                    this.lock = "h";
                }else{
                    // 图片的宽度偏小
                    w = imgCInfo.w;
                    scale = w/clipInfo.w;
                    h = scale * clipInfo.h;
                    this.lock = "w";
                }
                this.clipCinfo = {
                    w,
                    h,
                    scale
                }
                this.boundary = {
                    w:this.imgCInfo.w - this.clipCinfo.w,
                    h:this.imgCInfo.h - this.clipCinfo.h
                };
                this.pos = {
                    x:0,
                    y:0
                };
            },
            onmouseup(){
                this.mouse = null;
            },
            onmousedown(e){
                this.mouse = {
                    x:e.offsetX,
                    y:e.offsetY
                }
            },
            onmousemove(e){
                if(this.mouse){
                    let x = e.offsetX - this.mouse.x ;
                    let y = e.offsetY - this.mouse.y;
                    if(this.lock == "h"){
                        x = this.pos.x + x;
                        if(x < 0){
                            x = 0;
                        }else if(x > this.boundary.w){
                            x = this.boundary.w
                        }
                        this.pos.x = x;
                    }else{
                        y = this.pos.y + y;
                        if(y < 0){
                            y = 0;
                        }else if(y > this.boundary.h){
                            y = this.boundary.h
                        }
                        this.pos.y = y;
                    }
                    this.mouse = {
                        x:e.offsetX,
                        y:e.offsetY
                    }
                    this.fill();
                }
            },
            fill(){
                let {w,h} =  this.clipCinfo;
                let {x,y} = this.pos;
                let clipctx = this.ctx;
                let imgCInfo = this.imgCInfo;
                clipctx.clearRect(0, 0, imgCInfo.w, imgCInfo.h);
                clipctx.beginPath();
                clipctx.fillStyle = 'rgba(0,0,0,0.6)';
                clipctx.strokeStyle = "green";
                //遮罩层
                clipctx.globalCompositeOperation = "source-over";
                clipctx.fillRect(0, 0, imgCInfo.w, imgCInfo.h);
                //画框
                clipctx.globalCompositeOperation = 'destination-out';
                clipctx.fillRect(x, y, w, h);
                //描边
                clipctx.globalCompositeOperation = "source-over";
                clipctx.moveTo(x, y);
                clipctx.lineTo(x + w, y);
                clipctx.lineTo(x + w, y + h);
                clipctx.lineTo(x, y + h);
                clipctx.lineTo(x, y);
                clipctx.stroke();
                clipctx.closePath();
            },
            exportBase(){
                // 导出图片 base64
                let pos = this.pos;
                let scale = this.imgCInfo.scale;
                let sx = pos.x / scale;
                let sy = pos.y / scale;
                let swidth = parseInt(this.clipCinfo.w / scale);
                let sheight = parseInt(this.clipCinfo.h / scale);
                let canvas = document.createElement("canvas");
                canvas.width = swidth;
                canvas.height = sheight;
                let ctx = canvas.getContext("2d");  
                ctx.drawImage(this.img,sx,sy,this.imgInfo.w,this.imgInfo.h,0,0,this.imgInfo.w,this.imgInfo.h);
                return  canvas.toDataURL("image/png");
            },
            dataURLtoFile(b64Data,filename){
                filename = filename || "test.png";
                let mime = "image/png";
                var bstr = atob(b64Data.replace(/^data:image/(png|jpeg|jpg);base64,/, ''));
                var n = bstr.length;
                var u8arr = new Uint8Array(n);
                while(n--){
                    u8arr[n] = bstr.charCodeAt(n);
                }
                // 转换成file对象
                return new File([u8arr], filename, {type:mime});
    
                // 转换成成blob对象
                // return new Blob([u8arr],{type:mime});
                // return blob;
            }
        },
        destroyed(){
            window.removeEventListener("mouseup",this.onmouseup);
        }
    }
    </script>
    <style lang="scss" scoped>
    .clip-img{
        border: 1px solid red;
        margin:  20px auto;
        position: relative;
        height: 0;
         0;
        overflow: hidden;
        canvas{
            position: absolute;
            left: 0;
            top: 0;
            z-index: 1;
            cursor: move;
        }
        img{
            position: relative;
            z-index: 0;
        }
    }
    </style>
    

      

    使用:

    <template>
        <div class="clip-img">
            <clipImage ref="clipImage"></clipImage>
            <button @click="getImg">导出</button> <button @click="slide">切换</button>
            <img :src="src" v-if="src" alt="" class="result">
        </div>
    </template>
    <script>
    import clipImage from "@/components/clip-image.vue";
    export default {
        name:"clip-image",
        data(){
            return {
                src:""
            }
        },
        components:{
            clipImage
        },
        mounted(){
            // setSrc
            this.$refs.clipImage.init("xxx",{400,height:200});
        },
        methods:{
            getImg(){
                this.src = this.$refs.clipImage.exportBase();
                console.log("截图成功")
            },
            slide(){
                this.$refs.clipImage.setSrc("xxx");
            }
        }
    }
    </script>
    <style lang="scss" scoped>
    .clip-img{
        .result{
            max- 400px;
        }
    }
    </style>
    

      

  • 相关阅读:
    win7下 不支持DOS全屏 This system does not support fullscreen mode
    C语言 猜字游戏
    C语言 寻找字符串的第一个小写字母
    getch 函数 当ubuntu下没有curses.h下怎么办?
    C语言 将小写字母写入文件
    vc++读取文件属性的详细信息描述 读取QQ的注册表路径
    C语言 输入字符写入文件再计算文件里的大写字母个数
    #define STRICT 让编译器进行严格类型检查
    HDU1875 畅通工程再续
    HDU4146 Flip Game
  • 原文地址:https://www.cnblogs.com/muamaker/p/12051295.html
Copyright © 2020-2023  润新知