vue vue-cropper图片裁剪,头像裁剪

官方链接(github):

GitHub - xyxiao001/vue-cropper: A simple picture clipping plugin for vue

相关知识:

1.输出图片太模糊?可以通过enlarge属性修改图片裁剪的质量,默认值1(生成的大小25.k),值2(生成的大小900k),建议使用1.5(生成大小400k左右)。

一、安装。

npm install vue-cropper -S

以下测试代码推荐使用指定版本:

npm install [email protected] -S

如果生成的图片出现偏移多半是版本的问题。不过也有可能是样式问题,如:

img {max-width: 100%;}

如上代码就会出现图片拉伸的情况。

二、项目使用。

针对头像裁剪:

代码:(弹窗组件时view的)

待抽离。

完全代码:

<template>
<div>
    <div class="" style="display:flex;align-items:center;">
        <span>
            地址:<Input v-model="pageData.address" placeholder="请输入" style="width:150px;" />
        </span>
        <span class="ml10">
            邮箱:<Input v-model="pageData.mail" placeholder="请输入" style="width:150px;" />
        </span>
        <!-- <span class="ml10">
            角色:
            <Select v-model="pageData.priority" placeholder="请选择" style="width:100px;" clearable >
                <Option :value="1">用户1</Option>
                <Option :value="0">用户2</Option>
            </Select>
        </span> -->
        <Button type="primary" class="ml10" @click="seach()">查询</Button>
        <Button type="success" style="margin-left:10px;" @click="clear()" ghost>重置</Button>
    </div>
    <div class="mt10">
        <Table :columns="th" :data="td">
            <template slot="address" slot-scope="{ row }">
                <span v-if="!row.address" class="cloc">未绑定</span>
                <span v-else>{
   
   {row.address}}</span>
            </template>
            <template slot="status" slot-scope="{ row }">
                <span v-if="row.status===0" class="green">正常</span>
                <span v-else class="red">禁用</span>
            </template>
            <template slot="control" slot-scope="{ row }">
                <span class="active_t blue" @click="edit(row)">编辑</span>
            </template>
        </Table>
    </div>
    <div class="mt10">
         <Page :total="pageData.total" :current="pageData.page" @on-change="handlePage" />
    </div>
    <!--添加弹窗-->
    <Modal v-model="isBoxPop" :title="box.id?'编辑':'添加'" :maskClosable="false" width="600px" >
        <Form :model="box" :label-width="80">
            <FormItem label="头像" prop="imgUrl" :rules="[{ required: true, message: '请输入封面',trigger:'none'}]">
                <div v-if="box.imgUrl" class="onlineImg">
                    <viewer :images="[box.imgUrl]">
                        <img :src="box.imgUrl" style="width:80px;height:80px;" />
                    </viewer>
                    <span class="removeImg" @click="removeImg()">×</span>
                </div>
                <div v-else class="addImg">
                    <span><Icon type="md-camera" /></span>
                    <input type="file" accept="image/*" onblur="this.value=''" @change="uploadPhoto" class="uploadImg"/>
                </div>
                <span class="ml10 cloc">200×200px</span>
            </FormItem>
            <FormItem label="地址">
                <span v-if="!box.address" class="cloc">未绑定</span>
                <span v-else>{
   
   {box.address}}</span>
            </FormItem>
            <FormItem label="邮箱">
                <Input v-model="box.mail" style="width:50%;" maxlength="48"></Input>
            </FormItem>
            <!-- <FormItem label="性别">
                <Select v-model="box.priority" placeholder="请选择" style="width:100px;" clearable >
                    <Option :value="1">男</Option>
                    <Option :value="0">女</Option>
                </Select>
            </FormItem> -->
            <FormItem label="出生年月">
                <DatePicker v-model="box.birth" :options="options3" type="date" placeholder="请选择时间" style="width: 200px"></DatePicker>
            </FormItem>
            <FormItem label="介绍">
                <Input v-model="box.remark" type="textarea" maxlength="150" :autosize="{minRows: 2,maxRows: 5}" placeholder=""></Input>
            </FormItem>
            <FormItem label="角色">
                <Select v-model="box.memberLevel" placeholder="请选择" style="width:100px;" clearable disabled>
                    <Option :value="1">普通用户</Option>
                </Select>
            </FormItem>
            <FormItem label="状态" prop="status" :rules="[{ required: true, message: '',trigger:'none'}]">
                <Select v-model="box.status" placeholder="请选择" style="width:100px;" clearable >
                    <Option :value="0">正常</Option>
                    <Option :value="1">禁用</Option>
                </Select>
            </FormItem>
        </Form>
        <div slot="footer">
            <Button type="text" size="large" @click="isBoxPop=false;">取消</Button>
            <Button type="success" size="large" @click="saveBox()">确定</Button>
        </div>
    </Modal>
    <Modal v-model="cropperModel" :title="'图片裁剪'" :maskClosable="false" width="950px" @on-ok="uploadAvatar">
        <cropper-image
            :Name="cropperName"
            @uploadImgSuccess = "handleUploadSuccess"
            @getImageData="uploadAvatar"
            ref="cropper">
        </cropper-image>
     </Modal>
    <Modal
    v-model="modal1"
    title="图片裁剪"
    :loading="loading"
    @on-ok="uploadAvatar"
    :mask-closable="false"
    width="460px">
        <div class="cropper">
            <vueCropper
            ref="cropper"
            :img="option.img"
            :outputSize="option.size"
            :outputType="option.outputType"
            :info="true"
            :full="option.full"
            :canMove="option.canMove"
            :canMoveBox="option.canMoveBox"
            :original="option.original"
            :autoCrop="option.autoCrop"
            :fixed="option.fixed"
            :fixedNumber="option.fixedNumber"
            :centerBox="option.centerBox"
            :infoTrue="option.infoTrue"
            :fixedBox="option.fixedBox"
            @realTime="realTime"
            :enlarge="1.5"
            ></vueCropper>
        </div>
        <!--预览效果图-->
        <!-- <div class="show-preview">
            <div :style="previews.div" class="preview" style="overflow:hidden;">
                <img :src="previews.url" :style="previews.img">
            </div>
        </div> -->
        <!-- <div :style="previewStyle1"> 
            <div :style="previews.div">
                <img :src="previews.url" :style="previews.img">
            </div>
        </div> -->
    </Modal>

