html冷门标签,圈选.html · 衣沾不足惜/前端冷门组件.工具库 - Gitee.com

Document

html,

body {

margin: 0;

}

.wrapper {

position: relative;

left: 20%;

top: 100px;

width: 600px;

height: 400px;

border: 1px solid red;

text-align: center;

}

.test {

position: absolute;

width: 200px;

height: 200px;

background: blue;

}

/* 避免残留事件 点到蒙层上 */

.viewingArea {

pointer-events: none;

}

.wrapper .item {

margin: 0 auto;

width: 80%;

margin-top: 10px;

height: 25px;

background: rgba(0, 0, 0, 0.08);

user-select: none;

border: 1px solid black;

}

1
2
3
4
4
4
4

/*

* 圈选

*

*/

function boxSelection(scopedElement = document.body, targetAttrName = 'target', oEvent = {}) {

let startPageX = 0

let startPageY = 0

let currentPageX = 0

let currentPageY = 0

let oViewingArea = null

let scopedElementInfo = {}

function initoViewingArea() {

startPageX = 0

startPageY = 0

currentPageX = 0

currentPageY = 0

oViewingArea = document.createElement('div')

oViewingArea.className = 'viewingArea'

oViewingArea.style.cssText = 'position:absolute;background:rgba(0, 0, 255, 0.1);pointer-events: none;border:1px solid rgba(0, 0, 255, 0.5)'

document.body.appendChild(oViewingArea)

}

function move(e) {

currentPageX = e.pageX

currentPageY = e.pageY

let disX = currentPageX - startPageX

let disY = currentPageY - startPageY

let x = 0

let y = 0

// 蒙层 和 scopedElement 的间距

let rectDisX = 0

let rectDisY = 0

let dir = {

x: disX >= 0 ? 'left' : 'right',

y: disY >= 0 ? 'top' : 'bottom'

}

// 设置宽高 并限定范围

let w = Math.abs(disX)

let h = Math.abs(disY)

// 换算 绝对定位 left 为 right(因为需要修正宽度延伸方向)

// left 即为 鼠标按下的坐标 , right 为 文档宽度 - 鼠标按下的坐标

if (dir.x === 'right') {

x = document.documentElement.scrollWidth - startPageX

// scopedElement 右边X坐标 - 蒙层 x

// 统一从left计算 不使用 x了

rectDisX = startPageX - scopedElementInfo.left

if (w > rectDisX) {

w = rectDisX - 2

}

} else {

x = startPageX

// 蒙层的 left - scopedElement 的left

rectDisX = x - scopedElementInfo.left

if (rectDisX + w > scopedElementInfo.width) {

w = scopedElementInfo.width - rectDisX - 2 //去掉边框 2px

}

}

if (dir.y === 'bottom') {

y = document.documentElement.scrollHeight - startPageY

// bottom - 开始y

if (scopedElementInfo.height + scopedElementInfo.top - startPageY + h > scopedElementInfo.height) {

h = startPageY - scopedElementInfo.top - 2

}

} else {

y = startPageY

if (y + h > scopedElementInfo.height + scopedElementInfo.top) {

h = scopedElementInfo.height + scopedElementInfo.top - y - 2

}

}

// 限定选择蒙层宽高 , 开始坐标 + 宽度 不能超越 scopedElement的宽度 ,超过后 ,只给开始坐标到边界的距离为宽度

// x y 已经处理过 right 和 left的情况

// 蒙层和scopedElement的间距 + 蒙层的宽度 需要小于 scopedElement的宽度

setViewingArea({ w, h, x: x, y: y }, dir)

let targets = scopedElement.querySelectorAll(`[${targetAttrName}]`)

targets.forEach((item) => {

if (isIntersect(oViewingArea, item)) {

oEvent.onSelected && oEvent.onSelected({ el: item, selected: true })

} else {

oEvent.onSelected && oEvent.onSelected({ el: item, selected: false })

}

})

oEvent.onMove && oEvent.onMove(e)

}

function mouseUp(e) {

if (oViewingArea) {

// 立即调用 删除选择区 / 解除事件, 避免删除蒙层dom过慢鼠标再次点中选中蒙层

oViewingArea.style.display = 'none';

document.body.removeChild(oViewingArea)

}

document.removeEventListener('mousemove', move)

document.removeEventListener('mouseup', mouseUp)

oViewingArea = null

oEvent.onCancel && oEvent.onCancel(e)

}

function setViewingArea(params = { w: 0, h: 0, x: 0, y: 0 }, dir = { x: 'left', y: 'top' }) {

if (dir.x === 'right') {

oViewingArea.style.left = 'initial'

} else {

oViewingArea.style.right = 'initial'

}

if (dir.y === 'bottom') {

oViewingArea.style.top = 'initial'

} else {

oViewingArea.style.bottom = 'initial'

}

oViewingArea.style[dir.x] = params.x + 'px'

oViewingArea.style[dir.y] = params.y + 'px'

!isNaN(params.w) ? oViewingArea.style.width = params.w + 'px' : null

!isNaN(params.h) ? oViewingArea.style.height = params.h + 'px' : null

}

function isIntersect(elA, elB) {

let A = elA.getBoundingClientRect()

let B = elB.getBoundingClientRect()

// 判断不相交 在右边 , 右比左还小 ,b在左

if (A.left > B.right || A.right < B.left || A.bottom < B.top || A.top > B.bottom) {

return false

}

return true

}

scopedElement.addEventListener('mousedown', (e) => {

mouseUp()

initoViewingArea()

startPageX = e.pageX

startPageY = e.pageY

scopedElementInfo = scopedElement.getBoundingClientRect()

setViewingArea({ w: 0, h: 0, x: startPageX, y: startPageY })

document.addEventListener('mousemove', move)

document.addEventListener('mouseup', mouseUp)

e.stopPropagation()

})

}

boxSelection(document.querySelector('.wrapper'), 'target', {

onMove: function (e) {

},

onSelected: function (item) {

if (item.selected) {

item.el.style.border = '1px solid red'

item.el.style.color = 'red'

} else {

item.el.style.border = '1px solid black'

item.el.style.color = 'black'

}

},

onCancel: function () {

}

})

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值