From 92bbeb192f73dd6ab120c1935effa98fde516a28 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 1 Nov 2021 14:34:34 +0100 Subject: [PATCH 1/6] Removing padding when converting width/height values --- .../Animation-height-auto-padding.tsx | 145 ++++++++++++++++++ src/render/dom/utils/unit-conversion.ts | 12 +- 2 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 dev/examples/Animation-height-auto-padding.tsx diff --git a/dev/examples/Animation-height-auto-padding.tsx b/dev/examples/Animation-height-auto-padding.tsx new file mode 100644 index 0000000000..b5dd94d562 --- /dev/null +++ b/dev/examples/Animation-height-auto-padding.tsx @@ -0,0 +1,145 @@ +import * as React from "react" +import { useState } from "react" +import { motion, AnimatePresence } from "@framer" +import { mix } from "popmotion" + +export const App = () => { + const [isExpanded, setExpanded] = useState(false) + + return ( +
+ + {isExpanded ? ( + + Test + + ) : null} + + + +
+ ) +} + +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; +} + +.content-placeholder { + padding: 20px; + transform-origin: top center; +} + +header { + background: #0055ff; + border-radius: 10px; + color: white; + cursor: pointer; + height: 40px; + margin-bottom: 20px; +} + +.word { + height: 18px; + border-radius: 10px; + display: inline-block; + margin-bottom: 8px; + margin-right: 8px; + background: #0055ff; + border-radius: 10px; + display: inline-block; +} + +.paragraph { + margin-bottom: 20px; +} + +section { + overflow: hidden; +} + +@media (max-width: 600px) { + .content-placeholder { + padding-left: 20px; + } + + .header .word { + height: 30px; + } + + .word { + height: 14px; + margin-bottom: 5px; + margin-right: 5px; + } + + .paragraph { + margin-bottom: 20px; + } +}` + +const randomInt = (min, max) => Math.round(mix(min, max, Math.random())) +const generateParagraphLength = () => randomInt(5, 20) +const generateWordLength = () => randomInt(20, 100) + +// Randomly generate some paragraphs of word lengths +const paragraphs = Array(3) + .fill(1) + .map(() => { + return Array(generateParagraphLength()).fill(1).map(generateWordLength) + }) + +export const Word = ({ width }) =>
+ +const Paragraph = ({ words }) => ( +
+ {words.map((width) => ( + + ))} +
+) + +export const ContentPlaceholder = () => ( + + {paragraphs.map((words) => ( + + ))} + +) diff --git a/src/render/dom/utils/unit-conversion.ts b/src/render/dom/utils/unit-conversion.ts index 06ae02650d..dad5682e57 100644 --- a/src/render/dom/utils/unit-conversion.ts +++ b/src/render/dom/utils/unit-conversion.ts @@ -95,8 +95,10 @@ function removeNonTranslationalTransform(visualElement: VisualElement) { const positionalValues: { [key: string]: GetActualMeasurementInPixels } = { // Dimensions - width: ({ x }) => x.max - x.min, - height: ({ y }) => y.max - y.min, + 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), @@ -116,9 +118,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 @@ -140,7 +140,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) }) From c96882a20c43f0db4b6daae9889c73116b1f6e17 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 1 Nov 2021 14:36:22 +0100 Subject: [PATCH 2/6] Updating --- .../Animation-height-auto-padding.tsx | 86 ------------------- 1 file changed, 86 deletions(-) diff --git a/dev/examples/Animation-height-auto-padding.tsx b/dev/examples/Animation-height-auto-padding.tsx index b5dd94d562..d126bcf531 100644 --- a/dev/examples/Animation-height-auto-padding.tsx +++ b/dev/examples/Animation-height-auto-padding.tsx @@ -1,7 +1,6 @@ import * as React from "react" import { useState } from "react" import { motion, AnimatePresence } from "@framer" -import { mix } from "popmotion" export const App = () => { const [isExpanded, setExpanded] = useState(false) @@ -57,89 +56,4 @@ const styles = `body { width: 320px; padding: 20px; } - -.content-placeholder { - padding: 20px; - transform-origin: top center; -} - -header { - background: #0055ff; - border-radius: 10px; - color: white; - cursor: pointer; - height: 40px; - margin-bottom: 20px; -} - -.word { - height: 18px; - border-radius: 10px; - display: inline-block; - margin-bottom: 8px; - margin-right: 8px; - background: #0055ff; - border-radius: 10px; - display: inline-block; -} - -.paragraph { - margin-bottom: 20px; -} - -section { - overflow: hidden; -} - -@media (max-width: 600px) { - .content-placeholder { - padding-left: 20px; - } - - .header .word { - height: 30px; - } - - .word { - height: 14px; - margin-bottom: 5px; - margin-right: 5px; - } - - .paragraph { - margin-bottom: 20px; - } }` - -const randomInt = (min, max) => Math.round(mix(min, max, Math.random())) -const generateParagraphLength = () => randomInt(5, 20) -const generateWordLength = () => randomInt(20, 100) - -// Randomly generate some paragraphs of word lengths -const paragraphs = Array(3) - .fill(1) - .map(() => { - return Array(generateParagraphLength()).fill(1).map(generateWordLength) - }) - -export const Word = ({ width }) =>
- -const Paragraph = ({ words }) => ( -
- {words.map((width) => ( - - ))} -
-) - -export const ContentPlaceholder = () => ( - - {paragraphs.map((words) => ( - - ))} - -) From 129e5226731a14379445d00e9a2a10f56002e18b Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 1 Nov 2021 14:40:06 +0100 Subject: [PATCH 3/6] Adding test --- .../utils/__tests__/unit-conversion.test.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/render/dom/utils/__tests__/unit-conversion.test.ts diff --git a/src/render/dom/utils/__tests__/unit-conversion.test.ts b/src/render/dom/utils/__tests__/unit-conversion.test.ts new file mode 100644 index 0000000000..2b58dc9b42 --- /dev/null +++ b/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, { paddingTop: "50px" }) + ).toBe(50) + + expect( + positionalValues.width(testDimensions, { paddingBottom: "25px" }) + ).toBe(75) + + expect( + positionalValues.height(testDimensions, { paddingLeft: "50px" }) + ).toBe(250) + + expect( + positionalValues.height(testDimensions, { paddingRight: "25px" }) + ).toBe(275) + }) +}) From 1770811e28ba492c21d4a7bcef4ab2c3c067617b Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 1 Nov 2021 14:44:55 +0100 Subject: [PATCH 4/6] Updating changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5a11c79d..668b86469a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 From 835b7aadab4481ee55e71f5baa87c6ef6c728f4e Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 1 Nov 2021 15:15:57 +0100 Subject: [PATCH 5/6] Fixing export --- src/render/dom/utils/unit-conversion.ts | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/render/dom/utils/unit-conversion.ts b/src/render/dom/utils/unit-conversion.ts index dad5682e57..f883777d01 100644 --- a/src/render/dom/utils/unit-conversion.ts +++ b/src/render/dom/utils/unit-conversion.ts @@ -93,22 +93,24 @@ function removeNonTranslationalTransform(visualElement: VisualElement) { return removedTransforms } -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), -} +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, From 50329782f5577f5581596abda32e321d9462f6a6 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 1 Nov 2021 15:53:55 +0100 Subject: [PATCH 6/6] Fixing test --- src/render/dom/utils/__tests__/unit-conversion.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/render/dom/utils/__tests__/unit-conversion.test.ts b/src/render/dom/utils/__tests__/unit-conversion.test.ts index 2b58dc9b42..8765f579eb 100644 --- a/src/render/dom/utils/__tests__/unit-conversion.test.ts +++ b/src/render/dom/utils/__tests__/unit-conversion.test.ts @@ -7,19 +7,19 @@ describe("Unit conversion", () => { y: { min: 0, max: 300 }, } expect( - positionalValues.width(testDimensions, { paddingTop: "50px" }) + positionalValues.width(testDimensions, { paddingLeft: "50px" }) ).toBe(50) expect( - positionalValues.width(testDimensions, { paddingBottom: "25px" }) + positionalValues.width(testDimensions, { paddingRight: "25px" }) ).toBe(75) expect( - positionalValues.height(testDimensions, { paddingLeft: "50px" }) + positionalValues.height(testDimensions, { paddingTop: "50px" }) ).toBe(250) expect( - positionalValues.height(testDimensions, { paddingRight: "25px" }) + positionalValues.height(testDimensions, { paddingBottom: "25px" }) ).toBe(275) }) })