Skip to content

Commit

Permalink
Merge pull request #1321 from framer/fix/remove-padding-from-height-m…
Browse files Browse the repository at this point in the history
…easurement

Removing padding from measurement when converting width/height values
  • Loading branch information
mergetron[bot] committed Nov 2, 2021
2 parents 0a74169 + 5032978 commit 9e5ec0c
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,8 +4,11 @@ Framer Motion adheres to [Semantic Versioning](http://semver.org/).

## [5.0.2] 2021-11-02

### Fixed

- Convert x/y from percent to pixels before drag. [Issue](https://github.com/framer/motion/issues/424)
- Dynamic functions passed to `controls.start()` can now return variant names. [Issue](https://github.com/framer/motion/issues/503)
- Factors in padding when measuring elements for `width`/`height` unit conversion. [Issue](https://github.com/framer/motion/issues/368)

## [5.0.1] 2021-11-01

Expand Down
59 changes: 59 additions & 0 deletions dev/examples/Animation-height-auto-padding.tsx
@@ -0,0 +1,59 @@
import * as React from "react"
import { useState } from "react"
import { motion, AnimatePresence } from "@framer"

export const App = () => {
const [isExpanded, setExpanded] = useState(false)

return (
<div className="example-container">
<AnimatePresence>
{isExpanded ? (
<motion.div
animate={{
height: "auto",
opacity: 1,
paddingTop: 30,
paddingBottom: 30,
}}
exit={{
height: 0,
opacity: 0,
paddingTop: 0,
paddingBottom: 0,
}}
initial={{
height: 0,
opacity: 0,
paddingTop: 0,
paddingBottom: 0,
}}
style={{ background: "white", width: 200 }}
>
Test
</motion.div>
) : null}
</AnimatePresence>
<button style={{}} onClick={() => setExpanded(!isExpanded)}>
Toggle
</button>
<style>{styles}</style>
</div>
)
}

const styles = `body {
background: white!important;
background-repeat: no-repeat;
padding: 0;
margin: 0;
display: flex;
justify-content: flex-start;
align-items: flex-start;
}
.example-container {
width: 320px;
padding: 20px;
}
}`
25 changes: 25 additions & 0 deletions src/render/dom/utils/__tests__/unit-conversion.test.ts
@@ -0,0 +1,25 @@
import { positionalValues } from "../unit-conversion"

describe("Unit conversion", () => {
test("Correctly factors in padding when measuring width/height", () => {
const testDimensions = {
x: { min: 0, max: 100 },
y: { min: 0, max: 300 },
}
expect(
positionalValues.width(testDimensions, { paddingLeft: "50px" })
).toBe(50)

expect(
positionalValues.width(testDimensions, { paddingRight: "25px" })
).toBe(75)

expect(
positionalValues.height(testDimensions, { paddingTop: "50px" })
).toBe(250)

expect(
positionalValues.height(testDimensions, { paddingBottom: "25px" })
).toBe(275)
})
})
38 changes: 20 additions & 18 deletions src/render/dom/utils/unit-conversion.ts
Expand Up @@ -93,20 +93,24 @@ function removeNonTranslationalTransform(visualElement: VisualElement) {
return removedTransforms
}

const positionalValues: { [key: string]: GetActualMeasurementInPixels } = {
// Dimensions
width: ({ x }) => x.max - x.min,
height: ({ y }) => y.max - y.min,

top: (_bbox, { top }) => parseFloat(top as string),
left: (_bbox, { left }) => parseFloat(left as string),
bottom: ({ y }, { top }) => parseFloat(top as string) + (y.max - y.min),
right: ({ x }, { left }) => parseFloat(left as string) + (x.max - x.min),

// Transform
x: getTranslateFromMatrix(4, 13),
y: getTranslateFromMatrix(5, 14),
}
export const positionalValues: { [key: string]: GetActualMeasurementInPixels } =
{
// Dimensions
width: ({ x }, { paddingLeft = "0", paddingRight = "0" }) =>
x.max - x.min - parseFloat(paddingLeft) - parseFloat(paddingRight),
height: ({ y }, { paddingTop = "0", paddingBottom = "0" }) =>
y.max - y.min - parseFloat(paddingTop) - parseFloat(paddingBottom),

top: (_bbox, { top }) => parseFloat(top as string),
left: (_bbox, { left }) => parseFloat(left as string),
bottom: ({ y }, { top }) => parseFloat(top as string) + (y.max - y.min),
right: ({ x }, { left }) =>
parseFloat(left as string) + (x.max - x.min),

// Transform
x: getTranslateFromMatrix(4, 13),
y: getTranslateFromMatrix(5, 14),
}

const convertChangedValueTypes = (
target: TargetWithKeyframes,
Expand All @@ -116,9 +120,7 @@ const convertChangedValueTypes = (
const originBbox = visualElement.measureViewportBox()
const element = visualElement.getInstance()
const elementComputedStyle = getComputedStyle(element)
const { display, top, left, bottom, right, transform } =
elementComputedStyle
const originComputedStyle = { top, left, bottom, right, transform }
const { display } = elementComputedStyle

// If the element is currently set to display: "none", make it visible before
// measuring the target bounding box
Expand All @@ -140,7 +142,7 @@ const convertChangedValueTypes = (
const value = visualElement.getValue(key) as MotionValue
setAndResetVelocity(
value,
positionalValues[key](originBbox, originComputedStyle)
positionalValues[key](originBbox, elementComputedStyle)
)
target[key] = positionalValues[key](targetBbox, elementComputedStyle)
})
Expand Down

0 comments on commit 9e5ec0c

Please sign in to comment.