国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

react怎樣對圖片進行裁剪

來源:懂視網 責編:小采 時間:2020-11-27 19:39:57
文檔

react怎樣對圖片進行裁剪

react怎樣對圖片進行裁剪:這次給大家帶來react怎樣對圖片進行裁剪,react對圖片進行裁剪的注意事項有哪些,下面就是實戰案例,一起來看一下。開始寫了一年多vue,感覺碰到了點瓶頸,學習下react找找感覺。剛好最近使用vue寫了個基于cropperJS的圖片裁剪的組件,便花費了幾個晚上的功夫
推薦度:
導讀react怎樣對圖片進行裁剪:這次給大家帶來react怎樣對圖片進行裁剪,react對圖片進行裁剪的注意事項有哪些,下面就是實戰案例,一起來看一下。開始寫了一年多vue,感覺碰到了點瓶頸,學習下react找找感覺。剛好最近使用vue寫了個基于cropperJS的圖片裁剪的組件,便花費了幾個晚上的功夫

這次給大家帶來react怎樣對圖片進行裁剪,react對圖片進行裁剪的注意事項有哪些,下面就是實戰案例,一起來看一下。

開始

寫了一年多vue,感覺碰到了點瓶頸,學習下react找找感覺。剛好最近使用vue寫了個基于cropperJS的圖片裁剪的組件,便花費了幾個晚上的功夫用react再寫一遍。代碼地址

項目是使用create-react-app來開發的,省去了很多webpack配置的功夫,支持eslint,自動刷新等功能,使用前npm install并npm start即可。推薦同樣是新學習react的人也用用看。

項目寫的比較簡陋,自定義配置比較差,不過也是完成了裁剪圖片的基本功能,希望可以幫助到初學react和想了解裁剪圖片組件的朋友。

組件的結構是這樣的。

<!--Cropper-->
 <p>
 <ImageUploader handleImgChange={this.handleImgChange} getCropData={this.getCropData}/>
 <p className="image-principal">
 <img src={this.state.imageValue} alt="" className="img" ref="img" onLoad={this.setSize}/>
 <SelectArea ref="selectArea"></SelectArea>
 </p>
 </p>
<!--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}>獲取裁剪參數</button>
 </form>
<!--SelectArea -->
 <p className="select-area" onMouseDown={ this.dragStart} ref="selectArea" >
 <p className="top-resize" onMouseDown={ event => this.resizeStart(event, 'top')}></p>
 <p className="right-resize" onMouseDown={ event => this.resizeStart(event, 'right')}></p>
 <p className="bottom-resize" onMouseDown={ event => this.resizeStart(event, 'bottom')}></p>
 <p className="left-resize" onMouseDown={ event => this.resizeStart(event, 'left')}></p>
 <p className="right-bottom-resize" onMouseDown={ event => this.resizeStart(event, 'right')}></p>
 <p className="left-top-resize" onMouseDown={ event => this.resizeStart(event, 'left')}></p>
 </p>

ImageUploader & Cropper

ImageUploader主要做的就是上傳圖片,監聽了input的change事件,并調用了父組件Cropper的的handleImgChange方法,該方法設置了綁定到img元素的imageValue,會使得img元素出發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事件觸發了Cropper的setSize方法,該方法可以設置了圖片和裁剪選擇框的初始位置和大小。目前裁剪選擇框是默認設置是大小為圖片的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
 // 設置圖片大小、位置
 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
 }
 // 設置選擇框樣式
 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'
 }
 }

Cropper上還有一個getCropData方法,方法會打印并返回裁剪參數,

 getCropData = e => {
 e.preventDefault()
 let SelectArea = ReactDOM.findDOMNode(this.refs.selectArea).style
 let a = {
 width: parseInt(SelectArea.width, 10),
 height: parseInt(SelectArea.height, 10),
 left: parseInt(SelectArea.left, 10),
 top: parseInt(SelectArea.top, 10)
 }
 a.radio = this.state.naturalSize.width / a.width
 console.log(a)
 return a
 }

SelectArea

重新放一遍selectArea的結構。要注意,.top-resize的cursor屬性是 n-resize,而和left,right,bottom對應的分別是w-resize,e-resize,s-resize

 <p className="select-area" onMouseDown={ this.dragStart} ref="selectArea" >
 <p className="top-resize" onMouseDown={ event => this.resizeStart(event, 'top')}></p>
 <p className="right-resize" onMouseDown={ event => this.resizeStart(event, 'right')}></p>
 <p className="bottom-resize" onMouseDown={ event => this.resizeStart(event, 'bottom')}></p>
 <p className="left-resize" onMouseDown={ event => this.resizeStart(event, 'left')}></p>
 <p className="right-bottom-resize" onMouseDown={ event => this.resizeStart(event, 'right')}></p>
 <p className="left-top-resize" onMouseDown={ event => this.resizeStart(event, 'left')}></p>
 </p>