</div>
</template>

<script>
import axios from 'axios'
import {  getToken } from '@/libs/token.js'
import config from '@/config'
import {regex} from '@/utils/base.js'
import {memberPage,updateMember} from '@/api/http.js'
import CropperImage from '@/components/CropperImage/CropperImage'
import { VueCropper } from "vue-cropper";
export default {
    name: '',
    props: {
    },
    components: {
        CropperImage,VueCropper
    },
    data () {
        return {
            th: [
                { title: "ID", key: "id" },
                { title: "地址", slot: "address" },
                { title: "邮箱", key: "mail" },
                { title: "昵称", key: "username" },
                { title: "状态", slot: "status" },
                { title: "最后登录时间", key: "lastLoginTime" },
                { title: "操作", align: "center", slot: "control" },
            ],
            td: [],
            pageData:{
                page:1,
                size:10,
                total:0,
                address:'',
                mail:''
            },
            isBoxPop:false,
            box:{
                id:"",
                imgUrl:'',
                mail:''
            },
            cropperModel:false,//裁剪弹窗组件
            //头像裁剪
            cropperName:'',
            modal1: false,
            option: {
                img: '', // 裁剪图片的地址
                info: true, // 裁剪框的大小信息
                outputSize: 1, // 裁剪生成图片的质量
                outputType: 'png', // 裁剪生成图片的格式
                canScale: true, // 图片是否允许滚轮缩放
                autoCrop: true, // 是否默认生成截图框
                // autoCropWidth: 200, // 默认生成截图框宽度
                // autoCropHeight: 200, // 默认生成截图框高度
                fixedBox: true, // 固定截图框大小 不允许改变
                fixed: true, // 是否开启截图框宽高固定比例
                fixedNumber: [1, 1], // 截图框的宽高比例
                full: false, // 是否输出原图比例的截图
                canMoveBox: false, // 截图框能否拖动。裁剪框不能拖动的时候,那么拖动时就是控制的图片
                original: false, // 上传图片按照原始比例渲染。true,裁剪框始终保持80%,false:由图片决定。
                centerBox: true, // 截图框是否被限制在图片里面
                infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
            },
            fileinfo:'',
            // 防止重复提交
            loading: false,
            previews: {},
            previewStyle1:{},

            options3: {
                disabledDate (date) {
                    // return date && date.valueOf() < Date.now() - 86400000;//不能选今天之前的日期
                    // return date && date.valueOf() > Date.now() - 86400000;//不能选今天和今天之后的日期
                    return date && date.valueOf() > Date.now();//不能选今天之前的日期
                }
            },//时间选择框
        }
    },
    mounted() {
        this.getList();
    },
    methods: {
        realTime (data) {
            // 固定为 100 高度
            // var previews = data
            // var h = 1
            // var w = 0.2
            // this.previewStyle1 = {
            //     width: previews.w + "px",
            //     height: previews.h + "px",
            //     overflow: "hidden",
            //     margin: "0",
            //     zoom:  h
            // }
            this.previews = data;
        },
        uploadAvatar() {
            // console.log(data)
            // return;
            // this.$refs.cropper.getCropBlob((data) => {
            //     console.log(data,88)
            //         // this.downImg = window.URL.createObjectURL(data);
            //         // aLink.href = window.URL.createObjectURL(data);
            //         // aLink.click();
            //     });
            //     return;
            let that = this;
            this.$refs.cropper.getCropData((data) => {
                that.loading = true
                // that.$refs.upload.clearFiles() 
                console.log(convertBase64UrlToBlob(data),88);
                // that.$refs.cropper.clearFiles() 
                // let formData=new FormData();
                // formData.append('avatar',data)
                // that.$axios.post('/api/manage/avatar/update',formData,{
                //     'Content-Type':'multipart/form-data'
                // }).then(res=>{
                //     that.loading = false
                //    if(res.data.err_code == 0){
                //         that.$router.push('/login')
                //     }else if(res.data.err_code == 1){
                //         that.$Message.success('修改成功!')
                //         that.changeAvatar({Avatar:res.data.data.slice(1)})
                //     }else{
                //         that.$Message.error('服务器出错!')
                //     }
                
                // })

                //base64转Blob
                function convertBase64UrlToBlob(urlData){
                    //去掉url的头,并转换为byte 
                    var split = urlData.split(',');
                    var bytes=window.atob(split[1]);        
                    //处理异常,将ascii码小于0的转换为大于0  
                    var ab = new ArrayBuffer(bytes.length);  
                    var ia = new Uint8Array(ab);  
                    for (var i = 0; i < bytes.length; i++) {  
                        ia[i] = bytes.charCodeAt(i);  
                    }
                    return new Blob( [ab] , {type : split[0]});  
                } 
                let formData = new FormData();
                let configs = {
                    headers:{
                        "Content-Type":'multipart/form-data',
                        "apiKey": getToken(),
                        'lang':'zh-CN',
                    }
                }
                formData.append('file', convertBase64UrlToBlob(data), new Date().getTime() + '.jpg');
                formData.append('lang','1');//1中文,2英文
                formData.append('type','1');//1图片,2视频
                axios.post(config.baseUrl+'/file/upload',formData,configs).then(data=>{
                    that.loading = false
                    let res=data.data;
                    if(res.code=='000000'){
                        this.$Message.success(res.msg);
                        this.box.imgUrl=res.data.url;
                        this.$forceUpdate();
                    }else{
                        this.$Message.error(res.msg);
                    }
                })
            })
        },
        //图片上传成功后
        handleUploadSuccess (data){
            console.log(data)
            
            switch(data.name){
                case 'flagImg':
                this.formValidate.mainImage = 'http://ydfblog.cn/dfs/'+data.url;
                console.log('最终输出'+data.name)
                break;
            }
            this.cropperModel = false;
        },
        //删除图片
        removeImg(){
            this.$Modal.confirm({
                title:'您确认删除吗?',
                onOk:()=>{
                    this.box.imgUrl='';
                    this.$forceUpdate();
                },
                onCancel:()=>{

                }
            })
        },
        //上传图片
        uploadPhoto(e){
            console.log('选择图片:',e)
            let file = e.target.files[0];
            if(!file)return;
            this.fileinfo =file
            let data = window.URL.createObjectURL(new Blob([file]));
            this.option.img = data
            this.modal1 = true;
            // this.cropperModel=true;
            return false;//取消自动上传
            // let file = e.target.files[0];
            // let formData = new FormData();
            // let configs = {
            //     headers:{
            //         "Content-Type":'multipart/form-data',
            //         "apiKey": getToken(),
            //         'lang':'zh-CN',
            //     }
            // }
            // formData.append('file',file);
            // formData.append('lang','1');//1中文,2英文
            // formData.append('type','1');//1图片,2视频
            // axios.post(config.baseUrl+'/file/upload',formData,configs).then(data=>{
            //     let res=data.data;
            //     if(res.code=='000000'){
            //         this.$Message.success(res.msg);
            //         this.box.imgUrl=res.data.url;
            //         this.$forceUpdate();
            //     }else{
            //         this.$Message.error(res.msg);
            //     }
            // })
        },
        //编辑
        edit(item){
            this.isBoxPop=true;
            this.box=JSON.parse(JSON.stringify(item));
            this.box.id=item.id;
        },
        //保存
        saveBox(){
            let d={
                id:this.box.id,
                imgUrl:this.box.imgUrl,
                mail:this.box.mail,
                remark:this.box.remark,
                birth:this.box.birth && this.$dayjs(this.box.birth).format("YYYY-MM-DD"),//后推一天
                // birth:this.box.birth==''?null:this.$dayjs(this.box.birth).valueOf(),//后推一天
                status:this.box.status,
            }
            if(!d.imgUrl){
                this.$Message.warning('请上传头像!');
                return;
            }
            if(d.mail && !regex(d.mail,'email')){
                this.$Message.warning('邮箱格式不正确!');
                return;
            }
            if(!d.status && d.status!==0){
                this.$Message.warning('请选择状态!');
                return;
            }
            //临时
            // let configs = {
            //     headers:{
            //         "Content-Type": "application/json",
            //         "apiKey": getToken(),
            //         'lang':'zh-CN',
            //     }
            // }
            // axios.post(config.userBaseUrl+'/member/updateMember',d,configs).then((response) => {
            //     let res=response.data;
            //     if(res.code=='000000'){
            //         this.$Message.success(res.msg);
            //         this.getList();
            //         this.isBoxPop=false;
            //     }else{
            //         this.$Message.error(res.msg);
            //     }
            // })
            updateMember(d).then((res) => {
                if(res.code=='000000'){
                    this.$Message.success(res.msg);
                    this.getList();
                    this.isBoxPop=false;
                }else{
                    this.$Message.error(res.msg);
                }
            });
        },
        //清空
        clear(){
            this.pageData={
                page:1,
                address:'',
                mail:''
            }
            this.getList();
        },
        //搜索
        seach(){
            this.pageData.page=1;
            this.getList();
        },
        handlePage(page) {
            this.pageData.page = page;
            this.getList();
        },
        //获取用户列表
        getList() {
            let d={
                current:this.pageData.page,
                size:this.pageData.size,
                address:this.pageData.address && this.pageData.address.trim(),
                mail:this.pageData.mail && this.pageData.mail.trim(),
            }
            //临时
            // let configs = {
            //     headers:{
            //         "Content-Type": "application/json",
            //         "apiKey": getToken(),
            //         'lang':'zh-CN',
            //     }
            // }
            // axios.post(config.userBaseUrl+'/member/memberPage',d,configs).then((response) => {
            //     let res=response.data;
            //     if(res.code=='000000'){
            //         this.td=res.data.list || [];
            //         this.td.forEach(item=>{
            //             item.lastLoginTime=item.lastLoginTime && this.$dayjs(item.lastLoginTime).format('YYYY-MM-DD HH:mm:ss');
            //             item.birth=item.birth && this.$dayjs(item.birth).format('YYYY-MM-DD');
            //         });
            //         this.pageData.total=res.data.totalCount || 0;
            //     }else{
            //         this.$Message.error(res.msg);
            //     }
            // })
            memberPage(d).then((res) => {
                if(res.code=='000000'){
                    this.td=res.data.list || [];
                    this.td.forEach(item=>{
                        item.lastLoginTime=item.lastLoginTime && this.$dayjs(item.lastLoginTime).format('YYYY-MM-DD HH:mm:ss');
                        item.birth=item.birth && this.$dayjs(item.birth).format('YYYY-MM-DD');
                    });
                    this.pageData.total=res.data.totalCount || 0;
                }else{
                    this.$Message.error(res.msg);
                }
            });
        },
    },
}
</script>

