ng-zorro-antd-mobile
Version:
An enterprise-class mobile UI components based on Ant Design and Angular
275 lines (270 loc) • 13.4 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, ViewContainerRef, Component, ViewChild, Input, Output, NgModule } from '@angular/core';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i2 from 'ng-zorro-antd-mobile/flex';
import { FlexModule } from 'ng-zorro-antd-mobile/flex';
class ImagePickerComponent {
get files() {
return this._files;
}
set files(value) {
this._files = value;
this.sortItem();
}
get accept() {
return this._accept;
}
set accept(value) {
this._accept = value;
this.sortItem();
}
get length() {
return this._count;
}
set length(value) {
if (value > 0) {
this._count = value;
}
else {
this._count = 4;
}
this.sortItem();
}
get multiple() {
return this._multiple;
}
set multiple(value) {
this._multiple = value;
this.sortItem();
}
get selectable() {
return this._selectable;
}
set selectable(value) {
this._selectable = value;
this.sortItem();
}
constructor() {
this.prefixCls = 'am-image-picker';
this.flexEl = [];
this._accept = 'image/*';
this._count = 4;
this._selectable = true;
this._files = [];
this._multiple = false;
this.capture = false;
this.disableDelete = false;
this.onFail = new EventEmitter();
this.onChange = new EventEmitter();
this.onImageClick = new EventEmitter();
this.onAddImageClick = new EventEmitter();
}
sortItem() {
if (!this._files) {
return;
}
let count = parseInt('' + this._count, 10);
if (count <= 0) {
count = 4;
}
let allEl = this._files.map(item => {
return {
type: 'img',
backgroundImage: 'url(' + item.url + ')',
transform: 'rotate(' + this.getRotation(item.orientation) + 'deg)'
};
});
if (this._selectable) {
allEl.push({
type: 'select',
backgroundImage: '',
transform: ''
});
}
const length = allEl.length;
if (length !== 0 && length % count !== 0) {
const blankCount = count - (length % count);
const fillBlankEl = [];
for (let i = 0; i < blankCount; i++) {
fillBlankEl.push({
type: 'white',
backgroundImage: '',
transform: ''
});
}
allEl = allEl.concat(fillBlankEl);
}
this.flexEl = [];
for (let i = 0; i < allEl.length / count; i++) {
const rowEl = allEl.slice(i * count, i * count + count);
this.flexEl.push(rowEl);
}
}
addImage(imgItem) {
this._files.push({
type: 'img',
url: imgItem.url,
orientation: imgItem.orientation
});
this.sortItem();
this.onChange.emit({
files: this._files,
operationType: 'add',
index: this._files.length - 1
});
}
removeImage(index) {
this._files.splice(index, 1);
this.sortItem();
this.onChange.emit({
files: this._files,
operationType: 'remove',
index: index
});
}
imageClick(index) {
this.onImageClick.emit({
index: index,
files: this._files
});
}
addImageClick(e) {
this.onAddImageClick.emit(e);
}
parseFile(file, index) {
const reader = new FileReader();
reader.onload = e => {
const dataURL = e.target.result;
if (!dataURL) {
this.onFail.emit(`Fail to get the ${index} image`);
return;
}
let orientation = 1;
this.getOrientation(file, res => {
// -2: not jpeg , -1: not defined
if (res > 0) {
orientation = res;
}
this.addImage({
url: dataURL,
orientation,
file
});
});
};
reader.readAsDataURL(file);
}
fileChange(event) {
const fileList = event.target.files;
if (fileList && fileList.length) {
for (let i = 0; i < fileList.length; i++) {
this.parseFile(fileList[i], i);
}
}
}
getRotation(orientation = 1) {
let imgRotation = 0;
switch (orientation) {
case 3:
imgRotation = 180;
break;
case 6:
imgRotation = 90;
break;
case 8:
imgRotation = 270;
break;
default:
}
return imgRotation;
}
// https://stackoverflow.com/questions/7584794/accessing-jpeg-exif-rotation-data-in-javascript-on-the-client-side
getOrientation(file, callback) {
const reader = new FileReader();
reader.onload = e => {
const view = new DataView(e.target.result);
if (view.getUint16(0, false) !== 0xffd8) {
return callback(-2);
}
const length = view.byteLength;
let offset = 2;
while (offset < length) {
const marker = view.getUint16(offset, false);
offset += 2;
if (marker === 0xffe1) {
const tmp = view.getUint32((offset += 2), false);
if (tmp !== 0x45786966) {
return callback(-1);
}
const little = view.getUint16((offset += 6), false) === 0x4949;
offset += view.getUint32(offset + 4, little);
const tags = view.getUint16(offset, little);
offset += 2;
for (let i = 0; i < tags; i++) {
if (view.getUint16(offset + i * 12, little) === 0x0112) {
return callback(view.getUint16(offset + i * 12 + 8, little));
}
}
}
else if ((marker & 0xff00) !== 0xff00) {
break;
}
else {
offset += view.getUint16(offset, false);
}
}
return callback(-1);
};
reader.readAsArrayBuffer(file.slice(0, 64 * 1024));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: ImagePickerComponent, selector: "ImagePicker, nzm-image-picker", inputs: { capture: "capture", disableDelete: "disableDelete", files: "files", accept: "accept", length: "length", multiple: "multiple", selectable: "selectable" }, outputs: { onFail: "onFail", onChange: "onChange", onImageClick: "onImageClick", onAddImageClick: "onAddImageClick" }, viewQueries: [{ propertyName: "_fileSelectorInput", first: true, predicate: ["fileSelectorInput"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div class=\"{{ prefixCls }}-list\" role=\"group\">\n <Flex *ngFor=\"let rowItem of flexEl; let i = index\">\n <FlexItem *ngFor=\"let item of rowItem; let j = index\">\n <div *ngIf=\"item && 'img' === item.type && item.backgroundImage\" class=\"{{ prefixCls }}-item\">\n <div\n role=\"button\"\n *ngIf=\"!disableDelete\"\n aria-label=\"Click and Remove this image\"\n class=\"{{ prefixCls }}-item-remove\"\n (click)=\"removeImage(i * length + j)\"\n ></div>\n <div\n role=\"button\"\n aria-label=\"Image can be clicked\"\n class=\"{{ prefixCls }}-item-content\"\n [ngStyle]=\"{ 'background-image': item.backgroundImage, transform: item.transform }\"\n (click)=\"imageClick(i * length + j)\"\n ></div>\n </div>\n <div\n role=\"button\"\n aria-label=\"Choose and add image\"\n *ngIf=\"item && 'select' === item.type\"\n class=\"{{ prefixCls }}-item {{ prefixCls }}-upload-btn\"\n (click)=\"addImageClick($event)\"\n >\n <input\n #fileSelectorInput\n type=\"file\"\n [accept]=\"accept\"\n [multiple]=\"multiple\"\n [attr.capture]=\"capture ? capture : null\"\n (change)=\"fileChange($event)\"\n />\n </div>\n <div *ngIf=\"item && 'white' === item.type\" class=\"{{ prefixCls }}-item-white\"></div>\n </FlexItem>\n </Flex>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.FlexComponent, selector: "Flex, nzm-flex", inputs: ["direction", "wrap", "justify", "align", "alignContent"] }, { kind: "component", type: i2.FlexItemComponent, selector: "FlexItem, nzm-flex-item" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerComponent, decorators: [{
type: Component,
args: [{ selector: 'ImagePicker, nzm-image-picker', template: "<div class=\"{{ prefixCls }}-list\" role=\"group\">\n <Flex *ngFor=\"let rowItem of flexEl; let i = index\">\n <FlexItem *ngFor=\"let item of rowItem; let j = index\">\n <div *ngIf=\"item && 'img' === item.type && item.backgroundImage\" class=\"{{ prefixCls }}-item\">\n <div\n role=\"button\"\n *ngIf=\"!disableDelete\"\n aria-label=\"Click and Remove this image\"\n class=\"{{ prefixCls }}-item-remove\"\n (click)=\"removeImage(i * length + j)\"\n ></div>\n <div\n role=\"button\"\n aria-label=\"Image can be clicked\"\n class=\"{{ prefixCls }}-item-content\"\n [ngStyle]=\"{ 'background-image': item.backgroundImage, transform: item.transform }\"\n (click)=\"imageClick(i * length + j)\"\n ></div>\n </div>\n <div\n role=\"button\"\n aria-label=\"Choose and add image\"\n *ngIf=\"item && 'select' === item.type\"\n class=\"{{ prefixCls }}-item {{ prefixCls }}-upload-btn\"\n (click)=\"addImageClick($event)\"\n >\n <input\n #fileSelectorInput\n type=\"file\"\n [accept]=\"accept\"\n [multiple]=\"multiple\"\n [attr.capture]=\"capture ? capture : null\"\n (change)=\"fileChange($event)\"\n />\n </div>\n <div *ngIf=\"item && 'white' === item.type\" class=\"{{ prefixCls }}-item-white\"></div>\n </FlexItem>\n </Flex>\n</div>\n" }]
}], ctorParameters: () => [], propDecorators: { _fileSelectorInput: [{
type: ViewChild,
args: ['fileSelectorInput', { read: ViewContainerRef }]
}], capture: [{
type: Input
}], disableDelete: [{
type: Input
}], files: [{
type: Input
}], accept: [{
type: Input
}], length: [{
type: Input
}], multiple: [{
type: Input
}], selectable: [{
type: Input
}], onFail: [{
type: Output
}], onChange: [{
type: Output
}], onImageClick: [{
type: Output
}], onAddImageClick: [{
type: Output
}] } });
class ImagePickerModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerModule, declarations: [ImagePickerComponent], imports: [CommonModule, FlexModule], exports: [ImagePickerComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerModule, imports: [CommonModule, FlexModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerModule, decorators: [{
type: NgModule,
args: [{
declarations: [ImagePickerComponent],
exports: [ImagePickerComponent],
imports: [CommonModule, FlexModule]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { ImagePickerComponent, ImagePickerModule };
//# sourceMappingURL=ng-zorro-antd-mobile-image-picker.mjs.map