• croppie 在Angular8 中使用


    一:安装

       1. npm install croppie || cnpm install croppie
       2. npm install @types/croppie
    

    二:引入

    1. croppie官网,引入croppie.js和croppie.css文件.
      2.放到静态资源下(例: 下图).

      3.在index.html中引入croppie.css(讲道理在angular.json 中配置一下应该就可以了,但是项目着急,我又是菜鸟.没去研究)
      <link rel="stylesheet" href="./assets/croppie/croppie.css">
      4.引入croppie
      import * as Cropper from 'croppie';
      5.按照官网的步骤,实现就可以了

    三: 源码

    html部分
    <div class="actions">
        <button class="file-btn">
            <span> {{cropedSrc? '修改' : '上传'}}图片</span>
            <input type="file" id="upload" value="选择图片文件" accept="image/gif, image/jpeg,, image/png, image/jpg" />
        </button>
        <div id="result" *ngIf="cropedSrc">
            <img style="max- 200px;max-height: 200px;" [src]="cropedSrc">
            <div class="delete-img">
                <i (click)="redImg()" style="cursor: pointer;" nz-icon nzType="eye" nzTheme="outline"></i>
                <i (click)="resetImg()" style="cursor: pointer;margin-left: 10px;" nz-icon nzType="delete" nzTheme="outline"></i>
            </div>
        </div>
    </div>
    
    <nz-modal [(nzVisible)]="isVisible" nzTitle="图片裁剪" nzWidth="600" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()">
        <div class="crop">
            <div id="upload-demo"></div>
            <div style="display: flex;justify-content: space-between;">
                <button nz-button nzType="default" (click)="rotateLeft()">左旋</button>
                <button nz-button nzType="default" (click)="rotateRight()">右旋</button>
            </div>
        </div>
    </nz-modal>
    
    <nz-modal [(nzVisible)]="checkVisible" nzTitle="图片查看" nzWidth="600" (nzOnCancel)="handleCheckCancel()" (nzOnOk)="handleCheckOk()">
        <div class="check-box">
            <img *ngIf="imgShow" [src]="imgShow">
        </div>
    </nz-modal>
    
    
    css部分
    .actions button,
    .actions a.btn {
        background-color: #F79F42;
        color: white;
        border-radius: 3px;
        border: 1px solid rgba(255, 255, 255, 0.5);
        font-size: 14px;
        cursor: pointer;
        text-decoration: none;
        text-shadow: none;
    }
    
    .actions button:focus {
        outline: 0;
    }
    
    #upload{
        cursor: pointer;
    }
    
    .actions .file-btn {
        position: relative;
         84px;
        height: 36px;
        border-radius: 2px;
        font-size: 14px;
        cursor: pointer;
    }
    
    .actions .file-btn input[type="file"] {
        position: absolute;
        top: 0;
        left: 0;
         100%;
        height: 100%;
        opacity: 0;
        cursor: pointer;
    }
    
    .actions {
        padding: 5px 0;
    }
    
    .actions button {
        margin-right: 5px;
    }
    
    #result{
        margin-top: 20px;
        border: 1px solid #eeeeee;
        box-sizing: border-box;
        padding: 10px;
        background: #eee;
        border-radius: 4px;
        position: relative;
    }
    
    .crop{
         100%;
        padding-top: 20px;
    }
    
    *{
        box-sizing: border-box;
    }
    
    #result:hover .delete-img {
        background-color: rgba(0, 0, 0, 0.5);
        color: #fff;
        font-size: 20px;
        opacity: 1;
        transition: all ease 0.2s;
    }
    
    .delete-img{
        position: absolute;
        display: flex;
        justify-content: center;
        align-items: center;
        top: 0;
        left: 0;
         100%;
        height: 100%;
        opacity: 0;
    }
    
    .check-box{
        display: flex;
        justify-content: center;
    
        img{
             100%;
        }
    }
    
    ts部分
    import { Component, OnInit, ElementRef, Output, Input, EventEmitter, SimpleChanges, OnChanges } from '@angular/core';
    import { environment } from '@env/environment';
    import * as Cropper from 'croppie';
    import { NzMessageService } from 'ng-zorro-antd';
    import { filter } from 'rxjs/operators';
    import { HttpRequest, HttpClient, HttpResponse } from '@angular/common/http';
    
    @Component({
        selector: 'app-image-croppie',
        templateUrl: './image-croppie.component.html',
        styleUrls: ['./image-croppie.component.less']
    })
    export class ImageCroppieComponent implements OnInit, OnChanges {
        @Output() urlChange = new EventEmitter<any>();
        @Input() urlByDetail: any;
    
        uploadElement: any;
        croppie: any;
        isVisible = false;
        cropedSrc: any;
        uploadUrl: string;
        tempFile: any;
        checkVisible = false;
        imgSrc: any;
        imgShow: string;
    
        constructor(private el: ElementRef, private http: HttpClient, private message: NzMessageService, ) {
            this.cropedSrc = null;
            this.imgShow = null;
        }
    
        redImg() {
            this.imgShow = `${environment.baseUrl.bs}/company/SysObjectStorage/read?fileId=${this.imgSrc}`;
            this.checkVisible = true;
        }
    
        resetImg() {
            this.imgShow = null;
            this.cropedSrc = null;
            this.urlChange.emit('');
        }
    
        handleCheckCancel() {
            this.checkVisible = false;
        }
    
        handleCheckOk() {
            this.checkVisible = false;
        }
    
        removeAndDestory() {
            this.croppie.destroy();
            this.uploadElement.removeEventListener('change', this.onFileUpload);
            const inputValue: any = document.getElementById('upload');
            inputValue.value = null;
        }
    
        handleCancel() {
            this.isVisible = false;
            this.removeAndDestory();
        }
    
        handleOk() {
            this.getCroppieImage();
            this.isVisible = false;
            this.removeAndDestory();
        }
    
        initCroppie(url) {
            this.croppie = new Cropper(document.getElementById('upload-demo'), {
                viewport: {  200, height: 200, },
                boundary: {  400, height: 300 },
                enableOrientation: true,
                showZoomer: true,
            });
            this.croppie.bind({ url, zoom: 0 });
        }
    
        initFileUpload() {
            this.uploadElement = document.getElementById('upload');
            console.log(this.uploadElement);
    
            this.uploadElement.addEventListener('change', this.onFileUpload.bind(this));
        }
    
        onFileUpload() {
            this.isVisible = true;
            if (this.uploadElement.files && this.uploadElement.files.length > 0) {
                const file = this.uploadElement.files[0];
                const reader = new FileReader();
                this.tempFile = file;
                reader.readAsDataURL(file);
                reader.onload = ((event: any) => {
                    this.initCroppie(event.target.result);
                    this.uploadUrl = event.target.result;
                    this.croppie.bind({ url: event.target.result, orientation: 4 });
                });
            }
        }
    
        rotateLeft() {
            this.croppie.rotate(90);
        }
    
        rotateRight() {
            this.croppie.rotate(-90);
        }
    
        getCroppieImage() {
            this.croppie.result({ size: {  400, height: 400 } }, { type: 'rawcanvas' }).then(res => {
                // 得到二进制流图片,转化为blob格式传给后台
                const arr = res.split(',');
                const mime = arr[0].match(/:(.*?);/)[1];
                const bstr = atob(arr[1]);
                let n = bstr.length;
                const u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                const imgFile: any = new Blob([u8arr], {
                    type: mime,
                });
    
                imgFile.name = this.tempFile.name;
                this.popupResults({ src: res });
                this.handleUpload({ file: imgFile });
                // yourCroppieReference.result('canvas','original','png',1) 低质量图片旋转之后裁剪可能出现白边
            });
        }
    
        popupResults(result) {
            if (result.src) {
                this.cropedSrc = result.src;
            }
        }
    
        handleUpload = (item) => {
            const formData = new FormData();
            formData.append('file', item.file, item.file.name);
            const host = environment.baseUrl.bs + 'company/SysObjectStorage/upload';
            this.postData(item, host, formData);
        }
    
        postData(item, host, formData) {
            const req = new HttpRequest('POST', host, formData, { reportProgress: true });
            this.http.request(req).pipe(filter(e => e instanceof HttpResponse)).subscribe((event: any) => {
                this.message.success('上传成功');
                this.imgSrc = event.body.value;
                this.urlChange.emit(this.imgSrc);
            }, (err) => {
                console.log('upload fail');
            });
        }
    
        ngOnInit() {
            this.initFileUpload();
        }
    
        ngOnChanges(changes: SimpleChanges): void {
            if (changes.urlByDetail !== undefined) {
                this.cropedSrc = changes.urlByDetail.currentValue;
                this.imgSrc = changes.urlByDetail.currentValue.substr(changes.urlByDetail.currentValue.indexOf('=') + 1);
            }
        }
    }
    
    

    备注: 因为此项目多出用到改功能,所以当组件封装起来.
    angular新手,不喜勿喷..

  • 相关阅读:
    数据库事务的4种隔离级别
    线程竞争与同步
    flex 1与flex auto
    React环境搭建
    vue与mapbox
    前端-URL到页面显示的全过程
    监听滚动事件
    点击上下箭头,页码发生改变
    鼠标滑过元素,div显示,并根据scrollTop向下移动
    KB/MB/GB。。单位换算
  • 原文地址:https://www.cnblogs.com/niluiquhz/p/12036847.html
Copyright © 2020-2023  润新知