<style scoped lang='less'>
.cropper { 
    width: 400px; 
    height: 400px;
}
</style>

针对常规图片的处理(添加部分功能):

代码:

待处理。

完整代码:

三.官方测试所有用例:

 预览地址:https://codepen.io/xyxiao001/pen/wxwKGz

效果图:

代码:

<template>
<div>
    <div id="app">
        <div class="model" v-show="model" @click="model = false">
            <div class="model-show">
                <img :src="modelSrc" alt="">
            </div>
        </div>
        <p>例子</p>
        <div class="cut">
            <vue-cropper ref="cropper" :img="option.img" :output-size="option.size" :output-type="option.outputType" :info="true" :full="option.full" :fixed="fixed" :fixed-number="fixedNumber" :can-move="option.canMove" :can-move-box="option.canMoveBox" :fixed-box="option.fixedBox" :original="option.original" :auto-crop="option.autoCrop" :auto-crop-width="option.autoCropWidth" :auto-crop-height="option.autoCropHeight" :center-box="option.centerBox" @real-time="realTime" :high="option.high" @img-load="imgLoad" mode="cover" :max-img-size="option.max" @crop-moving="cropMoving"></vue-cropper>
        </div>
        <div class="show-preview" :style="{'width': previews.w + 'px', 'height': previews.h + 'px',  'overflow': 'hidden', 'margin': '5px'}">
            <div :style="previews.div">
                <img :src="previews.url" :style="previews.img">
            </div>
        </div>
        <div class="test-button">
            <button @click="changeImg" class="btn">changeImg</button>
            <label class="btn" for="uploads">upload</label>
            <input type="file" id="uploads" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="uploadImg($event, 1)">
            <button @click="startCrop" v-if="!crap" class="btn">start</button>
            <button @click="stopCrop" v-else class="btn">stop</button>
            <button @click="clearCrop" class="btn">clear</button>
            <button @click="refreshCrop" class="btn">refresh</button>
            <button @click="changeScale(1)" class="btn">+</button>
            <button @click="changeScale(-1)" class="btn">-</button>
            <button @click="rotateLeft" class="btn">rotateLeft</button>
            <button @click="rotateRight" class="btn">rotateRight</button>
            <button @click="finish('base64')" class="btn">preview(base64)</button>
            <button @click="finish('blob')" class="btn">preview(blob)</button>
            <a @click="down('base64')" class="btn">download(base64)</a>
            <a @click="down('blob')" class="btn">download(blob)</a>
            <a @click="() => option.img = ''" class="btn">清除图片</a>
            <div style="display:block; width: 100%;">
                <label class="c-item">
                    <span>上传图片是否显示原始宽高 (针对大图 可以铺满)</span>
                    <input type="checkbox" v-model="option.original">
                    <span>original: {
   
   { option.original}}</span>
                </label>
                <label class="c-item">
                    <span>能否拖动图片</span>
                    <input type="checkbox" v-model="option.canMove">
                </label>
                <label class="c-item">
                    <span>能否拖动截图框</span>
                    <input type="checkbox" v-model="option.canMoveBox">
                    <span>canMoveBox: {
   
   { option.canMoveBox}}</span>
                </label>
                <label class="c-item">
                    <span>截图框固定大小</span>
                    <input type="checkbox" v-model="option.fixedBox">
                    <span>fixedBox: {
   
   { option.fixedBox}}</span>
                </label>
                <label class="c-item">
                    <span>是否输出原图比例的截图</span>
                    <input type="checkbox" v-model="option.full">
                    <span>full: {
   
   { option.full}}</span>
                </label>
                <label class="c-item">
                    <span>是否自动生成截图框</span>
                    <input type="checkbox" v-model="option.autoCrop">
                    <span>autoCrop: {
   
   { option.autoCrop}}</span>
                </label>
                <label class="c-item">
                    <span>是否根据dpr生成适合屏幕的高清图片</span>
                    <input type="checkbox" v-model="option.high">
                    <span>high: {
   
   { option.high}}</span>
                </label>
                <label class="c-item">
                    <span>截图框是否限制在图片里(只有在自动生成截图框时才能生效)</span>
                    <input type="checkbox" v-model="option.centerBox">
                    <span>centerBox: {
   
   { option.centerBox}}</span>
                </label>
                <label class="c-item">
                    <p>输出图片格式</p>
                    <label>jpg
                        <input type="radio" name="type" value="jpeg" v-model="option.outputType">
                    </label>
                    <label>png
                        <input type="radio" name="type" value="png" v-model="option.outputType">
                    </label>
                    <label>webp
                        <input type="radio" name="type" value="webp" v-model="option.outputType">
                    </label>
                </label>
            </div>
        </div>
    </div>
