Skip to content

Commit

Permalink
Fixed backface visibility. (#5591)
Browse files Browse the repository at this point in the history
* Fixed backface visibility.

* Show reason.

* Reorganized logic.
  • Loading branch information
sainthkh authored and flotwig committed Nov 8, 2019
1 parent 6c39d2e commit ab8957a
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
46 changes: 46 additions & 0 deletions packages/driver/src/dom/visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ const isHidden = (el, name = 'isHidden()') => {
return true // is hidden
}

if (elIsBackface($el)) {
return true
}

// we do some calculations taking into account the parents
// to see if its hidden by a parent
if (elIsHiddenByAncestors($el)) {
Expand Down Expand Up @@ -112,6 +116,40 @@ const elHasVisibilityHidden = ($el) => {
return $el.css('visibility') === 'hidden'
}

const numberRegex = /-?[0-9]+(?:\.[0-9]+)?/g
// This is a simplified version of backface culling.
// https://en.wikipedia.org/wiki/Back-face_culling
//
// We defined view normal vector, (0, 0, -1), - eye to screen.
// and default normal vector, (0, 0, 1)
// When dot product of them are >= 0, item is visible.
const elIsBackface = ($el) => {
const el = $el[0]
const style = getComputedStyle(el)
const backface = style.getPropertyValue('backface-visibility')
const backfaceInvisible = backface === 'hidden'
const transform = style.getPropertyValue('transform')

if (!backfaceInvisible || !transform.startsWith('matrix3d')) {
return false
}

const m3d = transform.substring(8).match(numberRegex)
const defaultNormal = [0, 0, -1]
const elNormal = findNormal(m3d)
// Simplified dot product.
// [0] and [1] are always 0
const dot = defaultNormal[2] * elNormal[2]

return dot >= 0
}

const findNormal = (m) => {
const length = Math.sqrt(+m[8] * +m[8] + +m[9] * +m[9] + +m[10] * +m[10])

return [+m[8] / length, +m[9] / length, +m[10] / length]
}

const elHasVisibilityCollapse = ($el) => {
return $el.css('visibility') === 'collapse'
}
Expand Down Expand Up @@ -272,6 +310,10 @@ const elIsHiddenByAncestors = function ($el, $origEl = $el) {
return !elDescendentsHavePositionFixedOrAbsolute($parent, $origEl)
}

if (elIsBackface($parent)) {
return true
}

// continue to recursively walk up the chain until we reach body or html
return elIsHiddenByAncestors($parent, $origEl)
}
Expand Down Expand Up @@ -388,6 +430,10 @@ const getReasonIsHidden = function ($el) {
return `This element '${node}' is not visible because it has an effective width and height of: '${width} x ${height}' pixels.`
}

if (elIsBackface($el)) {
return `This element '${node}' is not visible because it is rotated and its backface is hidden.`
}

if ($parent = parentHasNoOffsetWidthOrHeightAndOverflowHidden($el.parent())) {
parentNode = $elements.stringify($parent, 'short')
width = elOffsetWidth($parent)
Expand Down
45 changes: 43 additions & 2 deletions packages/driver/test/cypress/integration/dom/visibility_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -820,12 +820,53 @@ describe('src/cypress/dom/visibility', () => {
})

describe('css backface-visibility', () => {
describe('element visibility by backface-visibility and rotation', () => {
const add = (el) => {
return $(el).appendTo(cy.$$('body'))
}

it('is visible when there is no transform', () => {
const el = add('<div>No transform</div>')

expect(el).to.be.visible
})

it('is visible when an element is rotated < 90 degrees', () => {
const el = add('<div style="backface-visibility: hidden; transform: rotateX(45deg)">rotateX(45deg)</div>')

expect(el).to.be.visible

const el2 = add('<div style="backface-visibility: hidden; transform: rotateY(-45deg)">rotateY(-45deg)</div>')

expect(el2).to.be.visible
})

it('is invisible when an element is rotated > 90 degrees', () => {
const el = add('<div style="backface-visibility: hidden; transform: rotateX(135deg)">rotateX(135deg)</div>')

expect(el).to.be.hidden

const el2 = add('<div style="backface-visibility: hidden; transform: rotateY(-135deg)">rotateY(-135deg)</div>')

expect(el2).to.be.hidden
})

it('is invisible when an element is rotated in 90 degrees', () => {
const el = add('<div style="backface-visibility: hidden; transform: rotateX(90deg)">rotateX(90deg)</div>')

expect(el).to.be.hidden

const el2 = add('<div style="backface-visibility: hidden; transform: rotateY(-90deg)">rotateY(-90deg)</div>')

expect(el2).to.be.hidden
})
})

it('is visible when backface not visible', function () {
expect(this.$parentsWithBackfaceVisibilityHidden.find('#front')).to.be.visible
})

// TODO: why is this skipped?
it.skip('is hidden when backface visible', function () {
it('is hidden when backface visible', function () {
expect(this.$parentsWithBackfaceVisibilityHidden.find('#back')).to.be.hidden
})
})
Expand Down

4 comments on commit ab8957a

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on ab8957a Nov 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.6.1/linux-x64/circle-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-188705/cypress.zip
npm install https://cdn.cypress.io/beta/npm/3.6.1/circle-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-188690/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on ab8957a Nov 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppVeyor has built the win32 ia32 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

set CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.6.1/win32-ia32/appveyor-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-28726363/cypress.zip
npm install https://cdn.cypress.io/beta/binary/3.6.1/win32-ia32/appveyor-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-28726363/cypress.zip

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on ab8957a Nov 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppVeyor has built the win32 x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

set CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.6.1/win32-x64/appveyor-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-28726363/cypress.zip
npm install https://cdn.cypress.io/beta/binary/3.6.1/win32-x64/appveyor-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-28726363/cypress.zip

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on ab8957a Nov 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.6.1/darwin-x64/circle-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-188757/cypress.zip
npm install https://cdn.cypress.io/beta/npm/3.6.1/circle-develop-ab8957a3ba353c6db684a4b29eb816680fe3df35-188707/cypress.tgz

Please sign in to comment.