開始
寫了一年多vue,感覺碰到了點瓶頸,學(xué)習(xí)下react找找感覺。剛好最近使用vue寫了個基于cropperJS的圖片裁剪的組件,便花費了幾個晚上的功夫用react再寫一遍。代碼地址
項目是使用create-react-app來開發(fā)的,省去了很多webpack配置的功夫,支持eslint,自動刷新等功能,使用前npm install并npm start即可。推薦同樣是新學(xué)習(xí)react的人也用用看。
項目寫的比較簡陋,自定義配置比較差,不過也是完成了裁剪圖片的基本功能,希望可以幫助到初學(xué)react和想了解裁剪圖片組件的朋友。
組件的結(jié)構(gòu)是這樣的。
<!--Cropper--> <div> <ImageUploader handleImgChange={this.handleImgChange} getCropData={this.getCropData}/> <div className="image-principal"> <img src={this.state.imageValue} alt="" className="img" ref="img" onLoad={this.setSize}/> <SelectArea ref="selectArea"></SelectArea> </div> </div><!--ImageUploader --> <form className="image-upload-form" method="post" encType="multipart/form-data" > <input type="file" name="inputOfFile" ref="imgInput" id="imgInput" onChange={this.props.handleImgChange}/> <button onClick={this.props.getCropData}>獲取裁剪參數(shù)</button> </form><!--SelectArea --> <div className="select-area" onMouseDown={ this.dragStart} ref="selectArea" > <div className="top-resize" onMouseDown={ event => this.resizeStart(event, 'top')}></div> <div className="right-resize" onMouseDown={ event => this.resizeStart(event, 'right')}></div> <div className="bottom-resize" onMouseDown={ event => this.resizeStart(event, 'bottom')}></div> <div className="left-resize" onMouseDown={ event => this.resizeStart(event, 'left')}></div> <div className="right-bottom-resize" onMouseDown={ event => this.resizeStart(event, 'right')}></div> <div className="left-top-resize" onMouseDown={ event => this.resizeStart(event, 'left')}></div> </div>ImageUploader & Cropper
ImageUploader主要做的就是上傳圖片,監(jiān)聽了input的change事件,并調(diào)用了父組件Cropper的的handleImgChange方法,該方法設(shè)置了綁定到img元素的imageValue,會使得img元素出發(fā)load事件。
handleImgChange = e => { let fileReader = new FileReader() fileReader.readAsDataURL(e.target.files[0]) fileReader.onload = e => { this.setState({...this.state, imageValue: e.target.result}) } }load事件觸發(fā)了Cropper的setSize方法,該方法可以設(shè)置了圖片和裁剪選擇框的初始位置和大小。目前裁剪選擇框是默認(rèn)設(shè)置是大小為圖片的80%,中間顯示。
setSize = () => { let img = this.refs.img let widthNum = parseInt(this.props.width, 10) let heightNum = parseInt(this.props.height, 10) this.setState({ ...this.state, naturalSize: { width: img.naturalWidth, height: img.naturalHeight } }) let imgStyle = img.style imgStyle.height = 'auto' imgStyle.width = 'auto' let principalStyle = ReactDOM.findDOMNode(this.refs.selectArea).parentElement.style const ratio = img.width / img.height // 設(shè)置圖片大小、位置 if (img.width > img.height) { imgStyle.width = principalStyle.width = this.props.width imgStyle.height = principalStyle.height = widthNum / ratio + 'px' principalStyle.marginTop = (widthNum - parseInt(principalStyle.height, 10)) / 2 + 'px' principalStyle.marginLeft = 0 } else { imgStyle.height = principalStyle.height = this.props.height imgStyle.width = principalStyle.width = heightNum * ratio + 'px' principalStyle.marginLeft = (heightNum - parseInt(principalStyle.width, 10)) / 2 + 'px' principalStyle.marginTop = 0 } // 設(shè)置選擇框樣式 let selectAreaStyle = ReactDOM.findDOMNode(this.refs.selectArea).style let principalHeight = parseInt(principalStyle.height, 10) let principalWidth = parseInt(principalStyle.width, 10) if (principalWidth > principalHeight) { selectAreaStyle.top = principalHeight * 0.1 + 'px' selectAreaStyle.width = selectAreaStyle.height = principalHeight * 0.8 + 'px' selectAreaStyle.left = (principalWidth - parseInt(selectAreaStyle.width, 10)) / 2 + 'px' } else { selectAreaStyle.left = principalWidth * 0.1 + 'px' selectAreaStyle.width = selectAreaStyle.height = principalWidth * 0.8 + 'px' selectAreaStyle.top = (principalHeight - parseInt(selectAreaStyle.height, 10)) / 2 + 'px' } }
新聞熱點
疑難解答
圖片精選