Bootstrap

分享一下使用knova插件进行缩放和拖拽遇到的问题及解决方案

最近使用了一个新的ai标注工具,遇到了一些问题分享给大家

问题

在项目中在对图形进行缩放或者拖拽后再进行绘制矩形时发现鼠标点击的位置和实际出现在图形中的位置不一致,废话不多说。先上代码

drawRectangle() {
      this.temporary = +new Date() + ''
      const Rect = new Konva.Rect()
      console.log(this.stage)
      let initPosition = null
      const onMousedown = ({ evt }) => {
        if (!Rect || evt.ctrlKey || evt.metaKey || evt.button !== 0) return
        initPosition = {
          x: evt.offsetX - this.attrs.x * this.attrs.scaleX,
          y: evt.offsetY - this.attrs.y * this.attrs.scaleY
        }
        Rect.setAttrs({ ...initPosition, stroke: 'gray', id: this.temporary, name: 'Rect' })
        this.layerRect.add(Rect)
        this.stage.on('mousemove', onMouseMove)
        window.addEventListener('mouseup', onMouseUp)
      }
      const onMouseMove = ({ evt }) => {
        if (!Rect || !initPosition) return
        let x = initPosition.x
        let y = initPosition.y
        const RelativePointerPosition = this.stage.getRelativePointerPosition()
        const width = Math.abs(initPosition.x - RelativePointerPosition.x)
        const height = Math.abs(initPosition.y - RelativePointerPosition.y)
        if (RelativePointerPosition.x < x) {
          x = RelativePointerPosition.x
        }
        if (RelativePointerPosition.y < y) {
          y = RelativePointerPosition.y
        }
        const width = Math.abs(initPosition.x - evt.offsetX)
        const height = Math.abs(initPosition.y - evt.offsetY)
        if (evt.offsetX < x) {
           x = evt.offsetX
        }
        if (evt.offsetY < y) {
          y = evt.offsetY
        }
        Rect.setAttrs({
          width,
          x,
          y,
          height
        })
      }
      const onMouseUp = () => {
        // Remove event listener
        this.stage?.off('mousemove', onMouseMove)
        window.removeEventListener('mouseup', onMouseUp)
        this.stage.off('mousedown', onMousedown)
        window.removeEventListener('mouseup', onMouseUp)
        if (!Rect) return
        const labelWidth = Rect.getSize().width
        const labelHeight = Rect.getSize().height
        const newShape = {
          type: 'rect',
          x: Rect.getPosition().x,
          y: Rect.getPosition().y,
          id: this.temporary,
          width: labelWidth,
          height: labelHeight
        }
        Rect.setAttrs(newShape)
        this.currentOperationStatus = '0'
        this.isAddRectDialog = true
      }
      this.stage.on('mousedown', onMousedown)
      this.stage.on('mousemove', onMouseMove)
    }

这是原来的代码,下面是改进后的代码

drawRectangle() {
      this.temporary = +new Date() + ''
      const Rect = new Konva.Rect()
      console.log(this.stage)
      let initPosition = null
      const onMousedown = ({ evt }) => {
        if (!Rect || evt.ctrlKey || evt.metaKey || evt.button !== 0) return
        const RelativePointerPosition = this.stage.getRelativePointerPosition()
        initPosition = {
          x: RelativePointerPosition.x,
          y: RelativePointerPosition.y
        }
        Rect.setAttrs({ ...initPosition, stroke: 'gray', id: this.temporary, name: 'Rect' })
        this.layerRect.add(Rect)
        this.stage.on('mousemove', onMouseMove)
        window.addEventListener('mouseup', onMouseUp)
      }
      const onMouseMove = ({ evt }) => {
        if (!Rect || !initPosition) return
        let x = initPosition.x
        let y = initPosition.y
        const RelativePointerPosition = this.stage.getRelativePointerPosition()
        console.log('鼠标位置变化了', RelativePointerPosition)
        const width = Math.abs(initPosition.x - RelativePointerPosition.x)
        const height = Math.abs(initPosition.y - RelativePointerPosition.y)
        if (RelativePointerPosition.x < x) {
          x = RelativePointerPosition.x
        }
        if (RelativePointerPosition.y < y) {
          y = RelativePointerPosition.y
        }
        Rect.setAttrs({
          width,
          x,
          y,
          height
        })
      }
      const onMouseUp = () => {
        // Remove event listener
        this.stage?.off('mousemove', onMouseMove)
        window.removeEventListener('mouseup', onMouseUp)
        this.stage.off('mousedown', onMousedown)
        window.removeEventListener('mouseup', onMouseUp)
        if (!Rect) return
        const labelWidth = Rect.getSize().width
        const labelHeight = Rect.getSize().height
        const newShape = {
          type: 'rect',
          x: Rect.getPosition().x,
          y: Rect.getPosition().y,
          id: this.temporary,
          width: labelWidth,
          height: labelHeight
        }
        Rect.setAttrs(newShape)
        this.currentOperationStatus = '0'
        this.isAddRectDialog = true
      }
      this.stage.on('mousedown', onMousedown)
      this.stage.on('mousemove', onMouseMove)
    }

这里面主要用到了 getRelativePointerPosition() 这个函数,它是用来获取鼠标再这个舞台中的相对位置的

;