Skip to content

Commit

Permalink
feat(utils): 新增 isElementVisible
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Sep 30, 2022
1 parent b448688 commit 16c149c
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export * from './inWechatWebView'
export * from './isBlobUrl'
export * from './isChineseIDCardNumber'
export * from './isDataUrl'
export * from './isElementVisible'
export * from './isNumeric'
export * from './isPossibleChineseMobilePhoneNumber'
export * from './isPromiseLike'
Expand Down
29 changes: 29 additions & 0 deletions src/utils/isElementVisible.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { isElementVisible } from './isElementVisible'

describe('isElementVisible', () => {
test('ok', () => {
const el = document.createElement('div')
expect(isElementVisible(el)).toBe(false)
document.body.appendChild(el)
expect(isElementVisible(el)).toBe(true)

el.style.display = 'none'
expect(isElementVisible(el)).toBe(false)
el.style.display = 'block'
expect(isElementVisible(el)).toBe(true)

el.style.opacity = '0'
expect(isElementVisible(el)).toBe(false)
el.style.opacity = '0.1'
expect(isElementVisible(el)).toBe(true)

el.style.visibility = 'hidden'
expect(isElementVisible(el)).toBe(false)
el.style.visibility = 'visible'
expect(isElementVisible(el)).toBe(true)

const el2 = document.createElement('div')
el.appendChild(el2)
expect(isElementVisible(el2)).toBe(true)
})
})
61 changes: 61 additions & 0 deletions src/utils/isElementVisible.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// ref: https://github.com/LuizAsFight/is-element-visible/blob/master/src/index.js

// @ts-nocheck
const isOverflowHidden = el => getComputedStyle(el, 'overflow') === 'hidden'
const getComputedStyle = (el, property) => {
const computedStyle = window.getComputedStyle
? document.defaultView.getComputedStyle(el, null)
: el.currentStyle

return property ? computedStyle[property] : computedStyle
}
const isOnDocument = el => {
while ((el = el.parentNode)) {
if (el === document) return true
}
return false
}
const isVisibleDueToOverflow = el => {
const elPositioning = getPositioning(el.getBoundingClientRect())

while ((el = el.parentNode)) {
if (el.nodeType !== 9 && isOverflowHidden(el)) {
const parentElPositioning = getPositioning(el.getBoundingClientRect())

const isElInsideParentRectX =
elPositioning.startX >= parentElPositioning.startX &&
elPositioning.endX <= parentElPositioning.endX
const isElInsideParentRectY =
elPositioning.startY >= parentElPositioning.startY &&
elPositioning.endY <= parentElPositioning.endY

if (!isElInsideParentRectX || !isElInsideParentRectY) return false
}
}

return true
}
const getPositioning = ({ x, width, y, height }) => ({
startX: parseInt(x),
endX: parseInt(x) + parseInt(width),
startY: parseInt(y),
endY: parseInt(y) + parseInt(height),
})

/**
* 检查 HTML 元素是否可见。
*
* @param el 要检查的 HTML 元素
*/
export function isElementVisible(el: HTMLElement): boolean {
if (!isOnDocument(el)) return false

const isHiddenDueToOpacity = getComputedStyle(el, 'opacity') === '0'
const isHiddenDueToDisplay = getComputedStyle(el, 'display') === 'none'
const isHiddenDueToVisibility =
getComputedStyle(el, 'visibility') === 'hidden'
if (isHiddenDueToOpacity || isHiddenDueToDisplay || isHiddenDueToVisibility)
return false

return isVisibleDueToOverflow(el)
}

0 comments on commit 16c149c

Please sign in to comment.