Skip to content

Commit

Permalink
Merge pull request #209 from tmg0/fix/scale
Browse files Browse the repository at this point in the history
fix: children element scale error
  • Loading branch information
tmg0 authored Nov 1, 2024
2 parents fdb50e8 + 33bcfb3 commit 9227180
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 8 deletions.
21 changes: 20 additions & 1 deletion packages/core/src/composables/use-hero.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import type { HeroProps } from '../components/hero'
import { tryOnBeforeUnmount, tryOnMounted, useElementBounding } from '@vueuse/core'
import { useElementTransform, useMotion } from '@vueuse/motion'
import { defu } from 'defu'
import { computed, type MaybeRef, unref } from 'vue'
import { computed, type MaybeRef, unref, watch } from 'vue'
import { type HeroContext, useHeroContext } from '../composables/use-hero-context'
import { useStyle } from './use-style'

export interface UseHeroProps extends Omit<HeroProps, 'as' | 'ignore'> {
ignore?: string[]
Expand Down Expand Up @@ -35,6 +36,10 @@ export function useHero(target: MaybeRef<HTMLElement | SVGElement | undefined>,
const { layouts, props: ctxProps } = ctx ?? useHeroContext()
const { height, width, x, y, update } = useElementBounding(target)
const props = computed(() => unref(options))
const { transform } = useStyle(target)

const scaleX = computed(() => transform.value.scaleX)
const scaleY = computed(() => transform.value.scaleY)

const style = computed(() => ({ borderRadius: useBorderRadius(target), ...props.value?.style ?? {} }))

Expand All @@ -53,6 +58,18 @@ export function useHero(target: MaybeRef<HTMLElement | SVGElement | undefined>,
},
})

watch(() => [scaleX.value, scaleY.value], ([x, y]) => {

Check failure on line 61 in packages/core/src/composables/use-hero.ts

View workflow job for this annotation

GitHub Actions / lint

'x' is defined but never used. Allowed unused args must match /^_/u

Check failure on line 61 in packages/core/src/composables/use-hero.ts

View workflow job for this annotation

GitHub Actions / lint

'y' is defined but never used. Allowed unused args must match /^_/u
const elt = unref(target)

if (!elt)
return

for (let i = 0; i < elt.children.length; i++) {
const child = elt.children[i] as HTMLElement
child.style.transform = `scaleX(${1 / scaleX.value}) scaleY(${1 / scaleY.value})`
}
})

tryOnMounted(setup)
tryOnBeforeUnmount(clean)

Expand Down Expand Up @@ -110,6 +127,8 @@ export function useHero(target: MaybeRef<HTMLElement | SVGElement | undefined>,
bounding,
x,
y,
scaleX,
scaleY,
setup,
clean,
}
Expand Down
49 changes: 49 additions & 0 deletions packages/core/src/composables/use-style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core'
import { type MaybeRef, ref, unref } from 'vue'

function parseTransform(value: string) {
const translate3dMatch = /translate3d\(([^)]+)\)/.exec(value)
const scaleXMatch = /scaleX\(([\d.]+)\)/.exec(value)
const scaleYMatch = /scaleY\(([\d.]+)\)/.exec(value)

const [x, y, z] = translate3dMatch
? translate3dMatch[1].split(',').map(val => Number.parseFloat(val))
: [0, 0, 0]

return {
translateX: x,
translateY: y,
translateZ: z,
scaleX: scaleXMatch ? Number.parseFloat(scaleXMatch[1]) : 1,
scaleY: scaleYMatch ? Number.parseFloat(scaleYMatch[1]) : 1,
}
}

export function useStyle(target: MaybeRef<HTMLElement | SVGElement | undefined>) {
let observer: MutationObserver

const transform = ref<Record<string, number>>({})

tryOnMounted(() => {
observer = new MutationObserver((mutations) => {
mutations.forEach(({ target }) => {
transform.value = parseTransform((target as any).style.transform ?? '')
})
})

const elt = unref(target)

if (!elt)
return

observer.observe(elt, { attributes: true, attributeFilter: ['style'] })
})

tryOnUnmounted(() => {
observer?.disconnect()
})

return {
transform,
}
}
12 changes: 8 additions & 4 deletions playgrounds/vite/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { directive, HeroProvider } from 'hero-motion'
import { directive, Hero, HeroProvider } from 'hero-motion'
import { ref } from 'vue'
import { Tab, Tabs } from './components/Tabs'
Expand Down Expand Up @@ -65,13 +65,17 @@ function toggleSize() {
</div>

<div class="p-4 bg-gradient-to-r from-violet-500 to-fuchsia-500 rounded-xl">
<div class="grid place-items-center h-48 w-48">
<div class="grid place-items-center h-52 w-52">
<button class="inline-flex justify-center rounded-md border border-transparent bg-violet-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-violet-200" @click="toggleSize">
Toggle (loading: {{ !hasCompleted }})
</button>

<div v-if="isLarge" v-hero as="div" layout-id="box" class="w-24 h-24 rounded-xl cursor-pointer" :style="{ background: '#f43f5e' }" @complete="onComplete" />
<div v-else v-hero as="div" layout-id="box" class="w-12 h-12 rounded-xl cursor-pointer" :style="{ background: '#2dd4bf' }" @complete="onComplete" />
<Hero v-if="isLarge" v-hero as="div" layout-id="box" class="w-36 h-36 rounded-xl flex items-center justify-center" :style="{ background: '#f43f5e' }" @complete="onComplete">
<div>text content</div>
</Hero>
<Hero v-else v-hero as="div" layout-id="box" class="w-24 h-24 rounded-xl flex items-center justify-center" :style="{ background: '#2dd4bf' }" @complete="onComplete">
<div>text content</div>
</Hero>
</div>
</div>
</div>
Expand Down
4 changes: 1 addition & 3 deletions playgrounds/vite/src/components/Avatar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,5 @@ defineProps<{
</script>

<template>
<Hero :layout-id="`avatar:${id}`" :style="{ width: `${size}px`, height: `${size}px` }" class="text-white rounded-lg flex items-center justify-center uppercase overflow-hidden">
<img :src="src">
</Hero>
<Hero as="img" :src="src" :layout-id="`avatar:${id}`" :style="{ width: `${size}px`, height: `${size}px` }" class="text-white rounded-lg flex items-center justify-center uppercase overflow-hidden" />
</template>

0 comments on commit 9227180

Please sign in to comment.