Skip to content

Commit

Permalink
Added a new test case and refactored functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
sainthkh committed Jan 3, 2020
1 parent 9fd8062 commit 8fb9801
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 81 deletions.
57 changes: 30 additions & 27 deletions packages/driver/src/dom/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ const identityMatrix3D: Matrix3D = [
0, 0, 0, 1,
]

// It became 1e-5 from 1e-10. Because 30deg + 30deg + 30deg is 6.0568e-7 and it caused a false negative.
const TINY_NUMBER = 1e-5

const nextPreserve3d = (i: number, list: TransformInfo[]) => {
return i + 1 < list.length &&
list[i + 1].transformStyle === 'preserve-3d'
Expand All @@ -86,44 +89,38 @@ const finalNormal = (startIndex: number, list: TransformInfo[]) => {
return normal
}

// This function uses a simplified version of backface culling.
// https://en.wikipedia.org/wiki/Back-face_culling
//
// We defined view vector, (0, 0, -1), - eye to screen.
// and default normal vector of an element, (0, 0, 1)
// When dot product of them are >= 0, item is visible.
const elIsBackface = (list: TransformInfo[]) => {
if (1 < list.length && list[1].transformStyle === 'preserve-3d') {
// When the direct parent of the target has style, preserve-3d
if (list.length > 1 && list[1].transformStyle === 'preserve-3d') {
// When the target is backface-invisible a2-1-1 ~ a2-1-4
if (list[0].backfaceVisibility === 'hidden') {
let normal = finalNormal(0, list)

if (checkBackface(normal)) {
return true
}
} else {
if (list[1].backfaceVisibility === 'visible') {
const { width, height } = list[0].el.getBoundingClientRect()

if (width === 0 || height === 0) {
return true
// When the direct parent of the target is backface-invisible
if (list[1].backfaceVisibility === 'hidden') {
// If it is not none, it is visible. Check a2-3-1
if (list[0].transform === 'none') {
let normal = finalNormal(1, list)

if (checkBackface(normal)) {
return true
}
}
} else {
if (list[0].transform !== 'none') {
// TODO: check 90 deg.
return false
}

let normal = finalNormal(1, list)
}

if (checkBackface(normal)) {
return true
}
// Check 90deg a2-2-3, a2-2-4.
let normal = finalNormal(0, list)

return false
}
return isElementOrthogonalWithView(normal)
}
} else {
for (let i = 0; i < list.length; i++) {
// Ignore preserve-3d when it is not a direct parent.
// Why? -> https://github.com/cypress-io/cypress/pull/5916
if (i > 0 && list[i].transformStyle === 'preserve-3d') {
continue
}
Expand All @@ -141,6 +138,12 @@ const elIsBackface = (list: TransformInfo[]) => {
return false
}

// This function uses a simplified version of backface culling.
// https://en.wikipedia.org/wiki/Back-face_culling
//
// We defined view vector, (0, 0, -1), - eye to screen.
// and default normal vector of an element, (0, 0, 1)
// When dot product of them are >= 0, item is visible.
const checkBackface = (normal: Vector3) => {
// Simplified dot product.
// viewVector[0] and viewVector[1] are always 0. So, they're ignored.
Expand All @@ -149,8 +152,8 @@ const checkBackface = (normal: Vector3) => {
// Because of the floating point number rounding error,
// cos(90deg) isn't 0. It's 6.12323e-17.
// And it sometimes causes errors when dot product value is something like -6.12323e-17.
// So, we're setting the dot product result to 0 when its absolute value is less than 1e-10(10^-10).
if (Math.abs(dot) < 1e-10) {
// So, we're setting the dot product result to 0 when its absolute value is less than SMALL_NUMBER(10^-10).
if (Math.abs(dot) < TINY_NUMBER) {
dot = 0
}

Expand Down Expand Up @@ -276,5 +279,5 @@ const isElementOrthogonalWithView = (normal: Vector3) => {
// [0] and [1] are always 0
const dot = viewVector[2] * normal[2]

return Math.abs(dot) <= 1e-10
return Math.abs(dot) < TINY_NUMBER
}
67 changes: 30 additions & 37 deletions packages/driver/test/cypress/fixtures/issue-5682.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,91 +114,84 @@ <h4>Parent rotate 90deg + Child rotate 190deg with backface-invisible</h4>
<div>
<h2>CASE 2: Direct parent preserve-3d elements</h2>

<h4>a2-1: Parent Flipped visible + target hidden</h4>
<h4>a2-1-1: Parent Flipped visible + target hidden</h4>
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(180deg)">
Parent rotateX(180deg)
<div id="a2-1" class="target" style="backface-visibility: hidden;">No transform</div>
<div id="a2-1-1" class="target" style="backface-visibility: hidden;">No transform</div>
</div>

<h4>a2-2: Parents rotated 60deg each visible + target hidden</h4>
<h4>a2-1-2: Parents rotated 60deg each visible + target hidden</h4>
<div class="grandparent" style="transform-style: preserve-3d; transform: rotateX(60deg)">
Grandparent rotateX(60deg)
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(60deg)">
Parent rotateX(60deg)
<div id="a2-2" class="target" style="backface-visibility: hidden;">No transform</div>
<div id="a2-1-2" class="target" style="backface-visibility: hidden;">No transform</div>
</div>
</div>

<h4>a2-3: Parent Flipped hidden + target hidden</h4>
<h4>a2-1-3: Parent Flipped hidden + target hidden</h4>
<div class="parent" style="backface-visibility: hidden; transform-style: preserve-3d; transform: rotateX(180deg)">
Parent rotateX(180deg)
<div id="a2-3" class="target" style="backface-visibility: hidden; transform: rotateX(0deg);">No transform</div>
<div id="a2-1-3" class="target" style="backface-visibility: hidden; transform: rotateX(0deg);">No transform</div>
</div>

<h4>a2-4: Parent 60deg visible + target hidden 60deg</h4>
<h4>a2-1-4: Parent 60deg visible + target hidden 60deg</h4>
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(60deg)">
Parent rotateX(60deg)
<div id="a2-4" class="target" style="backface-visibility: hidden; transform: rotateX(60deg)">rotateX(60deg)</div>
<div id="a2-1-4" class="target" style="backface-visibility: hidden; transform: rotateX(60deg)">rotateX(60deg)</div>
</div>

<h4>a2-5: Parent Flipped visible + target visible</h4>
<h4>a2-2-1: Parent Flipped visible + target visible</h4>
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(180deg)">
Parent rotateX(180deg)
<div id="a2-5" class="target">No transform</div>
<div id="a2-2-1" class="target">No transform</div>
</div>

<h4>a2-6: Parents Flipped visible + target visible</h4>
<h4>a2-2-2: Parents Flipped visible + target visible</h4>
<div class="grandparent" style="transform-style: preserve-3d; transform: rotateX(60deg)">
Parent rotateX(60deg)
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(60deg)">
Parent rotateX(60deg)
<div id="a2-6" class="target">No transform</div>
<div id="a2-2-2" class="target">No transform</div>
</div>
</div>

<h4>a2-7: Parents Flipped 45deg visible + target visible</h4>
<div class="grandparent" style="transform-style: preserve-3d; transform: rotateX(45deg)">
<h4>a2-2-3: Parents rotated 45deg visible + target visible</h4>
<div class="grandparent" style="backface-visibility: hidden; transform-style: preserve-3d; transform: rotateX(45deg)">
Grandparent rotateX(45deg)
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(45deg)">
Parent rotateX(45deg)
<div id="a2-7" class="target">No transform</div>
<div id="a2-2-3" class="target">No transform</div>
</div>
</div>

<h4>a2-8: Parent Flipped hidden + identity transform</h4>
<h4>a2-2-4: Parents rotated 30deg visible + target visible 30deg</h4>
<div class="grandparent" style="backface-visibility: hidden; transform-style: preserve-3d; transform: rotateX(30deg)">
Grandparent rotateX(30deg)
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(30deg)">
Parent rotateX(30deg)
<div id="a2-2-4" class="target" style="transform: rotateX(30deg)">rotateX(30deg)</div>
</div>
</div>

<h4>a2-3-1: Parent Flipped hidden + identity transform</h4>
<div class="parent" style="transform-style: preserve-3d; backface-visibility: hidden; transform: rotateX(180deg)">
Parent rotateX(180deg)
<div id="a2-8" class="target" style="transform: rotateX(0deg)">Identity transform</div>
<div id="a2-3-1" class="target" style="transform: rotateX(0deg)">Identity transform</div>
</div>

<h4>a2-9: Parent Flipped hidden + no transform</h4>
<h4>a2-3-2: Parent Flipped hidden + no transform</h4>
<div class="parent" style="transform-style: preserve-3d; backface-visibility: hidden; transform: rotateX(180deg)">
Parent rotateX(180deg)
<div id="a2-9" class="target">No transform</div>
<div id="a2-3-2" class="target">No transform</div>
</div>

<h4>a2-10: Grandparent rotated 45deg + parent rotated 45deg hidden + target visible</h4>
<h4>a2-3-3: Grandparent rotated 45deg + parent rotated 45deg hidden + target visible</h4>
<div class="grandparent" style="transform-style: preserve-3d; transform: rotateX(45deg)">
Grandparent rotateX(45deg)
<div class="parent" style="backface-visibility: hidden; transform-style: preserve-3d; transform: rotateX(45deg)">
Parent rotateX(45deg)
<div id="a2-10" class="target">No transform</div>
</div>
</div>
</div>

<div>
<h2>CASE 3: Others</h2>

<h4>flat after preserve-3d</h4>
<div class="grandgrandparent" style="backface-visibility: hidden; transform: rotateX(180deg);">
Grandgrandparent rotateX(180deg)
<div class="grandparent" style="transform-style: preserve-3d; transform: rotateX(30deg)">
Grandparent rotateX(30deg)
<div class="parent" style="transform-style: preserve-3d; transform: rotateX(30deg)">
Parent rotateX(30deg)
<div id="a3-1" class="target" style="backface-visibility: hidden;">No transform</div>
</div>
<div id="a2-3-3" class="target">No transform</div>
</div>
</div>
</div>
Expand Down
29 changes: 12 additions & 17 deletions packages/driver/test/cypress/integration/issues/5682_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,25 @@ describe('issue #5682 - backface visibility', () => {
})
})

describe('CASE 2: No transform after preserve-3d', () => {
describe('CASE 2: when direct parents have preserve-3d', () => {
it('target hidden + parents', () => {
cy.get('#a2-1').should('not.be.visible')
cy.get('#a2-2').should('not.be.visible')
cy.get('#a2-3').should('not.be.visible')
cy.get('#a2-4').should('not.be.visible')
cy.get('#a2-1-1').should('not.be.visible')
cy.get('#a2-1-2').should('not.be.visible')
cy.get('#a2-1-3').should('not.be.visible')
cy.get('#a2-1-4').should('not.be.visible')
})

it('target visible + parent visible', () => {
cy.get('#a2-5').should('be.visible')
cy.get('#a2-6').should('be.visible')
cy.get('#a2-7').should('not.be.visible')
cy.get('#a2-2-1').should('be.visible')
cy.get('#a2-2-2').should('be.visible')
cy.get('#a2-2-3').should('not.be.visible')
cy.get('#a2-2-4').should('not.be.visible')
})

it('target visible + parent hidden', () => {
cy.get('#a2-8').should('be.visible')
cy.get('#a2-9').should('not.be.visible')
cy.get('#a2-10').should('not.be.visible')
})
})

describe('CASE 3: Others', () => {
it('ignores and returns visible when flat appears after preserve-3d', () => {
cy.get('#a3-1').should('be.visible')
cy.get('#a2-3-1').should('be.visible')
cy.get('#a2-3-2').should('not.be.visible')
cy.get('#a2-3-3').should('not.be.visible')
})
})

Expand Down

0 comments on commit 8fb9801

Please sign in to comment.