|
@@ -1,17 +1,19 @@
|
|
|
<script setup lang="ts">
|
|
|
-import {ref, shallowRef} from "vue";
|
|
|
+import {reactive, ref} from "vue";
|
|
|
import TimeMagnet from "@/components/magnets/timeMagnet.vue";
|
|
|
import vueDrag, {MoveInfo} from "@/components/public/vueDrag.vue";
|
|
|
import {Magnet, MagnetEmit, MagnetSize} from "@/types/magnetType.ts";
|
|
|
-import {computeMagnetStyle, comXY, initTimeMagnetInfo} from "@/components/magnets/magnetInfo.ts";
|
|
|
+import {comMaxWidth, computeMagnetStyle, comXY, initTimeMagnetInfo} from "@/components/magnets/magnetInfo.ts";
|
|
|
|
|
|
import {Calendar} from "@/util/time.ts";
|
|
|
-import {CollisionResult, detectCollisionDirection, Rect} from "@/util/domDrag.ts";
|
|
|
+import {CollisionDirection, CollisionResult, detectCollisionDirection, Drag, Rect} from "@/util/domDrag.ts";
|
|
|
|
|
|
const timeMagnetInfo = initTimeMagnetInfo(TimeMagnet)
|
|
|
|
|
|
interface vueMagnet extends Magnet{
|
|
|
- component: any
|
|
|
+}
|
|
|
+const typeComponent = {
|
|
|
+ [timeMagnetInfo.type]: timeMagnetInfo.component
|
|
|
}
|
|
|
const magnetItemInfos: vueMagnet[] = [
|
|
|
{
|
|
@@ -24,7 +26,6 @@ const magnetItemInfos: vueMagnet[] = [
|
|
|
size: MagnetSize.medium,
|
|
|
editMode: false,
|
|
|
selected: false,
|
|
|
- component: timeMagnetInfo.component
|
|
|
},
|
|
|
{
|
|
|
id: `233`,
|
|
@@ -36,7 +37,6 @@ const magnetItemInfos: vueMagnet[] = [
|
|
|
size: MagnetSize.small,
|
|
|
editMode: false,
|
|
|
selected: false,
|
|
|
- component: timeMagnetInfo.component
|
|
|
},
|
|
|
{
|
|
|
id: `2323`,
|
|
@@ -48,11 +48,12 @@ const magnetItemInfos: vueMagnet[] = [
|
|
|
size: MagnetSize.small,
|
|
|
editMode: false,
|
|
|
selected: false,
|
|
|
- component: timeMagnetInfo.component
|
|
|
}
|
|
|
];
|
|
|
|
|
|
-const magnetItems = shallowRef(magnetItemInfos)
|
|
|
+const magnetItems = reactive(magnetItemInfos)
|
|
|
+const magnetEl = ref();
|
|
|
+let maxWidth = 10;
|
|
|
|
|
|
function daySelect(calendar: Calendar){
|
|
|
console.log(`选择日期 ${calendar.year}年 ${calendar.month}月 ${calendar.day}日`)
|
|
@@ -81,34 +82,49 @@ defineProps({
|
|
|
|
|
|
const moveTipStyle = ref()
|
|
|
|
|
|
-function moveHandle(magnet: vueMagnet, moveInfo: MoveInfo){
|
|
|
- // 计算新位置相对于多少值
|
|
|
- let {x, y} = comXY(moveInfo.left, moveInfo.top)
|
|
|
- let magnetInfo: vueMagnet = {
|
|
|
- ...magnet,
|
|
|
- x: x,
|
|
|
- y: y
|
|
|
- }
|
|
|
- let moveStyle = computeMagnetStyle(magnetInfo)
|
|
|
- moveTipStyle.value = {
|
|
|
- ...moveStyle,
|
|
|
- opacity: `1`
|
|
|
- }
|
|
|
- // 判断当前元素是否占用到对应元素
|
|
|
- // 移动占位元素
|
|
|
- // console.log(magnetInfo)
|
|
|
- comMagnets(magnetInfo)
|
|
|
-}
|
|
|
+
|
|
|
+// 定时器
|
|
|
+let collidingTimer: NodeJS.Timeout | null = null;
|
|
|
+let collidingWaitTime = 300
|
|
|
+
|
|
|
|
|
|
// 计算其他元素的位置
|
|
|
function comMagnets(changeMagnet: vueMagnet){
|
|
|
+ // 挤开当前元素所在位置
|
|
|
+ let collisionMagnets: {
|
|
|
+ magnet: vueMagnet,
|
|
|
+ direction: CollisionDirection
|
|
|
+ }[] = findCollisionMagnet(changeMagnet)
|
|
|
+ // 获取父元素的最大可用宽度
|
|
|
+ let result = [];
|
|
|
+ for (let i = 0; i < collisionMagnets.length; i++)
|
|
|
+ {
|
|
|
+ let item = collisionMagnets[i]
|
|
|
+ squeezeMagnet(changeMagnet, item.magnet , item.direction, maxWidth)
|
|
|
+ // 递归计算该元素的新位置
|
|
|
+ let children = comMagnets(item.magnet)
|
|
|
+ // 子元素移动完成
|
|
|
+ children.forEach(child => {
|
|
|
+ result.push(child)
|
|
|
+ })
|
|
|
+ result.push(item.magnet)
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ // 重新渲染界面
|
|
|
+}
|
|
|
+
|
|
|
+// 寻找已经碰撞的组件
|
|
|
+function findCollisionMagnet(changeMagnet: vueMagnet){
|
|
|
let changeMagnetRect: Rect = {
|
|
|
...changeMagnet
|
|
|
}
|
|
|
- // 挤开当前元素所在位置
|
|
|
- for (let i = 0; i < magnetItems.value.length; i++)
|
|
|
+ let collisionMagnets: {
|
|
|
+ magnet: vueMagnet,
|
|
|
+ direction: CollisionDirection
|
|
|
+ }[] = []
|
|
|
+ for (let i = 0; i < magnetItems.length; i++)
|
|
|
{
|
|
|
- let magnet = magnetItems.value[i]
|
|
|
+ let magnet = magnetItems[i]
|
|
|
if(magnet.id === changeMagnet.id) continue
|
|
|
// 判断当前元素是否被其他元素占用了
|
|
|
// 转换为 rect
|
|
@@ -118,10 +134,85 @@ function comMagnets(changeMagnet: vueMagnet){
|
|
|
let collisionResult: CollisionResult = detectCollisionDirection(changeMagnetRect, magnetRect)
|
|
|
if(collisionResult.colliding)
|
|
|
{
|
|
|
- console.log(`改位置已经有元素 方向${collisionResult.direction}`);
|
|
|
- // console.log(magnet)
|
|
|
+ collisionMagnets.push({
|
|
|
+ magnet,
|
|
|
+ direction: collisionResult.direction
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
+ return collisionMagnets
|
|
|
+}
|
|
|
+
|
|
|
+function squeezeMagnet(checkMagnet: vueMagnet, moveMagnet: vueMagnet, direction: CollisionDirection, _maxWidth: number){
|
|
|
+ let newVal = 0
|
|
|
+ // 移动受阻碍则尝试向下移动
|
|
|
+ if(direction === CollisionDirection.Right )
|
|
|
+ {
|
|
|
+ newVal = checkMagnet.x - moveMagnet.width
|
|
|
+ if(newVal < 0) {
|
|
|
+ return squeezeMagnet(checkMagnet, moveMagnet, CollisionDirection.Down, _maxWidth)
|
|
|
+ }
|
|
|
+ moveMagnet.x = newVal
|
|
|
+ }
|
|
|
+ else if(direction === CollisionDirection.Left)
|
|
|
+ {
|
|
|
+ newVal = checkMagnet.width + checkMagnet.x
|
|
|
+ if(newVal + moveMagnet.width > _maxWidth) {
|
|
|
+ return squeezeMagnet(checkMagnet, moveMagnet, CollisionDirection.Down, _maxWidth)
|
|
|
+ }
|
|
|
+ moveMagnet.x = newVal
|
|
|
+ }
|
|
|
+ else if(direction === CollisionDirection.Down)
|
|
|
+ {
|
|
|
+ newVal = checkMagnet.y - moveMagnet.height
|
|
|
+ if(newVal < 0) {
|
|
|
+ return squeezeMagnet(checkMagnet, moveMagnet, CollisionDirection.Top, _maxWidth)
|
|
|
+ }
|
|
|
+ moveMagnet.y = newVal
|
|
|
+ }
|
|
|
+ else if(direction === CollisionDirection.Top)
|
|
|
+ {
|
|
|
+ newVal = checkMagnet.y + checkMagnet.height
|
|
|
+ moveMagnet.y = newVal
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function moveInitHandle(drag: Drag)
|
|
|
+{
|
|
|
+ // 获取父元素的最大可用宽度
|
|
|
+ maxWidth = comMaxWidth(drag.parent.width) || 10
|
|
|
+ console.log(`maxWidth ${maxWidth}`)
|
|
|
+}
|
|
|
+
|
|
|
+function moveHandle(magnet: vueMagnet, moveInfo: MoveInfo){
|
|
|
+ // 计算新位置相对于多少值
|
|
|
+ let {x, y} = comXY(moveInfo.left, moveInfo.top)
|
|
|
+ let magnetInfo: vueMagnet = {
|
|
|
+ ...magnet,
|
|
|
+ x: x,
|
|
|
+ y: y
|
|
|
+ }
|
|
|
+ magnet.x = magnetInfo.x
|
|
|
+ magnet.y = magnetInfo.y
|
|
|
+ let moveStyle = computeMagnetStyle(magnetInfo)
|
|
|
+ moveTipStyle.value = {
|
|
|
+ ...moveStyle,
|
|
|
+ opacity: `1`
|
|
|
+ }
|
|
|
+ // 判断当前元素是否占用到对应元素
|
|
|
+ // 移动占位元素
|
|
|
+ // console.log(magnetInfo)
|
|
|
+
|
|
|
+ if(collidingTimer) {
|
|
|
+ clearTimeout(collidingTimer);
|
|
|
+ }
|
|
|
+ collidingTimer = setTimeout(()=>{
|
|
|
+ let changeMagnets = comMagnets(magnetInfo)
|
|
|
+ console.log(`更改的元素: ${changeMagnets.length}`)
|
|
|
+ collidingTimer = null
|
|
|
+
|
|
|
+ // 元素全部移动完成
|
|
|
+ }, collidingWaitTime)
|
|
|
}
|
|
|
|
|
|
function moveEndHandle(magnet: vueMagnet, moveInfo: MoveInfo)
|
|
@@ -136,7 +227,7 @@ function moveEndHandle(magnet: vueMagnet, moveInfo: MoveInfo)
|
|
|
|
|
|
<template>
|
|
|
<!-- 磁帖 布局组件, -->
|
|
|
- <div class="magnet scroll">
|
|
|
+ <div class="magnet scroll" :ref="magnetEl">
|
|
|
<!-- 磁贴组件布局 -->
|
|
|
<div class="magnet-move"
|
|
|
v-show="editMode"
|
|
@@ -149,16 +240,24 @@ function moveEndHandle(magnet: vueMagnet, moveInfo: MoveInfo)
|
|
|
:open-drag="editMode"
|
|
|
:move-hide="true"
|
|
|
:y-limit="false"
|
|
|
+ :hide-move="true"
|
|
|
+ @init="moveInitHandle"
|
|
|
@move="(moveInfo)=>{moveHandle(magnet, moveInfo)}"
|
|
|
@move-end="(moveInfo)=>{moveEndHandle(magnet, moveInfo)}"
|
|
|
>
|
|
|
+<!-- 组件遮罩-->
|
|
|
<component
|
|
|
v-show="!editMode"
|
|
|
- :is="magnet.component"
|
|
|
+ :is="typeComponent[magnet.type]"
|
|
|
:size="magnet.size"
|
|
|
@magnet="eventHandler"
|
|
|
></component>
|
|
|
</vue-drag>
|
|
|
+
|
|
|
+<!-- 编辑模式下的按钮控件 -->
|
|
|
+ <div class="edit-control">
|
|
|
+
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -176,12 +275,21 @@ function moveEndHandle(magnet: vueMagnet, moveInfo: MoveInfo)
|
|
|
border-radius: 6px;
|
|
|
box-shadow: 0 1px 2px #ccc;
|
|
|
overflow: hidden;
|
|
|
+ transition: all 0.3s;
|
|
|
}
|
|
|
|
|
|
.magnet-item > * {
|
|
|
position: relative;
|
|
|
}
|
|
|
-
|
|
|
+.magnet-item .magnet-mask {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-color: #fff;
|
|
|
+ opacity: 0.5;
|
|
|
+}
|
|
|
.magnet-item::before {
|
|
|
content: '';
|
|
|
position: absolute;
|
|
@@ -213,4 +321,6 @@ function moveEndHandle(magnet: vueMagnet, moveInfo: MoveInfo)
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
</style>
|