poppa / sveltekit-svg

SvelteKit plugin that makes it possible to import SVG files as Svelte components, inline SVG code or urls
MIT License
235 stars 23 forks source link

The "bind:this" directive doesn't work with sveltekit-svg #67

Closed geohuz closed 4 weeks ago

geohuz commented 1 month ago
<script>
  import BaseSvg from "./map2.svg?component";
  let base;

  $effect(() => {
    console.log(base); // --> {}
  });
</script>

<BaseSvg bind:this={base} />

I'm trying to use the getBBox() to get the dimension of mounted component, but it is {} and doesn't work.

poppa commented 1 month ago

I don't think that's possible. You'r not binding the DOM element of the SVG, you'r binding the component itself with bind:this.

But if I can be proven wrong I will happily look into it further.

geohuz commented 1 month ago
<script>
  let base;

  $effect(() => {
    console.log(base.clientWidth); // --> 730
  });
</script>

<div bind:this={base}>test</div>

https://svelte.dev/docs/svelte/bind#bind:this

poppa commented 1 month ago

But when you bind BaseSvg you bind the component holding the SVG, not the DOM element of the SVG.

poppa commented 1 month ago

BTW @geohuz, you might be able to achieve something like what you asked for with the preCompileHook. There's an example of the preCompileHook in the sample app: https://github.com/poppa/sveltekit-svg/blob/main/test-app/vite.config.ts

Now, this is psuedo code which I haven't tried, but I'm sure you can figure it out from here:

svg({
  includePaths: [`./src/assets/svg/`],
  preCompileHook(rawSvg, splitSvg) {
    const comp = `
    <script>export let domNode = undefined</script>
    <svg ${splitSvg.attributes} {...$$props} bind:this={domNode}>
      ${splitSvg.content}
    </svg>
    `

    return comp
  },
})

Then when you import your SVG:

<script>
import SvgBase from './assets/svg/file.svg?component'

let boundSvg

$effect(() => {
  // NOTE: the SVG may not be mounted yet at this point, that something you need to verify
  console.log('boundSvg svg:', boundSvg.domNode);
})
</script>

<SvgBase bind:this={boundSvg} />

Something like this may give you what you want.