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;
posted @ 2022-05-12 13:55  雪力顶天  阅读(563)  评论(0)    收藏  举报