</div>
</template>
<script>
import { VueCropper } from "vue-cropper";
export default {
    name: "",
    props: {},
    components: {
        VueCropper,
    },
    data() {
        return {
            model: false,
            modelSrc: "",
            crap: false,
            previews: {},
            lists: [
                {
                    img:
                        "https://avatars2.githubusercontent.com/u/15681693?s=460&v=4",
                },
            ],
            option: {
                img:
                    "https://avatars2.githubusercontent.com/u/15681693?s=460&v=4",
                size: 1,
                full: false,
                outputType: "png",
                canMove: true,
                fixedBox: false,
                original: false,
                canMoveBox: true,
                autoCrop: true,
                // 只有自动截图开启 宽度高度才生效
                autoCropWidth: 160,
                autoCropHeight: 150,
                centerBox: false,
                high: true,
                max: 99999,
            },
            show: true,
            fixed: true,
            fixedNumber: [16, 9],
        };
    },
    mounted() {},
    methods: {
        changeImg() {
            this.option.img = this.lists[
                ~~(Math.random() * this.lists.length)
            ].img;
        },
        startCrop() {
            // start
            this.crap = true;
            this.$refs.cropper.startCrop();
        },
        stopCrop() {
            //  stop
            this.crap = false;
            this.$refs.cropper.stopCrop();
        },
        clearCrop() {
            // clear
            this.$refs.cropper.clearCrop();
        },
        refreshCrop() {
            // clear
            this.$refs.cropper.refresh();
        },
        changeScale(num) {
            num = num || 1;
            this.$refs.cropper.changeScale(num);
        },
        rotateLeft() {
            this.$refs.cropper.rotateLeft();
        },
        rotateRight() {
            this.$refs.cropper.rotateRight();
        },
        finish(type) {
            // 输出
            // var test = window.open('about:blank')
            // test.document.body.innerHTML = '图片生成中..'
            if (type === "blob") {
                this.$refs.cropper.getCropBlob((data) => {
                    console.log(data);
                    var img = window.URL.createObjectURL(data);
                    this.model = true;
                    this.modelSrc = img;
                });
            } else {
                this.$refs.cropper.getCropData((data) => {
                    this.model = true;
                    this.modelSrc = data;
                });
            }
        },
        // 实时预览函数
        realTime(data) {
            this.previews = data;
            console.log(data);
        },

        finish2(type) {
            this.$refs.cropper2.getCropData((data) => {
                this.model = true;
                this.modelSrc = data;
            });
        },
        finish3(type) {
            this.$refs.cropper3.getCropData((data) => {
                this.model = true;
                this.modelSrc = data;
            });
        },
        down(type) {
            // event.preventDefault()
            var aLink = document.createElement("a");
            aLink.download = "demo";
            // 输出
            if (type === "blob") {
                this.$refs.cropper.getCropBlob((data) => {
                    this.downImg = window.URL.createObjectURL(data);
                    aLink.href = window.URL.createObjectURL(data);
                    aLink.click();
                });
            } else {
                this.$refs.cropper.getCropData((data) => {
                    this.downImg = data;
                    aLink.href = data;
                    aLink.click();
                });
            }
        },

        uploadImg(e, num) {
            //上传图片
            // this.option.img
            var file = e.target.files[0];
            if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
                alert("图片类型必须是.gif,jpeg,jpg,png,bmp中的一种");
                return false;
            }
            var reader = new FileReader();
            reader.onload = (e) => {
                let data;
                if (typeof e.target.result === "object") {
                    // 把Array Buffer转化为blob 如果是base64不需要
                    data = window.URL.createObjectURL(
                        new Blob([e.target.result])
                    );
                } else {
                    data = e.target.result;
                }
                if (num === 1) {
                    this.option.img = data;
                } else if (num === 2) {
                    this.example2.img = data;
                }
            };
            // 转化为base64
            // reader.readAsDataURL(file)
            // 转化为blob
            reader.readAsArrayBuffer(file);
        },
        imgLoad(msg) {
            console.log(msg);
        },
        cropMoving(data) {
            console.log(data, "截图框当前坐标");
        },
    },
};
</script>

