Aminerman / vue-kinesis

Easily create complex interactive animations with Vue.js
https://www.aminerman.com/kinesis/
MIT License
1.47k stars 59 forks source link

How to use with layered svg? #58

Closed DRD161 closed 3 years ago

DRD161 commented 3 years ago

I am trying to have 2 separate svg components, with one laying on top of the other, each have their own animations qwhen moving the mouse. The animations work but only for the component that is last in the source order (the one underneath the other). I am using CSS Grid to position the components and have also tried absolute positioning but once the two components intersect things stop working properly. My goal is to have them each move independently of one another. My components are below:

COMPONENT 1 (top layer)

<template>
  <kinesis-container class="square-container">
    <kinesis-element :strength="10">
      <svg
        id="blue-square"
        data-depth="0.6"
        xmlns="http://www.w3.org/2000/svg"
        width="330"
        height="330"
        viewBox="0 0 362 362"
      >
        <g
          id="Blue_Square"
          data-name="Blue Square"
          transform="translate(0 362) rotate(-90)"
          fill="none"
          stroke="rgba(2,137,204,0.33)"
          stroke-width="1"
        >
          <rect width="330" height="330" stroke="none" />
          <rect x="0.5" y="0.5" width="330" height="330" fill="none" />
        </g>
      </svg>
    </kinesis-element>
  </kinesis-container>
</template>

<script>
export default {
  props: {
    width: { type: Number, default: 200 },
    height: { type: Number, default: 200 }
  }
};
</script>

<style lang="scss" scoped>
.square-container {
  grid-column: 5;
  grid-row: 4;
}
</style>

COMPONENT 2 (bottom layer)

<template>
  <kinesis-container class="circle-container">
    <kinesis-element>
      <svg
        xmlns="http://www.w3.org/2000/svg"
        :width="width"
        :height="height"
        viewBox="0 0 547 547"
      >
        <g
          id="circle-green"
          data-name="circle green"
          fill="none"
          stroke="rgba(6,214,160,0.29)"
          stroke-width="1"
        >
          <circle cx="273.5" cy="273.5" r="273.5" stroke="none" />
          <circle cx="273.5" cy="273.5" r="273" fill="none" />
        </g>
      </svg>
    </kinesis-element>
  </kinesis-container>
</template>
<script>
export default {
  props: {
    width: { type: Number, default: 200 },
    height: { type: Number, default: 200 }
  }
};
</script>

<style lang="scss" scoped>
.circle-container {
  grid-column: 5;
  grid-row: 4;
}
</style>
Aminerman commented 3 years ago

Yes, I think I understand your issue. The way the kinesis-container works is that it detects the mouse hovering and triggers animations of the kinesis-element. So the hover will only be detected on the one that is on top in the render when they intersect. What you could do is instead of having Component1 on top of Component2, you can have a structure like this, but then it will not make them move independently:

Parent.vue

<kinesis-container>
    <Component1/>
    <Component2/>
</kinesis-container>

And you can remove kinesis-container from Component1 and Component2.

A workaround could be that I could add the possibility to add more control as to when the animations are triggered, through a prop that you'd manage yourself. Other than that I can't see an easy solution to fix this problem. It really is an issue of how the mouseover works, and not with the components.