oak-general-business/lib/miniprogram_npm/lin-ui/image-picker/index.js

319 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import nodeUtil from '../core/utils/node-util';
import deviceUtil from '../utils/device-util';
import eventUtil from '../core/utils/event-util';
import {promisic} from '../utils/util';
Component({
options: {
// 纯数据字段
pureDataPattern: /urls|cells|preview|remove|sizeType|maxImageSize|clear/
},
behaviors: ['wx://form-field'],
externalClasses: ['l-class', 'l-item-class'],
properties: {
// 图片 url 数组,与 cells 二选一传入
urls: {
type: Array,
value: null
},
// 图片 url 对象数组,与 urls 二选一传入
cells: {
type: Array,
value: null
},
// 每行可显示的个数
size: {
type: Number,
value: null
},
// 图片显示模式
mode: {
type: String,
value: 'aspectFit',
},
// 图片是否可预览
preview: {
type: Boolean,
value: true
},
// 图片是否可被删除
remove: {
type: Boolean,
value: true
},
// 最大可选择图片数量
count: {
type: Number,
value: 9
},
sizeType: {
// 该写法经测试有效
optionalTypes: [Array, String],
value: ['original', 'compressed']
},
// 所选图片最大限制,单位字节
// 0 为无限制
maxImageSize: {
type: Number,
value: 0,
},
// 清除 value
clear: {
type: Boolean,
value: false
},
// 是否传入自定义 slot
// 已弃用,直接传入 slot 即可,无需修改该属性
// todo 1.0.0 移除
custom: {
type: Boolean,
value: false
},
// 存放图片 url 的数组
// 放在 properties 中是因为引入了 behaviors: ['wx://form-field'],
// wx://form-field 中的 value 为 null会引起很多报错
// value 放在 data 中没有 properties 优先级高,覆盖不了
// 所以只能放在此处
value: {
type: Array,
value: []
}
},
data: {
// 根据 size 不同,计算的图片显示大小不同
itemSizePercentage: null
},
observers: {
/**
* 监听 clear
* @param clear
*/
clear(clear) {
if (clear) {
console.warn('clear 属性已废弃,请使用 linClearImage 函数' +
' 或 urls 属性清空图片\n 详情信息参考:');
this.setData({
value: [],
clear: false
});
}
},
/**
* 监听 urls、cells 更新 value 字段
* @param urls
* @param cells
*/
'urls,cells': function (urls, cells) {
if (!urls && !cells) {
return;
}
let value = [];
if (urls) {
value = urls;
} else if (cells) {
for (const cell of cells) {
if (Object.prototype.hasOwnProperty.call(cell, 'url')) {
value.push(cell.url);
}
}
}
this.setData({
value: value.slice(0, this.data.count)
});
},
/**
* size 属性变化时,重新调整图片大小
* @param size 新值
*/
async size(size) {
if (!size) {
this.setData({itemSizePercentage: null});
return;
}
// 获取 .lin-image-picker__container 容器宽度
const res = await nodeUtil.getNodeRectFromComponent(this, '.lin-image-picker__container');
const widthRpx = deviceUtil.px2rpx(res.right - res.left);
// 根据容器宽度计算单张图片宽度百分比
const itemSizePercentage = ((10 / size * 10) - 20 / widthRpx * 100) + '%;';
this.setData({itemSizePercentage});
},
custom(custom) {
if (custom) {
console.warn('custom 已弃用,请勿使用该属性,直接传入 slot 即可');
}
}
},
methods: {
// ============== 事件监听函数 =============
/**
* 点击图片触发的事件
* 进行图片预览,抛出自定义事件
* @param e
*/
onTapImage(e) {
const that = this;
const value = this.data.value;
const imageIndex = e.currentTarget.dataset.imageIndex;
const imageUrl = value[imageIndex];
const detail = {
all: value,
index: imageIndex,
current: imageUrl
};
eventUtil.emit(this, 'lintap', detail);
// 预览图片
if (this.data.preview) {
wx.previewImage({
urls: value,
current: imageUrl,
success() {
eventUtil.emit(that, 'linpreview', detail);
}
}, true);
}
},
/**
* 点击删除按钮触发的事件
* @param e 事件对象
*/
onTapRemove(e) {
const value = this.data.value;
const imageIndex = e.currentTarget.dataset.imageIndex;
const imageUrl = value[imageIndex];
const detail = {
all: value,
index: imageIndex,
current: imageUrl
};
eventUtil.emit(this, 'linremovetap', detail);
if (this.data.remove) {
this._removeImageByIndex(imageIndex);
}
},
/**
* 点击添加按钮触发的事件
* @returns {Promise<void>}
*/
async onTapAdd() {
let {value, count, sizeType, maxImageSize} = this.data;
const remainCount = count - value.length;
if (value.length >= count || remainCount <= 0) {
return;
}
// 调用微信 api 选择图片
const chooseImageRes = await promisic(wx.chooseImage)({
count: remainCount,
sizeType,
sourceType: ['album', 'camera'],
});
// 即将被添加的图片的 url 数组
const addImageUrlArray = [];
// 超过了大小限制的图片的 url 数组,不会被添加到 image-picker 中
const oversizeImageUrlArray = [];
chooseImageRes.tempFiles.forEach((tempFile) => {
const {path, size} = tempFile;
if (size > maxImageSize && maxImageSize > 0) {
oversizeImageUrlArray.push(path);
} else {
addImageUrlArray.push(path);
}
});
// 赋值并触发事件
this.setData({
value: value.concat(addImageUrlArray)
}, () => {
const detail = {
all: this.data.value,
current: addImageUrlArray,
oversize: oversizeImageUrlArray
};
eventUtil.emit(this, 'linadd', detail);
// todo 1.0.0 版本去除 linchange 事件
eventUtil.emit(this, 'linchange', detail);
// todo 1.0.0 版本去除 linoversize 事件
eventUtil.emit(this, 'linoversize', detail);
});
},
/**
* 供 Form 组件调用的取值方法
* @returns {*}
*/
getValues() {
return this.data.value;
},
// ======= 内部函数 =========
/**
* 根据图片索引删除图片
* @param index 图片索引
* @private
*/
_removeImageByIndex(index) {
const value = this.data.value;
const current = value[index];
value.splice(index, 1);
const detail = {
index,
current,
all: value
};
this.setData({value}, () => {
eventUtil.emit(this, 'linremove', detail);
});
},
// ============== 开放函数 ==============
/**
* 删除图片
* @param imageIndex 图片索引
*/
linRemoveImage(imageIndex) {
this._removeImageByIndex(imageIndex);
},
/**
* 清空所有图片
* 不会触发 linremove 事件
*/
linClearImage() {
this.setData({
value: []
});
},
/**
* 获取所有 url 图片链接
* @returns {Array<String>}
*/
linGetValue() {
return this.data.value;
}
}
});