<style scoped lang='scss'>
* {
    margin: 0;
    padding: 0;
}

.cut {
    width: 500px;
    height: 500px;
    margin: 30px auto;
}

.c-item {
    max-width: 800px;
    margin: 10px auto;
    margin-top: 20px;
}

.content {
    margin: auto;
    max-width: 1200px;
    margin-bottom: 100px;
}

.test-button {
    display: flex;
    flex-wrap: wrap;
    align-content: center;
    justify-content: center;
}

.btn {
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    background: #fff;
    border: 1px solid #c0ccda;
    color: #1f2d3d;
    text-align: center;
    box-sizing: border-box;
    outline: none;
    margin: 20px 10px 0px 0px;
    padding: 9px 15px;
    font-size: 14px;
    border-radius: 4px;
    color: #fff;
    background-color: #50bfff;
    border-color: #50bfff;
    transition: all 0.2s ease;
    text-decoration: none;
    user-select: none;
}

.des {
    line-height: 30px;
}

code.language-html {
    padding: 10px 20px;
    margin: 10px 0px;
    display: block;
    background-color: #333;
    color: #fff;
    overflow-x: auto;
    font-family: Consolas, Monaco, Droid, Sans, Mono, Source, Code, Pro, Menlo,
        Lucida, Sans, Type, Writer, Ubuntu, Mono;
    border-radius: 5px;
    white-space: pre;
}