selectArea的state值設為這樣,selectArea保存拖拽選擇框時的參數,resizeArea保存裁剪選擇框時的參數,container為.image-principal元素,el為觸發事件時的event.target。

 this.state = {
 selectArea: null,
 el: null,
 container: null,
 resizeArea: null
 }

拖拽選擇框

在.select-area按下鼠標,觸發mouseDown事件,調用dragStart方法。

使用method = e => {}的形式可以避免在jsx中使用this.method.bind(this)

在這個方法中,首先保存按下鼠標時的鼠標位置,裁剪框與圖片的相對距離和裁剪框的最大位移距離,接著添加事件監聽

 dragStart = e => {
 const el = e.target
 const container = this.state.container
 let selectArea = {
 posLeft: e.clientX,
 posTop: e.clientY,
 left: e.clientX - el.offsetLeft,
 top: e.clientY - el.offsetTop,
 maxMoveX: container.offsetWidth - el.offsetWidth,
 maxMoveY: container.offsetHeight - el.offsetHeight,
 }
 this.setState({ ...this.state, selectArea, el})
 document.addEventListener('mousemove', this.moveBind, false)
 document.addEventListener('mouseup', this.stopBind, false)
 }

moveBind和stopBind來自于

 this.moveBind = this.move.bind(this)
 this.stopBind = this.stop.bind(this)

move方法,在鼠標移動中根據記錄新的鼠標位置來計算新的相對位置newPosLeft和newPosTop,并控制該值在合理范圍內

 move(e) {
 if (!this.state || !this.state.el || !this.state.selectArea) {
 return
 }
 let selectArea = this.state.selectArea
 let newPosLeft = e.clientX- selectArea.left
 let newPosTop = e.clientY - selectArea.top
 // 控制移動范圍
 if (newPosLeft <= 0) {
 newPosLeft = 0
 } else if (newPosLeft > selectArea.maxMoveX) {
 newPosLeft = selectArea.maxMoveX
 }
 if (newPosTop <= 0) {
 newPosTop = 0
 } else if (newPosTop > selectArea.maxMoveY) {
 newPosTop = selectArea.maxMoveY
 }
 let elStyle = this.state.el.style
 elStyle.left = newPosLeft + 'px'
 elStyle.top = newPosTop + 'px'
 }

stop方法,移除事件監聽,清除state,避免方法錯誤調用

 stop() {
 document.removeEventListener('mousemove', this.moveBind , false)
 document.removeEventListener('mousemove', this.resizeBind , false)
 document.removeEventListener('mouseup', this.stopBind, false)
 this.setState({...this.state, el: null, resizeArea: null, selectArea: null})
 }

裁剪選擇框

跟拖拽一樣,首先調用resizeStart方法,保存開始裁剪的鼠標位置,裁剪框的尺寸和位置,添加關于resizeBind和stopBind的事件監聽,注意,由于react的事件機制特點,需要使用stopPropagation來禁止事件冒泡,事件監聽的第三個參數使用false是無效的。

 resizeStart = (e, type) => {
 e.stopPropagation()
 const el = e.target.parentElement
 let resizeArea = {
 posLeft: e.clientX,
 posTop: e.clientY,
 width: el.offsetWidth,
 height: el.offsetHeight,
 left: parseInt(el.style.left, 10),
 top: parseInt(el.style.top, 10)
 }
 this.setState({ ...this.state, resizeArea, el})
 this.resizeBind = this.resize.bind(this, type)
 document.addEventListener('mousemove', this.resizeBind, false)
 document.addEventListener('mouseup', this.stopBind, false)
 }

裁剪的方法,將裁剪分為兩種情況,一種是右側,下側和右下側的拉伸。另一種是左側,上側和左上側的拉伸。

第一種情況下,選擇框的位置是不會變的,只有尺寸會變,處理起來相對簡單。新的尺寸大小為原大小加上當前的鼠標的位置再減去開始拖拽處的鼠標的位置,如果寬度或者高度有一個超標了,則將尺寸設置為剛好到邊界的大小。均為超標,設置為新的尺寸。

