Skip to content

Commit

Permalink
feat: multiple select box (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
devlzl authored Jan 18, 2024
1 parent 2e66034 commit 3cee6de
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 204 deletions.
15 changes: 1 addition & 14 deletions src/BlockHub/CanvasBlock/Canvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,5 @@ const render = () => {
</script>

<template>
<canvas
ref="canvasRef"
class="absolute"
:width="props.width"
:height="props.height"
:style="{
left: `${props.x}px`,
top: `${props.y}px`,
width: `${props.width}px`,
height: `${props.height}px`,
rotate: `${props.rotate}deg`,
}"
>
</canvas>
<canvas ref="canvasRef" :width="props.width" :height="props.height"> </canvas>
</template>
11 changes: 1 addition & 10 deletions src/BlockHub/PictureBlock/Picture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,7 @@ block.props.events.update.on(({ key, to }) => {
</script>

<template>
<div
class="picture absolute"
:style="{
left: `${props.x}px`,
top: `${props.y}px`,
width: `${props.width}px`,
height: `${props.height}px`,
rotate: `${props.rotate}deg`,
}"
>
<div class="picture">
<img :src="props.url" :style="{ width: '100%', height: '100%' }" />
</div>
</template>
15 changes: 1 addition & 14 deletions src/BlockHub/ShapeBlock/Shape.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,5 @@ const ShapeComponent = {
</script>

<template>
<component
class="absolute"
:is="ShapeComponent"
:size="props.width"
theme="filled"
fill="#4f71be"
:style="{
left: `${props.x}px`,
top: `${props.y}px`,
width: `${props.width}px`,
height: `${props.height}px`,
rotate: `${props.rotate}deg`,
}"
></component>
<component :is="ShapeComponent" :size="props.width" theme="filled" fill="#4f71be"></component>
</template>
12 changes: 1 addition & 11 deletions src/BlockHub/TableBlock/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,7 @@ const cellHeight = computed(() => {
</script>

<template>
<div
ref="tableRef"
class="table absolute border border-dashed border-secondary-border"
:style="{
left: `${props.x}px`,
top: `${props.y}px`,
width: `${props.width}px`,
height: `${props.height}px`,
rotate: `${props.rotate}deg`,
}"
>
<div ref="tableRef" class="table border border-dashed border-secondary-border">
<div
class="row flex"
v-for="(row, rowIndex) of tableData"
Expand Down
7 changes: 1 addition & 6 deletions src/BlockHub/TextBoxBlock/TextBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,8 @@ block.props.events.update.on(({ key, to }) => {

<template>
<div
class="text-box absolute border border-dashed border-secondary-border"
class="text-box border border-dashed border-secondary-border"
:style="{
left: `${props.x}px`,
top: `${props.y}px`,
width: `${props.width}px`,
height: `${props.height}px`,
rotate: `${props.rotate}deg`,
padding: '4px',
textAlign: `${props.align}`,
}"
Expand Down
1 change: 0 additions & 1 deletion src/Const/select.ts

This file was deleted.

31 changes: 18 additions & 13 deletions src/Kernel/ToolBox/controller/Selection/RotateController.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { selectionManager } from '@Kernel/index'
import { ToolController } from '../_ToolController'
import { toSlideCoords } from '@Utils/toSlideCoords'
import { type Block } from '@BlockHub/Block/Block'
import { blockHub } from '@BlockHub/BlockHub'

export class RotateController extends ToolController {
private _rotating = false
private _centerX = 0
private _centerY = 0
private _selectedBlocks: Block[] = []

handleClick() {}

handleMouseDown() {
const blocks = selectionManager.selectedBlocks
if (blocks.length === 1) {
this._rotating = true
}
// TODO: multi blocks rotate
handleMouseDown(event: MouseEvent) {
this._rotating = true
this._selectedBlocks = selectionManager.selectedBlocks

const target = (event.target as HTMLElement).closest('.selectable-block') as HTMLElement
const block = blockHub.getBlock(Number(target.dataset.blockId))
this._centerX = block.x + block.width / 2
this._centerY = block.y + block.height / 2
}

handleMouseMove(event: MouseEvent) {
if (!this._rotating) {
return
}

const block = selectionManager.selectedBlocks[0]
const centerX = block.x + block.width / 2
const centerY = block.y + block.height / 2
const { x, y } = toSlideCoords(event.currentTarget as HTMLElement, event.clientX, event.clientY)
const dx = x - centerX
const dy = y - centerY
const dx = x - this._centerX
const dy = y - this._centerY
const degree = Math.atan2(dx, -dy) * (180 / Math.PI)
block.rotate = degree
this._selectedBlocks.forEach((block) => {
block.rotate = degree
})
}

handleMouseUp() {
Expand Down
14 changes: 6 additions & 8 deletions src/UserInterface/Slide/Slide.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<script setup lang="ts">
import { ref, onMounted, shallowRef, watch } from 'vue'
import { BlockViews } from '@BlockHub/BlockHub'
import { toolBox, selectionManager } from '@Kernel/index'
import { DEFAULT_SLIDE_WIDTH, DEFAULT_SLIDE_HEIGHT } from '@Const/slide'
import { Block } from '@BlockHub/Block/Block'
import SelectedBox from './components/SelectedBox.vue'
import { Slide } from '@Kernel/Slide'
import type { Block } from '@BlockHub/Block/Block'
import type { Slide } from '@Kernel/Slide'
import SelectableBlock from './components/SelectableBlock.vue'
const props = defineProps<{
slide: Slide
Expand Down Expand Up @@ -56,13 +55,12 @@ toolBox.events.toolChange.on(() => {
cursor: toolType === 'TextBox' || toolType === 'Shape' ? 'crosshair' : 'default',
}"
>
<SelectedBox v-if="props.inSlideContainer" />
<component
<SelectableBlock
v-for="block of blocks"
:key="block.id"
:is="BlockViews[block.type]"
:block="block"
:inSlideContainer="props.inSlideContainer"
@click="handleBlockClick($event, block)"
></component>
/>
</div>
</template>
1 change: 1 addition & 0 deletions src/UserInterface/Slide/SlideContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const handleMouseUp = () => {
}
})
showDragArea.value = false
dragAreaRect.value = { x: 0, y: 0, width: 0, height: 0 }
slideContainerRef.value?.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
}
Expand Down
141 changes: 141 additions & 0 deletions src/UserInterface/Slide/components/SelectableBlock.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<script setup lang="ts">
import type { BasicPropName, Block } from '@BlockHub/Block/Block'
import { BlockViews } from '@BlockHub/BlockHub'
import { selectionManager } from '@Kernel/index'
import { OneThirdRotation } from '@icon-park/vue-next'
import { computed, ref } from 'vue'
const { block, inSlideContainer } = defineProps<{
block: Block
inSlideContainer: boolean
}>()
const { x, y, width, height, rotate } = block
const props = ref({ x, y, width, height, rotate })
block.props.events.update.on(({ key, to }) => {
if (['x', 'y', 'width', 'height', 'rotate'].includes(key)) {
const name = key as BasicPropName
props.value[name] = to as number
}
})
const selected = ref(selectionManager.isSelected(block))
const showSelectHandle = computed(() => {
return selected.value && inSlideContainer
})
selectionManager.events.update.on(() => {
selected.value = selectionManager.isSelected(block)
})
</script>

<template>
<div
class="selectable-block absolute"
:data-block-id="block.id"
:style="{
left: `${props.x}px`,
top: `${props.y}px`,
width: `${props.width}px`,
height: `${props.height}px`,
rotate: `${props.rotate}deg`,
}"
>
<component :is="BlockViews[block.type]" :block="block" :style="{ width: '100%', height: '100%' }"></component>

<OneThirdRotation
v-if="showSelectHandle"
class="rotate-handle"
:style="{ top: '-40px', left: `${props.width / 2 - 12}px` }"
theme="outline"
size="24"
fill="#333"
:strokeWidth="2"
/>

<div v-if="showSelectHandle" class="move-handle" :style="{ top: '-6px', left: '0', width: '100%', height: '12px' }">
<div class="absolute w-full h-[2px] top-[5px] bg-[gray]"></div>
</div>
<div
v-if="showSelectHandle"
class="move-handle"
:style="{ bottom: '-6px', left: '0', width: '100%', height: '12px' }"
>
<div class="absolute w-full h-[2px] bottom-[5px] bg-[gray]"></div>
</div>
<div v-if="showSelectHandle" class="move-handle" :style="{ top: '0', left: '-6px', width: '12px', height: '100%' }">
<div class="absolute h-full w-[2px] left-[5px] bg-[gray]"></div>
</div>
<div
v-if="showSelectHandle"
class="move-handle"
:style="{ top: '0', right: '-6px', width: '12px', height: '100%' }"
>
<div class="absolute h-full w-[2px] right-[5px] bg-[gray]"></div>
</div>

<div
v-if="showSelectHandle"
class="size-handle top cursor-ns-resize"
:style="{ top: '-6px', left: `${props.width / 2 - 6}px` }"
></div>
<div
v-if="showSelectHandle"
class="size-handle bottom cursor-ns-resize"
:style="{ bottom: '-6px', left: `${props.width / 2 - 6}px` }"
></div>
<div
v-if="showSelectHandle"
class="size-handle left cursor-ew-resize"
:style="{ top: `${props.height / 2 - 6}px`, left: '-6px' }"
></div>
<div
v-if="showSelectHandle"
class="size-handle right cursor-ew-resize"
:style="{ top: `${props.height / 2 - 6}px`, right: '-6px' }"
></div>

<div
v-if="showSelectHandle"
class="size-handle top left cursor-nwse-resize"
:style="{ top: '-6px', left: '-6px' }"
></div>
<div
v-if="showSelectHandle"
class="size-handle top right cursor-nesw-resize"
:style="{ top: '-6px', right: '-6px' }"
></div>
<div
v-if="showSelectHandle"
class="size-handle bottom left cursor-nesw-resize"
:style="{ bottom: '-6px', left: '-6px' }"
></div>
<div
v-if="showSelectHandle"
class="size-handle bottom right cursor-nwse-resize"
:style="{ bottom: '-6px', right: '-6px' }"
></div>
</div>
</template>

<style scoped lang="scss">
.rotate-handle {
position: absolute;
cursor: grab;
}
.move-handle {
position: absolute;
z-index: 1;
cursor: move;
}
.size-handle {
position: absolute;
z-index: 1;
width: 12px;
height: 12px;
background-color: white;
border: 2px solid gray;
border-radius: 50%;
}
</style>
Loading

0 comments on commit 3cee6de

Please sign in to comment.