Jump to content
Search Community

Dealing with multiple elements with the same class name

Eugene Rayner test
Moderator Tag

Recommended Posts

Hey there, welcome to my post.

 

I'm building my portfolio site in Vuejs and have decided to go with GSAP as I love GSAP :D

 

I've split my code into pages and components. The pages send data over to my components so that it's easier to manage the content.

 

The issue I am facing is that I don't want to give separate Ids to each render of the component. 

 

Take this code example which I have simplified for the purpose of this post

 

<template>
  <div class="paragraph-image-block">
     <div class="paragraph-image-block--text">
        <h3>{{title}}</h3>
        <p v-for="(paragraph, index) in paragraphs" :key="'paragraph-' + index" v-html="paragraph"></p>
      </div>
      <Icon :name="image"/>
  </div>
</template>

<script>
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

export default {
  name: 'Paragraph',
  methods: {
    scrollAnimation() {
      gsap.to("h3", { opacity: 1, duration: 2, scrollTrigger: ".paragraph-image-block"})
      gsap.to("p", { opacity: 1, duration: 2, scrollTrigger: ".paragraph-image-block"})
    }
  },
  mounted() {
    this.scrollAnimation();
  },
}
</script>

<style>
  .paragraph-image-block h3, .paragraph-image-block p{
    opacity: 0;
  }
</style>

Say I have like 3 of these components rendering on the page. Each component has a class of paragraph-image-block and each contains 1 <h3> and multiple <p> tags. When the component is scrolled into, I want to just make the opacity go from 0 to 1.

 

I have set the initial css to be opacity 0, and they do work, but the problem is, because I am saying when this class is scrolled into, show them, then all of the classes with the same class are showed at the same time. I want them to each show only when the component is scrolled into.. if that makes sense.

 

Any help greatly appreciated :)

 

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

A few months later and i'm back :D
I still can't get it to work aye. I am getting an out of scope error. I assume it's got something to do with the $refs.

 

I am using gsap utils like you've suggested, but I am getting an out of scope error which I assume is related to my $refs. The example uses this.$el but I am inside the component so that doesn't really exist for me... hence $refs

 

methods: {
    animate() {
      const { block } = this.$refs.block
      const whole = gsap.utils.selector(block)
      gsap.timeline({
        scrollTrigger: {
          trigger: whole,
          start: "top top",
          markers: true
        },
      })
      .to(whole, { rotation:90, duration: 2 })
    }
  },
  mounted() {
    this.$nextTick(() => this.animate());
  },

Any help always appreciated guys, thanks! 

Link to comment
Share on other sites

Okay it's all come back to me. LOL!

 

I'll note the answer here incase someone comes across a similar problem from the Vue community.

mounted() {
    // fix was to get the block ref and then get it's elements
      const { block } = this.$refs
      
      //element
      const whole = block.getElementsByClassName("paragraph-image-block--text")
      const h3 = block.getElementsByTagName("h3")

      gsap.timeline({
        scrollTrigger: {
          trigger: whole,
          markers: true
        },
      })
      .to(h3, { rotation:90, duration: 2 })
  },

Essentially instead of trying to get A element, just target the specific ones you want and use the $refs to get the whole block itself.

Link to comment
Share on other sites

You weren't using the selector correctly. It returns a function.

const q = gsap.utils.selector(block);
const h3 = q("h3");
const foo = q(".foo");

 

Think of it kind of like jQuery's $

const $ = gsap.utils.selector(block);
const h3 = $("h3");
const foo = $(".foo");

 

We use the name q in our code samples because it returns a query function.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

Hallo Forum!

Im doing something similar(but in nuxt), i actually do @Carl course just trying to do everything in nuxt.

  and just got this error.

 

 

so i wonder how to get out of this without turning back to nuxt😃

if anyone had a similar experience, id be grateful for any ideas:!)

happy tweening!

 

1026212337_Bildschirmfoto2021-12-06um03_08_01.thumb.png.2bc46112e8df17f0c3611d4f044ed102.png

<template>
  <div>
    <div class="hero">Scroll Down</div>
    <div ref="ban" class="ban banner">
      <div ref="background" class="background miata"></div>
      <div class="foreground">
        <h1>1995 Mazda Miata</h1>
        <h2>10k miles</h2>
      </div>
    </div>
    <div class="content">
      <p>
        Nullam lobortis tincidunt orci, id ultricies mauris consectetur sit
        amet. Nulla at enim augue. Nam quam velit, efficitur vestibulum justo
        iaculis, rutrum posuere sem. Orci varius natoque penatibus et magnis dis
        parturient montes
      </p>
    </div>

    <div class="banner" ref="ban">
      <div class="background cayman"></div>
      <div class="foreground">
        <h1>2006 Porsche Cayman S</h1>
        <h2>33k miles</h2>
      </div>
    </div>
    <div class="content">
      <p>
        Nullam lobortis tincidunt orci, id ultricies mauris consectetur sit
        amet. Nulla at enim augue. Nam quam velit, efficitur vestibulum justo
        iaculis, rutrum posuere sem. Orci varius natoque penatibus et magnis dis
        parturient montes
      </p>
    </div>
  </div>
</template>

<script>
import gsap from 'gsap/all'
import { ScrollTrigger } from 'gsap/all'
export default {
  data() {
    return {}
  },
  mounted() {
    gsap.registerPlugin(ScrollTrigger)
    this.animation()
  },
  methods: {
    animation() {
      const q = gsap.utils.selector('.banner')
      //   const background = q('.background')
      //   const headings = q('h1, h2 ')
      q('.banner').forEach((banner) => {
        let tl = gsap.timeline({
          ScrollTrigger: {
            trigger: banner,
            start: 'top 90%',
            toggleActions: 'play none none reverse',
          },
        })
        tl.from(background, {
          backgroundPosition: '60% 0%',
          filter: 'brightness(0.1)',
          duration: 1,
        }).from(headings, { y: 200, stagger: 0.1 }, 0)
      })
    },
  },
}
</script>

 

Link to comment
Share on other sites

hey mate, I ended up paying someone to help a bit haha!
hope this helps

 

import { gsap } from "gsap";

computed: {
	meAnimation(){
      return gsap.timeline({paused:true})
      .to('#me', {x:200, rotation:360/4, transformOrigin:'center'})
    },
},
methods:{
    hoverIn(){
      this.meAnimation.play()
    },
}

Chuck it on a hover or a click before attempting mounted. Mounted has some issues with when things load especially with animations.

Link to comment
Share on other sites

Hi @mateuszjanbilko,

 

It looks like you're trying to use gsap.utils.selector('.banner') in the same way as you'd use document.querySelectorAll('.banner')

 

Easy mistake to make but these aren't equivalent. Take a look at this 
 

methods: {
 animate() {
   // this creates a scoped selector 
   let q = gsap.utils.selector(this.$el);
  
   // this bit queries within that scope - it uses this.$el.querySelectorAll() internally
   gsap.to(q(".box"), { x: 100 });
 }
}


Maybe this vanilla demo will help clear it up?

See the Pen abLdwBP?editors=1010 by GreenSock (@GreenSock) on CodePen

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...