Heim > Web-Frontend > js-Tutorial > Hauptteil

So beschneiden Sie Bilder in React

php中世界最好的语言
Freigeben: 2018-06-07 13:53:21
Original
1887 Leute haben es durchsucht

Dieses Mal zeige ich Ihnen, wie Sie Bilder in React zuschneiden und welche Vorsichtsmaßnahmen beim Zuschneiden von Bildern in React gelten. Das Folgende ist ein praktischer Fall, schauen wir uns das an.

Starten

Ich schreibe Vue seit mehr als einem Jahr und ich habe das Gefühl, dass ich auf einen Engpass gestoßen bin, um das Gefühl herauszufinden. Ich habe erst vor Kurzem mit Vue eine auf CropperJS basierende Komponente zum Zuschneiden von Bildern geschrieben, also habe ich ein paar Nächte damit verbracht, sie noch einmal mit React zu schreiben. Das Codeadressen-

-Projekt wird mit der Create-React-App entwickelt, was viel Aufwand bei der Webpack-Konfiguration spart. Es unterstützt nur npm install und npm start vor der Verwendung. Es wird empfohlen, dass auch Leute, die noch keine Erfahrung mit der Reaktion haben, es ausprobieren.

Das Projekt ist relativ einfach zu schreiben und die benutzerdefinierte Konfiguration ist relativ schlecht. Ich hoffe jedoch, dass es Freunden, die neu sind, helfen kann, darauf zu reagieren Bildkomponente zuschneiden.

Die Struktur der Komponente ist wie folgt.

<!--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>
Nach dem Login kopieren

ImageUploader & Cropper

Die Hauptaufgabe von ImageUploader besteht darin, Bilder hochzuladen, das Änderungsereignis der Eingabe abzuhören und die Methode handleImgChange der übergeordneten Komponente aufzurufen Cropper. Das Festlegen des an das img-Element gebundenen imageValue führt dazu, dass das img-Element das Ladeereignis auslöst. Das

 handleImgChange = e => {
  let fileReader = new FileReader()
  fileReader.readAsDataURL(e.target.files[0])
  fileReader.onload = e => {
   this.setState({...this.state, imageValue: e.target.result})
  }
 }
Nach dem Login kopieren

load-Ereignis löst die setSize-Methode von Cropper aus, die die Anfangsposition und -größe des Bild- und Zuschneideauswahlfelds festlegt. Derzeit ist die Standardeinstellung des Zuschneideauswahlfelds so, dass die Größe 80 % des Bildes beträgt und in der Mitte angezeigt wird.

 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'
  }
 }
Nach dem Login kopieren

Es gibt auch eine getCropData-Methode auf Cropper, die die Zuschneideparameter druckt und zurückgibt,

 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
 }
Nach dem Login kopieren

SelectArea

Die Struktur von selectArea wiedergeben . Es ist zu beachten, dass das Cursor-Attribut von .top-resize n-resize ist und die entsprechenden Attribute für links, rechts und unten w-resize, e-resize und s-resize sind

   <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>
Nach dem Login kopieren

Die Der Statuswert von selectArea ist auf festgelegt. Auf diese Weise speichert selectArea die Parameter beim Ziehen des Auswahlfelds, resizeArea speichert die Parameter beim Zuschneiden des Auswahlfelds, Container ist das .image-principal-Element und el ist das event.target, wenn das Ereignis auftritt ausgelöst wird.

  this.state = {
   selectArea: null,
   el: null,
   container: null,
   resizeArea: null
  }
Nach dem Login kopieren

Ziehen Sie das Auswahlfeld

Drücken Sie die Maus im .select-area, lösen Sie das MouseDown-Ereignis aus und rufen Sie die DragStart-Methode auf.

Durch die Verwendung von method = e => {} kann die Verwendung von this.method.bind(this) in jsx vermieden werden.

Speichern Sie bei dieser Methode zunächst die Position der Maus, wenn die Maus gedrückt wird relativer Abstand zwischen dem Zuschneiderahmen und dem Bild und der maximale Verschiebungsabstand des Zuschneiderahmens, und fügen Sie dann die Ereignis-Listener

 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)
 }
Nach dem Login kopieren

moveBind und stopBind hinzu, die von der

 this.moveBind = this.move.bind(this)
 this.stopBind = this.stop.bind(this)
Nach dem Login kopieren

move-Methode stammen, und zeichnen Sie neue auf Daten während der Mausbewegung. Verwenden Sie die Mausposition, um die neuen relativen Positionen newPosLeft und newPosTop zu berechnen und die Werte innerhalb eines angemessenen Bereichs zu steuern.

 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'
 }
Nach dem Login kopieren

Methode stoppen, Ereignisüberwachung entfernen, Status löschen und falsche Methode vermeiden ruft

 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})
 }
Nach dem Login kopieren

Auswahlfeld zuschneiden

auf. Wie beim Ziehen rufen Sie zuerst die resizeStart-Methode auf, speichern die Mausposition, an der das Zuschneiden beginnt, die Größe und Position des Zuschneidefelds, und fügen Sie Ereignis-Listener für resizeBind und stopBind hinzu. Aufgrund der Eigenschaften des Ereignismechanismus muss stopPropagation verwendet werden, um das Blasen von Ereignissen zu verhindern.

 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)
 }
Nach dem Login kopieren

Die Schneidemethode unterteilt das Schneiden in zwei Situationen: Die eine ist das Strecken der rechten Seite, der unteren Seite und der unteren rechten Seite. Das andere ist die Dehnung auf der linken Seite, der oberen Seite und der oberen linken Seite.

Im ersten Fall ändert sich die Position des Auswahlfelds nicht, nur die Größe ändert sich und die Verarbeitung ist relativ einfach. Die neue Größe ist die Originalgröße plus die aktuelle Mausposition minus die Position der Maus zu Beginn des Ziehens. Wenn entweder die Breite oder Höhe den Standard überschreitet, wird die Größe auf eine Größe eingestellt, die gerade die Grenze erreicht. Alle übertreffen den Standard und sind auf neue Größen eingestellt.

Im zweiten Fall ändern sich Position und Größe des Auswahlfelds gleichzeitig. Es ist notwendig, die Größe und Position gleichzeitig zu steuern, um die Grenze nicht zu überschreiten.

 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'
   }
  }
 }
Nach dem Login kopieren

Ich glaube, dass Sie die Methode beherrschen, nachdem Sie den Fall in diesem Artikel gelesen haben. Weitere spannende Informationen finden Sie in anderen verwandten Artikeln auf der chinesischen PHP-Website!

Empfohlene Lektüre:

Wie man Vue zum Ausblenden von Divs verwendet

Eine Zusammenfassung, wie die Zustandsobjekte von Vuex verwendet werden

Das obige ist der detaillierte Inhalt vonSo beschneiden Sie Bilder in React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!