.show-info {
    margin-bottom: 50px;
}

.show-info h2 {
    line-height: 50px;
}

/*.title, .title:hover, .title-focus, .title:visited {
        color: black;
      }*/

.title {
    display: block;
    text-decoration: none;
    text-align: center;
    line-height: 1.5;
    margin: 20px 0px;
    background-image: -webkit-linear-gradient(
        left,
        #3498db,
        #f47920 10%,
        #d71345 20%,
        #f7acbc 30%,
        #ffd400 40%,
        #3498db 50%,
        #f47920 60%,
        #d71345 70%,
        #f7acbc 80%,
        #ffd400 90%,
        #3498db
    );
    color: transparent;
    -webkit-background-clip: text;
    background-size: 200% 100%;
    animation: slide 5s infinite linear;
    font-size: 40px;
}

.test {
    height: 500px;
}

.model {
    position: fixed;
    z-index: 10;
    width: 100vw;
    height: 100vh;
    overflow: auto;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.8);
}

.model-show {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100vw;
    height: 100vh;
}

.model img {
    display: block;
    margin: auto;
    max-width: 80%;
    user-select: none;
    background-position: 0px 0px, 10px 10px;
    background-size: 20px 20px;
    background-image: linear-gradient(
            45deg,
            #eee 25%,
            transparent 25%,
            transparent 75%,
            #eee 75%,
            #eee 100%
        ),
        linear-gradient(
            45deg,
            #eee 25%,
            white 25%,
            white 75%,
            #eee 75%,
            #eee 100%
        );
}

.c-item {
    display: block;
    user-select: none;
}

@keyframes slide {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: -100% 0;
    }
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_42740797/article/details/123181854