目的:框选 表格中单元格 ,外面出现一个绿色的边框。
思路: 把选取的单元格 外套上一个 绿色边框的 div
问题描述:当框选 大了时, 无法通过移动鼠标缩小,这时,鼠标要移入 绿色div内 ,
但 绿色边框的 div挡住了下面的td元素 ,无法监听到鼠标移动至的目标,
所以也改不了 绿色边框的 div 的位置 和 大小
<table id='form_table' ref='ref_table' class="form-table" @mousedown = "handleMouseDown" >
<tr>
<td id="1-1">1-1</td>
<td id="1-2">1-2</td>
<td id="1-3" rowspan="2">1-3</td>
<td id="1-4">1-4</td>
<td id="1-5">1-5</td>
</tr>
..略
<div id="select_range" :class="rangeBoxStyle">
</div>
</table>
<script setup lang="ts">
import { ref, reactive, onMounted} from 'vue'
const ref_table = ref<string>()
const rangeBoxStyle = ref<string>('range-box-none')
const rangeBoxPosition = reactive({
left:'',top:'',width:'',height:'',
})
const cellRange = reactive({
start:{ // 4个角的座标
a:{x:1,y:2},
b:{x:1,y:2},
c:{x:1,y:2},
d:{x:1,y:2},
},
end:{
a:{x:1,y:2},
b:{x:1,y:2},
c:{x:1,y:2},
d:{x:1,y:2},
}
})
//鼠标按下事件
const handleMouseDown = (event:any)=> {
// 记录第一个点击目标 4个角的座标 x,y 由于框选的方向不一样,所以要记录4个角的座标 x,y
cellRange.start = {
a: { x:event.target.offsetLeft, y:event.target.offsetTop },
b: { x:event.target.offsetLeft + event.target.offsetWidth, y:event.target.offsetTop},
c: { x:event.target.offsetLeft + event.target.offsetWidth, y:event.target.offsetTop + event.target.offsetHeight},
d: { x:event.target.offsetLeft, y:event.target.offsetTop + event.target.offsetHeight}
}
// 给当前元素套一层, 绿色边框的div, 并显示出来
rangeBoxPosition.left = cellRange.start.a.x + 'px' // 绿色边框的div position 定位的 left, 值绑定在 style 类属性中
rangeBoxPosition.top = cellRange.start.a.y + 'px' // 绿色边框的div position 定位的 top, 值绑定在 style 类属性中
rangeBoxPosition.width = event.target.offsetWidth + 'px' // 绿色边框的div 宽度
rangeBoxPosition.height = event.target.offsetHeight + 'px' // 绿色边框的div 高度
rangeBoxStyle.value = 'range-box-show' // 显示出来 (更改类名来显示)
const form_table = document.getElementById('form_table') as HTMLTableElement
form_table.addEventListener("mousemove", handleMouseMove) //监听鼠标移动事件
form_table.addEventListener("mouseup", handleMouseUp) //监听鼠标抬起事件
}
// 问题在这里!!,当框选, 框选大了时, 无法移动鼠标来缩小, 绿色边框的div 挡着了下面的元素,无法再监听到鼠标的移动
function handleMouseMove(event:any) {
// 根据鼠标移动的位置来调整,绿色边框的div的大小和位置:
if(event.target.id == 'select_range' || event.target.id =='form_table') return
cellRange.end = { // 当前鼠标移动到的目标位置
a: { x:event.target.offsetLeft, y:event.target.offsetTop },
b: { x:event.target.offsetLeft + event.target.offsetWidth, y:event.target.offsetTop},
c: { x:event.target.offsetLeft + event.target.offsetWidth, y:event.target.offsetTop + event.target.offsetHeight},
d: { x:event.target.offsetLeft, y:event.target.offsetTop + event.target.offsetHeight}
}
// 如果相对第一个点击元素: 水平方向和右方向移动鼠标 ,计算出 绿色边框的div 位置 和 宽高
if(cellRange.end.a.x >= cellRange.start.a.x && cellRange.end.a.y >= cellRange.start.a.y){
rangeBoxPosition.left = cellRange.start.a.x + 'px' // 绿色边框的div position 定位的 left
rangeBoxPosition.top = cellRange.start.a.y + 'px' // 绿色边框的div position 定位的 top
rangeBoxPosition.width = (cellRange.end.c.x - cellRange.start.a.x) + 'px' // 绿色边框的div 宽度
rangeBoxPosition.height = (cellRange.end.c.y - cellRange.start.a.y) + 'px' // 绿色边框的div 高度
}
console.dir(`鼠标在移动的元素${event.target.id}:`)
// event.stopPropagation()
}
function handleMouseUp() {
// rangeBoxStyle.value = 'range-box-none'
const form_table = document.getElementById('form_table') as HTMLTableElement
form_table.removeEventListener("mousemove", handleMouseMove);
form_table.removeEventListener("mouseup", handleMouseUp);
// cellRange.is_show_mask = false;
}
onMounted(() => {
// console.dir('ref-table',ref_table)
})
</script>
<style lang="scss">
@import '../../assets/css/handle';
.range-box-none{
display: none;
position: absolute;
}
.range-box-show{
border:2px solid greenyellow;
display: block;
position: absolute;
left: v-bind('rangeBoxPosition.left');
top: v-bind('rangeBoxPosition.top'); // offsetTop
width:v-bind('rangeBoxPosition.width'); // offsetLeft
height: v-bind('rangeBoxPosition.height'); // offsetLeft
}
.form-table{
margin:auto;
margin-top: 100px;
font-size: 12px;
position: relative;
// 让文字不可选
user-select: none;
-webkit-user-seletct: none;
-moz-user-seletct: none;
@include font_color('font_color2');
tr,td{
border: 1px solid rgb(188, 188, 188);
}
td{
width: 100px;
}
}
</style>