Skip to content

Commit

Permalink
feat: negative direction drag generate TextBox (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
devlzl authored Jan 11, 2024
1 parent 9f01a5d commit cd8f7a4
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 44 deletions.
23 changes: 12 additions & 11 deletions src/BlockHub/TextBoxBlock/TextBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { type TextBoxBlock } from './TextBoxBlock'
import RichText from '@RichText/RichText.vue'
import { ref } from 'vue'
type RectKey = 'x' | 'y' | 'width' | 'height'
const { block } = defineProps<{
block: TextBoxBlock
}>()
const { x, y, textStore, bindController } = block
const { x, y, width, height, textStore, bindController } = block
const width = ref(block.width)
const height = ref(block.height)
const rect = ref({ x, y, width, height })
block.props.events.update.on(({ key, to }) => {
if (key === 'width') {
width.value = to as number
} else if (key === 'height') {
height.value = to as number
const value = to as number
const rectKey = key as RectKey
if (['x', 'y', 'width', 'height'].includes(rectKey)) {
rect.value[rectKey] = value
}
})
</script>
Expand All @@ -24,10 +25,10 @@ block.props.events.update.on(({ key, to }) => {
<div
class="text-box absolute border border-dashed border-secondary-border"
:style="{
left: `${x}px`,
top: `${y}px`,
width: `${width}px`,
height: `${height}px`,
left: `${rect.x}px`,
top: `${rect.y}px`,
width: `${rect.width}px`,
height: `${rect.height}px`,
padding: '4px',
}"
>
Expand Down
47 changes: 26 additions & 21 deletions src/Kernel/ToolBox/ToolBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,37 @@ export class ToolBox {
}

private _bindEvents() {
const eventNames = ['Click', 'MouseDown', 'MouseMove', 'MouseUp'] as const
const previousHandlerMap = Object.create(null)

const _addListener = () => {
eventNames.forEach((eventName) => {
const handler = this._currentController[`handle${eventName}`].bind(this._currentController)
if (eventName === 'MouseUp') {
document.addEventListener('mouseup', handler)
} else {
this._slideElement?.addEventListener(
eventName.toLowerCase() as Lowercase<(typeof eventNames)[number]>,
handler
)
}
previousHandlerMap[eventName] = handler
})
const controller = this._currentController
const slideElement = this._slideElement as HTMLElement

const handleClick = controller.handleClick.bind(this._currentController)
slideElement.addEventListener('click', handleClick)
previousHandlerMap.click = handleClick

const handleMouseDown = controller.handleMouseDown.bind(this._currentController)
slideElement.addEventListener('mousedown', handleMouseDown)
previousHandlerMap.mousedown = handleMouseDown

const handleMouseMove = controller.handleMouseMove.bind(this._currentController)
slideElement.addEventListener('mousemove', handleMouseMove)
previousHandlerMap.mousemove = handleMouseMove

const handleMouseUp = controller.handleMouseUp.bind(this._currentController)
document.addEventListener('mouseup', handleMouseUp)
previousHandlerMap.mouseup = handleMouseUp
}

const _removeListener = () => {
eventNames.forEach((eventName) => {
const handler = previousHandlerMap[eventName]
if (eventName === 'MouseUp') {
document.removeEventListener('mouseup', handler)
} else {
this._slideElement?.removeEventListener(eventName.toLowerCase(), previousHandlerMap[eventName])
}
})
const slideElement = this._slideElement as HTMLElement
slideElement.removeEventListener('click', previousHandlerMap.click)
slideElement.removeEventListener('mousedown', previousHandlerMap.mousedown)
slideElement.removeEventListener('mousemove', previousHandlerMap.mousemove)
document.removeEventListener('mouseup', previousHandlerMap.mouseup)
}

_addListener()
this.events.toolChange.on((toolType) => {
this._currentToolType = toolType
Expand Down
34 changes: 22 additions & 12 deletions src/Kernel/ToolBox/controller/TextBoxToolController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,39 @@ import { TextBoxBlock } from '@BlockHub/TextBoxBlock/TextBoxBlock'
import { ToolController } from './_ToolController'
import { slideManager, toolBox } from '@Kernel/index'
import { TEXT_BOX_DEFAULT_HEIGHT, TEXT_BOX_DEFAULT_WIDTH } from '@Const/block'
import { toSlideCoords } from '../utils'

export class TextBoxToolController extends ToolController {
private _currentBlock?: TextBoxBlock
private _dragging = false
private _startX = 0
private _startY = 0

handleClick() {}

handleMouseDown(event: MouseEvent) {
const { offsetX, offsetY } = event
this._currentBlock = new TextBoxBlock(offsetX, offsetY, 0, 0)
const { x, y } = toSlideCoords(event.currentTarget as HTMLElement, event.clientX, event.clientY)
this._startX = x
this._startY = y
this._currentBlock = new TextBoxBlock(x, y, 0, 0)
slideManager.currentSlide.addBlock(this._currentBlock)
}

handleMouseMove(event: MouseEvent): void {
const { x, y } = toSlideCoords(event.currentTarget as HTMLElement, event.clientX, event.clientY)
const block = this._currentBlock
const { x, y } = (event.currentTarget as HTMLElement).getBoundingClientRect()
const { clientX, clientY } = event
const slideX = clientX - x
const slideY = clientY - y
if (block && slideX > block.x && slideY > block.y) {
if (block) {
this._dragging = true
block.width = slideX - block.x
block.height = slideY - block.y
const left = Math.min(this._startX, x)
const top = Math.min(this._startY, y)
const right = Math.max(this._startX, x)
const bottom = Math.max(this._startY, y)
const width = right - left
const height = bottom - top
block.x = left
block.y = top
block.width = width
block.height = height
}
}

Expand All @@ -33,12 +43,12 @@ export class TextBoxToolController extends ToolController {
if (!block) {
return
}
if (this._dragging) {
this._dragging = false
} else {
if (!this._dragging) {
block.width = TEXT_BOX_DEFAULT_WIDTH
block.height = TEXT_BOX_DEFAULT_HEIGHT
}
this._currentBlock = undefined
this._dragging = false
toolBox.events.toolChange.emit('Default')
}
}
4 changes: 4 additions & 0 deletions src/Kernel/ToolBox/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const toSlideCoords = (slideElement: HTMLElement, clientX: number, clientY: number) => {
const { x, y } = slideElement.getBoundingClientRect()
return { x: clientX - x, y: clientY - y }
}

0 comments on commit cd8f7a4

Please sign in to comment.