H5拍照添加水印上传
/**
* 可预览图片 ++水印 名字 部门 当前时间
*/
import React, { Component } from 'react';
import { ImagePicker } from 'antd-mobile';
import { Toast } from '@/pages/project/yjpt/components/PandaToast.jsx'
import envconfig from "@/envconfig/envconfig";
import Carousel, { ModalGateway, Modal } from 'react-images'
import './index.less';
import { getUsrInfo } from '@/util/localUitl'
import moment from 'moment';
class PicturePreview extends Component {
static defaultProps = {
label: '',
name: '',
value: '',
placeholder: '',
readOnly: 0
}
state = {
isShowModal: false,
}
toggleModal = () => {
this.setState({
isShowModal: !this.state.isShowModal,
})
}
mapUrl = (url) => {
if(url.includes('base64')) {
return url;
}
return `${envconfig.pandaURL}/cityinterface/rest/services/filedownload.svc/download${url}`;
}
handleChange = (files, type) => {
if(type === 'add') {
const len = files.length;
const newFile = files[len - 1];
//newFile 就是被上传文件的一些信息 和input 中text=file是一样的道理
this.changeFileFormat(newFile)
// this.uploadImage(newFile);
} else if(type === 'remove') {
const { value } = this.props;
const urls = value.split(',');
const removeUrl = urls.filter(url => !files.find(file => file.url === url));
if(removeUrl.length > 0) {
this.deleteImage(removeUrl[0]);
}
}
}
// 格式转换成base64 添加水印
changeFileFormat=(url) => {
let that=this
let file = url.file;
let fileReader = new FileReader();
fileReader.onloadend = function () {
if (fileReader.readyState == fileReader.DONE) {
// console.log(fileReader)
that.getBase64Time(fileReader.result).then(res=>{
//此时已经完成水印的添加
let data=that.base64TOfile(res)
that.uploadImage(data)
})
}
};
fileReader.readAsDataURL(file);
}
// to base64
getBase64Time(url){
let that =this;
return new Promise((resolve, reject)=>{//异步处理
let canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
image = new Image(),
fontSize, //水印的大小
MAX_WH = 800;//图片的最大宽高比,因为在以上方法中获取的照片size太大,上传时耗时太多所以需要做处理
image.crossOrigin = "Anonymous";
image.onload = function() {//这里是一个异步,所以获取到的base64文件需要用回调
if (image.height>MAX_WH) {
image.width *= MAX_WH/image.height;
image.height = MAX_WH
}
if (image.width>MAX_WH) {
image.height *= MAX_WH/ image.width;
image.width = MAX_WH;
}
canvas.height = image.height;
canvas.width = image.width;
ctx.drawImage(image, 0, 0, image.width, image.height);
// if(image.width>100 && image.width<500){
// fontSize = '24px'
// }else if(image.width>=500 && image.width<1000){
// fontSize = '44px'
// }else if(image.width>=1000 && image.width<1500){
// fontSize = '64px'
// }
ctx.font =`30px Arial`;
ctx.fillStyle = "tomato";
let time = moment().format('YYYY-MM-DD HH:mm:ss');//获取当前的时间
ctx.textAlign = "end";
let str = `${time}\n${getUsrInfo().fullName} ${getUsrInfo().depart.name}`;
let b = 30;
let lineheight = 30;
let lines = str.split('\n');
for (let j = 0; j<lines.length; j++){
ctx.fillText(lines[j], image.width-20, image.height- ((j+1)*lineheight) );
}
ctx.textBaseline = "middle";
// ctx.fillText(time, image.width-20, image.height-20);
let dataURL = canvas.toDataURL( "image/png/jpg");
if(dataURL) {
resolve(dataURL)
}else{
reject("err")
}
};
image.src = url
})
}
// 再转换成file,用于保存
base64TOfile(base64){
let that = this;
let arr = base64.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]); // 解码base-64编码的数据
let n = bstr.length;
let u8arr = new Uint8Array(n);// 无符号整型数组
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
//转换成file对象
let filename = new Date().getTime();
let filetest = new File([u8arr], filename, {type:mime})
return filetest
}
// 上传图片
uploadImage = async (file) => {
const { type } = file;
console.log(moment(file.lastModified).format('YYYY-MM-DD HH:mm:ss'))
const { upload, value, name, onChange } = this.props;
const formData = new FormData();
formData.append('filedata', file);
const now = +new Date();
const imgType = type.split("/")[1] || 'png';
const path = `/WebApp/${name}/${now}.${imgType}`;
console.log(this.mapUrl(path))
const params = {
imagePath: path,
data: formData
}
Toast.loading('图片上传中...', 0);
try{
const res = await upload(params);
Toast.hide();
if(res.success) {
let newVal = '';
if(value === '') {
newVal = path;
} else {
newVal = value + ',' + path;
}
onChange && typeof onChange === 'function' && onChange(name, newVal);
}
}catch(e){
console.log(e)
}
}
// 删除
deleteImage = async (url) => {
const { deleteImage, value, onChange, name } = this.props;
const params = {
imagePath: url
};
Toast.loading('图片删除中...', 0);
const res = await deleteImage(params);
Toast.hide();
if(res.status) {
const urls = value.split(',');
const newUrls = urls.filter(u => u !== url);
// console.log(urls, newUrls, url);
onChange && typeof onChange === 'function' && onChange(name, newUrls.join(','));
}
}
render() {
const { isShowModal, } = this.state;
const { label = '', name = '', value = '', placeholder = '', readOnly = 0, unit = '', max = 4 } = this.props;
const files = value.split(',').filter(url => !!url).map(url => ({
url: this.mapUrl(url)
}));
const views = files.map((item) => {
return {
src: item.url
}
})
return (
<div className={`PicturePreview`}>
<div className="label" id='label'>{label}</div>
<ImagePicker
files={files}
onChange={this.handleChange}
onImageClick={this.toggleModal}
disableDelete={readOnly}
selectable={(files.length < max) && !readOnly}
/>
<ModalGateway>
{isShowModal ? (
<Modal onClose={this.toggleModal}>
<Carousel views={views} />
</Modal>
) : null}
</ModalGateway>
</div>
);
}
}
export default PicturePreview;
* 可预览图片 ++水印 名字 部门 当前时间
*/
import React, { Component } from 'react';
import { ImagePicker } from 'antd-mobile';
import { Toast } from '@/pages/project/yjpt/components/PandaToast.jsx'
import envconfig from "@/envconfig/envconfig";
import Carousel, { ModalGateway, Modal } from 'react-images'
import './index.less';
import { getUsrInfo } from '@/util/localUitl'
import moment from 'moment';
class PicturePreview extends Component {
static defaultProps = {
label: '',
name: '',
value: '',
placeholder: '',
readOnly: 0
}
state = {
isShowModal: false,
}
toggleModal = () => {
this.setState({
isShowModal: !this.state.isShowModal,
})
}
mapUrl = (url) => {
if(url.includes('base64')) {
return url;
}
return `${envconfig.pandaURL}/cityinterface/rest/services/filedownload.svc/download${url}`;
}
handleChange = (files, type) => {
if(type === 'add') {
const len = files.length;
const newFile = files[len - 1];
//newFile 就是被上传文件的一些信息 和input 中text=file是一样的道理
this.changeFileFormat(newFile)
// this.uploadImage(newFile);
} else if(type === 'remove') {
const { value } = this.props;
const urls = value.split(',');
const removeUrl = urls.filter(url => !files.find(file => file.url === url));
if(removeUrl.length > 0) {
this.deleteImage(removeUrl[0]);
}
}
}
// 格式转换成base64 添加水印
changeFileFormat=(url) => {
let that=this
let file = url.file;
let fileReader = new FileReader();
fileReader.onloadend = function () {
if (fileReader.readyState == fileReader.DONE) {
// console.log(fileReader)
that.getBase64Time(fileReader.result).then(res=>{
//此时已经完成水印的添加
let data=that.base64TOfile(res)
that.uploadImage(data)
})
}
};
fileReader.readAsDataURL(file);
}
// to base64
getBase64Time(url){
let that =this;
return new Promise((resolve, reject)=>{//异步处理
let canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
image = new Image(),
fontSize, //水印的大小
MAX_WH = 800;//图片的最大宽高比,因为在以上方法中获取的照片size太大,上传时耗时太多所以需要做处理
image.crossOrigin = "Anonymous";
image.onload = function() {//这里是一个异步,所以获取到的base64文件需要用回调
if (image.height>MAX_WH) {
image.width *= MAX_WH/image.height;
image.height = MAX_WH
}
if (image.width>MAX_WH) {
image.height *= MAX_WH/ image.width;
image.width = MAX_WH;
}
canvas.height = image.height;
canvas.width = image.width;
ctx.drawImage(image, 0, 0, image.width, image.height);
// if(image.width>100 && image.width<500){
// fontSize = '24px'
// }else if(image.width>=500 && image.width<1000){
// fontSize = '44px'
// }else if(image.width>=1000 && image.width<1500){
// fontSize = '64px'
// }
ctx.font =`30px Arial`;
ctx.fillStyle = "tomato";
let time = moment().format('YYYY-MM-DD HH:mm:ss');//获取当前的时间
ctx.textAlign = "end";
let str = `${time}\n${getUsrInfo().fullName} ${getUsrInfo().depart.name}`;
let b = 30;
let lineheight = 30;
let lines = str.split('\n');
for (let j = 0; j<lines.length; j++){
ctx.fillText(lines[j], image.width-20, image.height- ((j+1)*lineheight) );
}
ctx.textBaseline = "middle";
// ctx.fillText(time, image.width-20, image.height-20);
let dataURL = canvas.toDataURL( "image/png/jpg");
if(dataURL) {
resolve(dataURL)
}else{
reject("err")
}
};
image.src = url
})
}
// 再转换成file,用于保存
base64TOfile(base64){
let that = this;
let arr = base64.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]); // 解码base-64编码的数据
let n = bstr.length;
let u8arr = new Uint8Array(n);// 无符号整型数组
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
//转换成file对象
let filename = new Date().getTime();
let filetest = new File([u8arr], filename, {type:mime})
return filetest
}
// 上传图片
uploadImage = async (file) => {
const { type } = file;
console.log(moment(file.lastModified).format('YYYY-MM-DD HH:mm:ss'))
const { upload, value, name, onChange } = this.props;
const formData = new FormData();
formData.append('filedata', file);
const now = +new Date();
const imgType = type.split("/")[1] || 'png';
const path = `/WebApp/${name}/${now}.${imgType}`;
console.log(this.mapUrl(path))
const params = {
imagePath: path,
data: formData
}
Toast.loading('图片上传中...', 0);
try{
const res = await upload(params);
Toast.hide();
if(res.success) {
let newVal = '';
if(value === '') {
newVal = path;
} else {
newVal = value + ',' + path;
}
onChange && typeof onChange === 'function' && onChange(name, newVal);
}
}catch(e){
console.log(e)
}
}
// 删除
deleteImage = async (url) => {
const { deleteImage, value, onChange, name } = this.props;
const params = {
imagePath: url
};
Toast.loading('图片删除中...', 0);
const res = await deleteImage(params);
Toast.hide();
if(res.status) {
const urls = value.split(',');
const newUrls = urls.filter(u => u !== url);
// console.log(urls, newUrls, url);
onChange && typeof onChange === 'function' && onChange(name, newUrls.join(','));
}
}
render() {
const { isShowModal, } = this.state;
const { label = '', name = '', value = '', placeholder = '', readOnly = 0, unit = '', max = 4 } = this.props;
const files = value.split(',').filter(url => !!url).map(url => ({
url: this.mapUrl(url)
}));
const views = files.map((item) => {
return {
src: item.url
}
})
return (
<div className={`PicturePreview`}>
<div className="label" id='label'>{label}</div>
<ImagePicker
files={files}
onChange={this.handleChange}
onImageClick={this.toggleModal}
disableDelete={readOnly}
selectable={(files.length < max) && !readOnly}
/>
<ModalGateway>
{isShowModal ? (
<Modal onClose={this.toggleModal}>
<Carousel views={views} />
</Modal>
) : null}
</ModalGateway>
</div>
);
}
}
export default PicturePreview;

浙公网安备 33010602011771号