我曾仰慕的身姿,从相伴到相知。为你提笔写名诗···
摸鱼小故事
你:你人哪?
你:都快八点了,你怎么还没来。
老板:老子卖了十几年的煎饼,从来都是无拘无束自由自在,自从认识了你,第一次让我有了上班的感觉😊。
进入正题,看效果。
先看一下效果
sorry 放错了重来
所有代码
为了方便操作dom,在vue项目引入
jquery即可应用。
<template>
<div class="hello">
<table cellspacing="0" id="gridtable" align="center">
<!-- 表头 -->
<tr class="tabHead">
<th class="tabTh" width="4%">
时间
</th>
<th class="tabTh" width="4%" v-for="(item, index) in tableLists" :key="index">
{{ item.name }}
</th>
</tr>
<tr>
<tr v-for="(item, index) in regionListRow" :key="index">
<!-- 时间列 -->
<td class="dayDataTd">
{{item.dates}}时
</td>
<td class="dayDataList" id="weekList" v-for="(temp, key) in tableLists" :key="key">
{{item[temp.key]}}
</td>
</tr>
</table>
<!-- 弹出 -->
<ul class="handleBatch">
<li class="handleList" @click="reCheckOpinion()">
一号
</li>
<li class="handleList" @click="reCheckOpinion()">
二号
</li>
<li class="handleList" @click="reCheckOpinion()">
三号
</li>
<li class="handleList" @click="reCheckOpinion()">
四号
</li>
</ul>
</div>
</template>
<script>
import $ from 'jquery'
export default {
name: 'HelloWorld',
data () {
return {
tableLists: [], // 表头
regionListRow: [], // tab数据
selectedList: [] // 选中集合
}
},
created () {
this.tableLists = [
{
name: 'PM₁₀(μg/m³)',
code: '104',
key: 'pm10'
},
{
name: 'PM₂.₅(μg/m³)',
code: '105',
key: 'pm25'
},
{
name: 'SO₂(μg/m³)',
code: '100',
key: 'so2'
},
{
name: 'NO₂(μg/m³)',
code: '101',
key: 'no2'
},
{
name: 'CO(mg/m³)',
code: '103',
key: 'co'
}
]
this.regionListRow = new Array(24).fill().map((item, index) => {
return { id: '1000' + index, dates: '2022-3-10 ' + (index + 1), co: '80', no2: '20', so2: '2', pm25: '10', pm10: '23' }
})
},
mounted () {
const atPresent = {} // 按下位置记录
// 按下事件
$('#gridtable').mousedown((event) => {
// ctrl + 左
// console.log(event.target.className)
if (!(event.button === 0 && event.ctrlKey && event.target.className.indexOf('dayDataList') !== -1)) {
this.removeStyle() // 清除数据
}
if (event.target.className.indexOf('dayDataList') !== -1) {
const link = $("<span class='boxChoose'></span>").css({
border: '1px solid #666',
'background-color': 'rgba(47, 170, 228, 0.39)',
position: 'absolute',
top: event.pageY,
left: event.pageX
})
$('#gridtable').append(link)
atPresent.atPresentX = event.pageX
atPresent.atPresentY = event.pageY
}
})
// 当前事件位置
$('#gridtable').mousemove((e) => {
// const pageX = e.pageX - parseInt(atPresent.atPresentX)
// const pageY = e.pageY - parseInt(atPresent.atPresentY)
// $('.boxChoose').css({ height: pageY, width: pageX })
const pageX = e.pageX - parseInt(atPresent.atPresentX)
const pageY = e.pageY - parseInt(atPresent.atPresentY)
if (pageX >= 0 && pageY >= 0) {
$('.boxChoose').css({
width: pageX,
height: pageY
})
} else if (pageX <= 0 && pageY <= 0) {
$('.boxChoose').css({
width: Math.abs(pageX),
height: Math.abs(pageY),
top: e.pageY,
left: e.pageX
})
} else if (pageX <= 0) {
$('.boxChoose').css({
width: Math.abs(pageX),
height: Math.abs(pageY),
left: e.pageX
})
} else {
$('.boxChoose').css({
width: Math.abs(pageX),
height: Math.abs(pageY),
top: e.pageY
})
}
})
// 抬起事件
$('#gridtable').mouseup((e) => {
// 获取元素
const blockList = $('#gridtable .dayDataList')
const boxChoose = $('.boxChoose')[0]
if (!boxChoose) return
// 框定位信息
const boxChooseLeft = boxChoose.style.left.split('px')[0]
const boxChooseRight = Number(boxChooseLeft) + Number(boxChoose.style.width.split('px')[0])
const boxChooseTop = boxChoose.style.top.split('px')[0]
const boxChooseBottom = Number(boxChooseTop) + Number(boxChoose.style.height.split('px')[0])
// 批量
for (let i = 0; i < blockList.length; i++) {
// 计算每个格子的定位信息
const left = $(blockList[i]).offset().left
const right = $(blockList[i]).width() + left
const top = $(blockList[i]).offset().top
const bottom = $(blockList[i]).height() + top
// 判断每个块是否被遮罩盖住(即选中)
const oneLine = boxChooseLeft >= left && right >= boxChooseRight
const leftFlag = boxChooseLeft <= left && left <= boxChooseRight
const rightFlag = boxChooseLeft <= right && right <= boxChooseRight
const single = boxChooseTop >= top && bottom >= boxChooseBottom
const topFlag = boxChooseTop <= top && top <= boxChooseBottom
const bottomFlag = boxChooseTop <= bottom && bottom <= boxChooseBottom
if ((oneLine || leftFlag || rightFlag) && (single || topFlag || bottomFlag)) {
let cow = true
this.selectedList.forEach((element, index) => {
if (element === blockList[i]) {
$(blockList[i]).removeClass('treeBoxStyles')
this.selectedList.splice(index, 1)
cow = false
}
})
if (cow) {
$(blockList[i]).addClass('treeBoxStyles')
this.selectedList.push(blockList[i])
}
}
}
// console.log(this.selectedList)
// 显示弹出
$('.handleBatch').css({
display: 'block',
top: $(window).height() - $('.handleBatch').height() > e.pageY ? e.pageY : e.pageY - $('.handleBatch').height(),
left: Number(boxChoose.style.left.split('px')[0]) + Number(boxChoose.style.width.split('px')[0]) + 30
})
$('.boxChoose').remove()
// 批量操作显示
})
// 点击表格意外删除
$(window).click(e => {
console.log(e.target.className)
if (e.target.className.indexOf('dayDataList') === -1) {
this.removeStyle()
}
})
},
methods: {
// 清楚样式
removeStyle () {
this.selectedList = []
$('.boxChoose').remove()
$('.handleBatch').css({ display: 'none' })
$('#gridtable .dayDataList').removeClass('treeBoxStyles')
},
reCheckOpinion () {
const dataResult = []
for (let i = 0; i < this.selectedList.length; i++) {
const column = $(this.selectedList[i].parentNode).prevAll().length - 2 // 行索引
const line = $(this.selectedList[i].cellIndex)[0] - 1 // 列索引
dataResult.push({
ids: this.regionListRow[column].id,
date: this.regionListRow[column].dates,
code: this.tableLists[line].code,
name: this.tableLists[line].name
})
}
console.log('请求数据', dataResult)
}
}
}
</script>
<style>
.hello {
-moz-user-select: none; /*火狐*/
-webkit-user-select: none; /*webkit浏览器*/
-ms-user-select: none; /*IE10*/
-khtml-user-select: none; /*早期浏览器*/
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.582);
}
#gridtable {
user-select: none;
margin-top: 30px;
height: 90%;
width: 1000px;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
.tabHead {
background-color: #f3f3f3;
}
.tabTh {
border-right: 1px solid #ccc;
font-weight: 400;
}
.dayDataTd {
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.dayDataList {
margin: 0;
padding: 0;
text-align: center;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
cursor: pointer;
}
/* 背景颜色 */
.treeBoxStyles {
background-color: #00cdff !important;
}
.handleBatch {
transition: 1s;
z-index: 999;
position: absolute;
top: 0;
width: 140px;
border: 1px solid rgb(163, 163, 163);
margin: 0;
padding: 0;
cursor: pointer;
display: none;
background-color: #f0f0f0c7;
border-radius: 3px;
}
.handleBatch li {
list-style: none;
color: rgb(114, 113, 113);
transition: 0.3s;
line-height: 20px;
font-size: 15px;
padding: 5px 5px;
text-align: center;
border-bottom: 1px solid #ccc;
}
.handleBatch li:hover {
background-color: rgb(224, 223, 223);
}
</style>
说一下实现思路
使用jq,不代表只能用jq实现。主要是思路有了,实现举不胜举。 1.首先要知道三个事件
鼠标按下mousedown,鼠标移动mousemove,鼠标抬起mouseup。当鼠标按下的时候,创建jq
创建一个元素,获取鼠标距离浏览器坐标位置,赋值给元素top、left。
当鼠标移动的时候,获取鼠标距离浏览器坐标位置,持续给元素的宽高赋值。
当鼠标抬起的时候,记录当前元素距离浏览器坐标位置和元素宽高。
这三个事件触发后,就可以获取到创建元素盒子的top,left,right,bottom。
2. 获取表格内所有小格子获取每一个小各子距离top,left,right,bottom。
3.计算符合要求的小格子
- 横轴判断
看一下,我们框选小格子的时候有这四种情况满足要求 - 竖轴判断 竖轴也是一样的道理。
- 计算公式
const oneLine = 框Left >= 格left && 格right >= 框Right
const leftFlag = 框Left <= 格left && 格left <= 框Right
const rightFlag = 框Left <= 格right && 格right <= 框Right
const single = 框Top >= 格top && 格bottom >= 框Bottom
const topFlag = 框Top <= 格top && 格top <= 框Bottom
const bottomFlag = 框Top <= 格bottom && 格bottom <= 框Bottom
if ((oneLine || leftFlag || rightFlag) && (single || topFlag || bottomFlag)) {
// 满足的元素
}
3.获取小格子对于的行列索引
const column = $(元素.parentNode).prevAll().length - 2 // 行索引
const line = $(元素.cellIndex)[0] - 1 // 列索引
拿到索索引后,就可以通过索引查询数组中对于的数据了。