UNPKG

joywok-material-components

Version:

<h1 align="center"> Joywok Material Components </h1>

371 lines (359 loc) 16.1 kB
/** * * @api {} EditImage * @apiName EditImage - 图片上传裁切组件 * @apiGroup 组件使用 * * @apiParam {Number } cutHeight 裁切后的图片高度 (推荐尺寸的 height 值) * @apiParam {Number } cutWidth 裁切后的图片宽度 (推荐尺寸的 width 值) * @apiParam {Number } height 裁切蒙版的高度(最大设为裁剪可视区的像素高度,宽高比保持跟裁切后的宽高比一致,预览效果才是准确的) * @apiParam {Number } width 裁切蒙版的宽度(最大设为裁剪可视区的像素宽度,宽高比保持跟裁切后的宽高比一致,预览效果才是准确的) * @apiParam {Number|Number[] } border 定制裁切蒙版的边框,在裁切时可以在边框里看到图片,但实际裁切时,只裁切蒙版内的图片内容。可不传,或直接设置为0,当传数组时,会当成水平边框和垂直边框 * @apiParam {Number } zoom 缩放比例,推荐尺寸/裁切蒙版尺寸的比值,即 cutWidth/width 或 cutHeight/height * @apiParam {String } cutfileUrl 固定的接口地址,图片裁切接口 URL * @apiParam {String } uploadUrl 固定的接口地址,图片保存接口 URL * @apiParam {String } title 弹框显示的标题 * @apiParam {String } desc 推荐尺寸描述等 * @apiParam {String } colorSystem 色系,gray 灰色;默认为绿色 */ import React , {Component} from 'react'; import {connect} from 'dva'; import AvatarEditor from 'react-avatar-editor' import { Base64 } from 'js-base64'; import Upload from 'antd/lib/upload'; import Progress from 'antd/lib/progress/progress'; import { AloneTip, Button } from 'joywok-material-components'; import request from '../utils/request'; import { COMPONENT_DICT } from '../constants'; require('./style/index.css'); require('./style/form.css'); const Dragger = Upload.Dragger; class EditImage extends React.Component{ constructor(props) { super(props); let self = this; console.log(props,'zzzzzzzz'); this.state = { image: this.props.image ? this.props.image : "", position_x: 0.5, position_y: 0.5, top: 0.5, left: 0.5, mouseFlag: 5, desc: this.props.desc ? this.props.desc : COMPONENT_DICT('label.business.suggested.size')+this.props.cutWidth+"*"+this.props.cutHeight+ ' px', title: this.props.title ? this.props.title : COMPONENT_DICT('label.business.edit.logo'), disabled: true, saveing: false, loading: false, id:this.props.id?this.props.id:'', border: this.props.border ? this.props.border : 0, height: this.props.height ? this.props.height : 0, width: this.props.width ? this.props.width : 0, cutHeight: this.props.cutHeight ? this.props.cutHeight/this.props.zoom : 80, zoom: this.props.zoom, scale: 1, cutWidth: this.props.cutWidth ? this.props.cutWidth/this.props.zoom : 200, cutfileUrl: this.props.cutfileUrl, colorSystem: props.colorSystem || 'green', files: { name: 'jwfile', action: this.props.uploadUrl, accept: props.fileAccept || "image/*,.png,.jpg,.jpeg,.gif", headers: { authorization: 'authorization-text', "Access-Token":window.AccessToken, "Domain-Id": window.DomainId }, beforeUpload(){ self.setState({ percent: 0, }) setTimeout(function(){ self.setState({ show: true, }) },100) let a = AloneTip({ type: 'warning', duration: 1000, hasclose: false, autoHideDuration: 1000, message: COMPONENT_DICT('label.business.uploading') }) // message.loading('上传中…', 0); }, onProgress(){ setTimeout(function(){ self.setState({ percent: 50 }) },200) }, onChange(info) { if (info.file.status !== 'uploading') { self.setState({ loading: true }) } if (info.file.status === 'done') { // message.destroy() if(info.file.response.data && info.file.response.data.data && info.file.response.data.data.errmemo){ // message.error(`${info.file.name} 上传失败`); let a = AloneTip({ type: 'error', duration: 1000, hasclose: false, autoHideDuration: 1000, message: `${info.file.name} ` + COMPONENT_DICT('label.business.failed.upload') }) }else{ if(info.file.response.JMStatus && info.file.response.JMStatus.errmemo){ let a = AloneTip({ type: 'error', duration: 1000, hasclose: false, autoHideDuration: 1000, message: `${info.file.response.JMStatus.errmemo}` }) // message.error(); }else{ console.log('!!!!!! info: ', info); self.state.image = info.file.response.JMTmpfile.link; self.state.height = info.file.response.JMTmpfile.height; self.state.width = info.file.response.JMTmpfile.width; self.state.id = info.file.response.JMTmpfile.fid; self.state.disabled = false; self.state.saveing = false; self.setState({ state: self.state }) // message.success(`${info.file.name} 上传成功`); let a = AloneTip({ type: 'success', duration: 1000, hasclose: false, autoHideDuration: 1000, message: `${info.file.name} ` + COMPONENT_DICT('label.business.success.upload') }) setTimeout(function(){ self.setState({ percent: 100 }) },300) setTimeout(function(){ self.setState({ show: false, }) },2000) } } } else if (info.file.status === 'error') { // message.error(`${info.file.name} file upload failed.`); let a = AloneTip({ type: 'error', duration: 1000, hasclose: false, autoHideDuration: 1000, message: `${info.file.name} file upload failed.` }) } }, }, percent:0, show:false, noCut:this.props.noCut || 'undefined' } } save(){ let self = this; let data = { "type": this.props.type ? this.props.type : "maker" } self.setState({ disabled: true }) data.id = self.state.id if(this.state.noCut!='undefined'){ data.scale = 0; data.height = self.state.height; data.width = self.state.width; data.zoom = 1; data.top = 0; data.left = 0; }else{ data.height = self.props.cutHeight data.width = self.props.cutWidth data.zoom = self.props.zoom let zoom = Math.abs(self.state.scale); if(self.state.height/self.state.cutHeight < self.state.width/self.state.cutWidth){ let height = zoom * self.state.cutHeight; data.scale = height/self.state.height data.top = self.state.top * self.state.cutHeight * zoom - self.state.cutHeight/2 data.left = self.state.left * self.state.cutHeight * zoom * self.state.width / self.state.height - self.state.cutWidth/2 }else{ let width = zoom * self.state.cutWidth; data.scale = width/self.state.width data.left = self.state.left * self.state.cutWidth*zoom - self.state.cutWidth/2 data.top = self.state.top * self.state.cutWidth*zoom * self.state.height / self.state.width - self.state.cutHeight/2 } } let url = self.state.cutfileUrl.replace(":id", data.id) request(url,{ method:"POST", body: JSON.stringify(data) }) .then(function(resp){ if(resp.data.errmemo){ self.setState({ saveing: false }) let a = AloneTip({ type: 'error', duration: 1000, hasclose: false, autoHideDuration: 1000, message:COMPONENT_DICT('label.business.err.info')+ resp.data.errmemo }) // message.error("保存失败,错误信息:"+ resp.data.errmemo ); }else{ if(resp.data.JMStatus && resp.data.JMStatus.errmemo){ // message.error("保存失败,错误信息:"+ resp.data.errmemo ); let a = AloneTip({ type: 'error', duration: 1000, hasclose: false, autoHideDuration: 1000, message:COMPONENT_DICT('label.business.err.info')+ resp.data.errmemo }) self.setState({ saveing: false }) }else{ if(resp.data && resp.data.data && resp.data.data.errmemo){ // message.error("保存失败,错误信息:"+ resp.data.errmemo ); let a = AloneTip({ type: 'error', duration: 1000, hasclose: false, autoHideDuration: 1000, message:COMPONENT_DICT('label.business.err.info')+ resp.data.errmemo }) self.setState({ saveing: false }) }else{ let a = AloneTip({ type: 'success', duration: 1000, hasclose: false, autoHideDuration: 1000, message: COMPONENT_DICT('label.business.saved.success') }) // message.success("保存成功"); self.setState({ disabled: true }) self.props.callback(resp.data) $("body").removeClass('overflowhidden') } } } }) } handleClickClose = () => { this.props.close && this.props.close(); $("body").removeClass('overflowhidden'); } onPositionChange(position){ let self = this; self.setState({ position_x: position.x, position_y: position.y, top: position.y, left: position.x }) } onChange(e,a){ $('.submit').click() } handleScroll(e){ let self = this; if(e.deltaY < 0 && e.deltaY < self.state.mouseFlag*-1){ self.state.scale = (self.state.scale*10-1)/10 == 0 ? (self.state.scale*10-2)/10 : (self.state.scale*10-1)/10 self.setState({ scale: self.state.scale }) }else if(e.deltaY < 0 && e.deltaY > self.state.mouseFlag*-1){ self.state.scale = (self.state.scale*10-1)/10 == 0 ? (self.state.scale*10-2)/10 : (self.state.scale*10-1)/10 self.setState({ scale: self.state.scale }) }else if(e.deltaY > 0 && e.deltaY > self.state.mouseFlag){ self.state.scale = (self.state.scale*10+1)/10 == 0 ? (self.state.scale*10+2)/10 : (self.state.scale*10+1)/10 self.setState({ scale: self.state.scale }) }else if(e.deltaY > 0 && e.deltaY < self.state.mouseFlag){ self.state.scale = (self.state.scale*10+1)/10 == 0 ? (self.state.scale*10+2)/10 : (self.state.scale*10+1)/10 self.setState({ scale: self.state.scale }) } } onDrop(e){ e.preventDefault() } onDragEnter(e){ e.preventDefault() } onDragLeave(e){ e.preventDefault() } componentDidMount(){ $("body").addClass('overflowhidden') } render(){ var self=this; let zoom = 0; if(self.state.height/self.state.cutHeight < self.state.width/self.state.cutWidth){ zoom = self.state.height/self.state.cutHeight }else{ zoom = self.state.width/self.state.cutWidth } let style = { "background-image": "url("+this.state.image+")", "background-size": (self.state.width/2/zoom) + "px " +(self.state.height/2/zoom)+ "px", "background-position": self.state.position_x+" "+self.state.position_y, "width": self.state.cutWidth/2 + "px", "height": self.state.cutHeight/2 + "px" } // {this.state.show?<Progress percent={this.state.percent} showInfo={false} />:''} let colorSystemClass = this.state.colorSystem=='gray'? 'jw-upload-button-gray' : ''; let colorSystemButton = this.state.colorSystem=='gray'? 'jw-button-gray' : ''; return( <div className="jw-img-editor"> <div className="jw-img-editor-bg">&nbsp;</div> <div className="jw-img-editor-content"> <div className="jw-img-content-title">{self.state.title}<div onClick={self.props.close} className="close"><i className="icon-dialog-close"></i></div></div> <div className="jw-img-content-left"> {this.state.show?<Progress percent={this.state.percent} showInfo={false} />:''} <div className="jw-img-content" onWheel={self.handleScroll.bind(self)}> {self.state.image == "" ? "" : <div className="jw-img-content-left-bg">&nbsp;</div>} {self.state.image == "" ? <Dragger className="jw-upload-drop" {...this.state.files}> <div className="drop-1">{COMPONENT_DICT('label.business.drag.img')}</div> <div className="drop-2">{COMPONENT_DICT('label.business.or-by')}</div> <div className={"jw-upload-button "+colorSystemClass}> <Button variant="contained">{COMPONENT_DICT('label.business.choose.from.comp')}</Button> </div> </Dragger> : (this.state.noCut!='undefined' ? <div className={"jw-img-content-nocut-c"}><div className={"jw-img-content-nocut"}> <img src={this.state.image}/></div></div> : <AvatarEditor style={{left: ((440-self.state.cutWidth)/2-self.state.border), top: ((330-self.state.cutHeight)/2-self.state.border)}} image={this.state.image} width={this.state.cutWidth} height={this.state.cutHeight} border={this.state.border} color={[0, 0, 0, 0.3]} scale={Math.abs(self.state.scale)} rotate={0} onPositionChange={this.onPositionChange.bind(this)} /> ) } </div> { this.state.noCut!='undefined'?"":<div className="jw-img-desc">{self.state.desc}</div> } </div> {self.state.image == "" ? "" : <div className="jw-img-content-right"> <div className="jw-img-preview"> <div className="preview-title">{COMPONENT_DICT('label.business.preview')}</div> {(this.state.noCut!='undefined' ? <img src={this.state.image}/> : <AvatarEditor image={this.state.image} width={this.state.cutWidth/2} height={this.state.cutHeight/2} border={0} color={[0, 0, 0, 0.3]} scale={Math.abs(self.state.scale)} rotate={0} position={{x: this.state.position_x , y: this.state.position_y}} onPositionChange={this.onPositionChange.bind(this)} /> )} { //<div className="preview-img" style={style}></div> } </div> <div className={"jw-upload-button " + colorSystemClass}> <Upload {...this.state.files}> <Button className="jw-img-upload-reset"> {this.state.image ? COMPONENT_DICT('label.business.reset.upload') : COMPONENT_DICT('label.business.select.file')} </Button> </Upload> </div> </div> } <div className={"jw-img-editor-options " + colorSystemButton}> {self.state.disabled ? <Button className="editor-save disabled" disabled>{COMPONENT_DICT('label.business.save')}</Button> : (self.state.saveing ? <Button className="editor-save saving">{COMPONENT_DICT('label.business.saving')}</Button> : <Button className="editor-save" onClick={self.save.bind(self)}>{COMPONENT_DICT('label.business.save')}</Button>)} <Button className="editor-cancel" onClick={this.handleClickClose} >{COMPONENT_DICT('label.business.cancel')}</Button> </div> </div> </div> ) } } export default connect()(EditImage);