diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts index fc5d260b91e..13eea5e8a1d 100644 --- a/packages/runtime-dom/src/components/TransitionGroup.ts +++ b/packages/runtime-dom/src/components/TransitionGroup.ts @@ -183,7 +183,16 @@ function applyTranslation(c: VNode): VNode | undefined { const dy = oldPos.top - newPos.top if (dx || dy) { const s = (c.el as HTMLElement).style - s.transform = s.webkitTransform = `translate(${dx}px,${dy}px)` + const p = (c.el as HTMLElement).offsetParent as HTMLElement + let scaleX = 1 + let scaleY = 1 + if (p) { + scaleX = p.getBoundingClientRect().width / p.offsetWidth + scaleY = p.getBoundingClientRect().height / p.offsetHeight + } + s.transform = s.webkitTransform = `translate(${dx / scaleX}px,${ + dy / scaleY + }px)` s.transitionDuration = '0s' return c } diff --git a/packages/vue/__tests__/e2e/TransitionGroup.spec.ts b/packages/vue/__tests__/e2e/TransitionGroup.spec.ts index 1a61c23a44e..60d91c65dfc 100644 --- a/packages/vue/__tests__/e2e/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/e2e/TransitionGroup.spec.ts @@ -19,6 +19,12 @@ describe('e2e: TransitionGroup', () => { const transitionFinish = (time = duration) => timeout(time + buffer) + const top = async (selector: string) => { + return await page().$eval(selector, node => { + return node.getBoundingClientRect().top + }) + } + beforeEach(async () => { await page().goto(baseUrl) await page().waitForSelector('#app') @@ -508,4 +514,58 @@ describe('e2e: TransitionGroup', () => { expect(` children must be keyed`).toHaveBeenWarned() }) + + test( + 'scale', + async () => { + await page().evaluate(() => { + const { createApp, ref, onMounted } = (window as any).Vue + createApp({ + template: ` +
+
+ +
  • {{item}}
  • +
    + +
    +
    + `, + setup: () => { + const items = ref(['a', 'b', 'c']) + const click = () => { + items.value.reverse() + } + + onMounted(() => { + const styleNode = document.createElement('style') + styleNode.innerHTML = `.v-move { + transition: transform 0.5s ease; + }` + document.body.appendChild(styleNode) + }) + + return { items, click } + } + }).mount('#app') + }) + + const original_top = await top('ul li:nth-child(1)') + const new_top = await page().evaluate(() => { + const el = document.querySelector('ul li:nth-child(1)') + const p = new Promise(resolve => { + el!.addEventListener('transitionstart', () => { + const new_top = el!.getBoundingClientRect().top + resolve(new_top) + }) + }) + ;(document.querySelector('#toggleBtn') as any)!.click() + + return p + }) + + expect(original_top).toBeLessThan(new_top as number) + }, + E2E_TIMEOUT + ) })