第二種情況下,選擇框的位置和大小同時會變,要同時控制尺寸和位置不超出邊界。

 resize(type, e) {
 if (!this.state || !this.state.el || !this.state.resizeArea) {
 return
 }
 let container = this.state.container
 const containerHeight = container.offsetHeight
 const containerWidth = container.offsetWidth
 const containerLeft = parseInt(container.style.left || 0, 10)
 const containerTop = parseInt(container.style.top || 0, 10)
 let resizeArea = this.state.resizeArea
 let el = this.state.el
 let elStyle = el.style
 if (type === 'right' || type === 'bottom') {
 let length
 if (type === 'right') {
 length = resizeArea.width + e.clientX - resizeArea.posLeft
 } else {
 length = resizeArea.height + e.clientY - resizeArea.posTop
 }
 if (parseInt(el.style.left, 10) + length > containerWidth || parseInt(el.style.top, 10) + length > containerHeight) {
 const w = containerWidth - parseInt(el.style.left, 10)
 const h = containerHeight - parseInt(el.style.top, 10)
 elStyle.width = elStyle.height = Math.min(w, h) + 'px'
 } else {
 elStyle.width = length + 'px'
 elStyle.height = length + 'px'
 }
 } else {
 let posChange
 let newPosLeft
 let newPosTop
 if (type === 'left') {
 posChange = resizeArea.posLeft - e.clientX
 } else {
 posChange = resizeArea.posTop - e.clientY
 }
 newPosLeft = resizeArea.left - posChange
 // 防止過度縮小
 if (newPosLeft > resizeArea.left + resizeArea.width) {
 elStyle.left = resizeArea.left + resizeArea.width + 'px'
 elStyle.top = resizeArea.top + resizeArea.height + 'px'
 elStyle.width = elStyle.height = '2px'
 return
 }
 newPosTop = resizeArea.top - posChange
 // 到達邊界
 if (newPosLeft <= containerLeft || newPosTop < containerTop) {
 // 讓選擇框到圖片最左邊
 let newPosLeft2 = resizeArea.left -containerLeft
 // 判斷頂部會不會超出邊界
 if (newPosLeft2 < resizeArea.top) {
 // 未超出邊界
 elStyle.top = resizeArea.top - newPosLeft2 + 'px'
 elStyle.left = containerLeft + 'px'
 } else {
 // 讓選擇框到達圖片頂部
 elStyle.top = containerTop + 'px'
 elStyle.left = resizeArea.left + containerTop - resizeArea.top + 'px'
 }
 } else {
 if (newPosLeft < 0) {
 elStyle.left = 0;
 elStyle.width = Math.min(resizeArea.width + posChange - newPosLeft, containerWidth) + 'px'
 elStyle.top = newPosTop - newPosLeft;
 elStyle.height = Math.min(resizeArea.height + posChange - newPosLeft, containerHeight) + 'px'
 return;
 }
 if (newPosTop < 0) {
 elStyle.left = newPosLeft - newPosTop;
 elStyle.width = Math.min(resizeArea.width + posChange - newPosTop, containerWidth) + 'px'
 elStyle.top = 0;
 elStyle.height = Math.min(resizeArea.height + posChange - newPosTop, containerHeight) + 'px'
 return;
 }
 elStyle.left = newPosLeft + 'px'
 elStyle.top = newPosTop + 'px'
 elStyle.width = resizeArea.width + posChange + 'px'
 elStyle.height = resizeArea.height + posChange + 'px'
 }
 }
 }

相信看了本文案例你已經掌握了方法,更多精彩請關注Gxl網其它相關文章!

推薦閱讀:

如何使用vue隱藏div

vuex的state狀態對象使用方式匯總

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

react怎樣對圖片進行裁剪

react怎樣對圖片進行裁剪:這次給大家帶來react怎樣對圖片進行裁剪,react對圖片進行裁剪的注意事項有哪些,下面就是實戰案例,一起來看一下。開始寫了一年多vue,感覺碰到了點瓶頸,學習下react找找感覺。剛好最近使用vue寫了個基于cropperJS的圖片裁剪的組件,便花費了幾個晚上的功夫
推薦度:
標簽: 圖片 剪裁 裁剪
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 国产在线观看第一页 | 国产99久久 | 国产精品久久久久久久久久久久 | 怡红院一区二区三区 | 欧美一区二区在线免费观看 | 国产aⅴ精品一区二区三区久久 | 亚洲精品电影 | 久久精品国产一区 | 伊人色综合一区二区三区 | 日韩一区二区三区在线播放 | 国产成人一区二区三区小说 | 日韩视频在线观看 | 国产成人久久777777 | 120秒免费试看 | 黄色a一级 | 美女视频黄a视频全免费网站下载 | 欧美成人禁片在线观看网址 | 欧美一级成人影院免费的 | 国产在线一区二区三区欧美 | 日韩精品欧美一区二区三区 | 国产在线精彩视频 | 国产九九在线 | 美女视频黄全免费的 | 一区二区三区成人 | 亚欧精品在线观看 | 国产亚洲婷婷香蕉久久精品 | 美女视频黄a视频全免费网站色 | 欧美日韩亚洲一区二区三区在线观看 | 国产91精品久久久久久久 | 九九久久久2 | 欧美精品一区二区在线观看 | 亚洲欧美一区二区三区久久 | 亚洲一区二区三区一品精 | 美女视频黄全免费的 | 欧美不卡二区 | 久久99久久精品国产99热 | 亚洲成a人一区二区三区 | 日韩国产欧美一区二区三区在线 | 全部费免一级毛片不收费 | 日韩视频在线观看免费 | 国产精品免费观看视频播放 |