이런 질문도 답변 가능할까요?
미해결
애플 웹사이트 인터랙션 클론!
지금 16강 수강중이구요 스크롤 애니메이션을 vue에서 따라 작성해보고있는데 .. 값이 다르게 찍히는게 있어서 혹시나 해결방법을 아시는지 궁금해서 여쭤봅니다. ㅠㅠ 다른 부분들은 나름 어거지로??어떻게 따라와서 텍스트 하나를 나타나고 사라지게 하는게 되긴하는데 ... 추후 강의를 똑같이 따라갈 수 있을런지... 제 이슈는 이렇습니다. value값이 동일하게 찍히질않습니다. 강의에서는 아래처럼 values.length값이 배열로 잘 나오는데.. 저는 value값을 콘솔로 찍었을 때는 이렇게나오고 values[0]은 undefined로 나와버려서 length값 체크도못하고 calcValue함수 내에서도 이런식으로 작성하면서 따라했거든요 .. object name을 콕 찝어서 데려와야만 배열값을 얻어요.. 배열로얻어오지못하니 강의와 똑같이 구현해보려고 calcvalue함수를 copy해서 하나는 in 하나는 out으로하는 무지막지한 코드를 작성해놨어요🤯🤯 같은 자바스크립트인데 환경좀 다르다고 이렇게 value값이 다를일인가요........... value의 배열값을 강의처럼 얻을수없다면 제 vue 스크롤연습은 여기서 접어야하는걸까요..?........ 이후 강의는 따라해볼 엄두가 안나네요 ..ㅜ 이틀 삽질하다 슬퍼서 질문올려봅니다... full code남기며 ... 질문마무리하겠습니다🥺 <template> <div class="main" ref="scrollWrap"> <section class="scroll-section" id="scroll-section-0" ref="scrollSection0"> <div class="hero" :style="`background-image: url(${이미지})`"> <div class="text-test">소환사 여러분</div> <div class="sticky-elem hero-message a" ref="message1"> <div class="year">10th ANNIVERSARY</div> </div> <!-- <div class="sticky-elem hero-message b" ref="message2"> <div class="thanks">THANK YOU SUMMONERS</div> </div> <div class="sticky-elem hero-message c" ref="message3"> <div class="greeting">리그오브레전드와 10년간 함께 해주신 소환사 여러분, 감사합니다!</div> <div class="greeting">THANK YOU, SUMMONERS!</div> </div> --> </div> </section> <section class="scroll-section" id="scroll-section-1" ref="scrollSection1"> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Assumenda<br> </p> </section> <button @click="setLayout">레이아웃d</button> <div> <input type="text" @input="setSearch($event.target.value)" /> <button @click="searchForPlayer(e)">serach</button> <div v-if="playerData" class="box"> <p>{{playerData.name}}</p> <p>{{playerData.summonerLevel}}</p> <p>{{playerData.profileIconId}}</p> <p><img width="100" height="100" :src="`http://ddragon.leagueoflegends.com/cdn/12.7.1/img/profileicon/${playerData.profileIconId}.png`"></p> </div> <div v-else class="box2"> <p>{{noPlayer}}</p> <p>데이터가없습니다</p> </div> </div> <router-view></router-view> <router-link to="/JH">링크</router-link> </div> </template> <script> import { onMounted, ref} from 'vue' import axios from 'axios' //씬을나눈다 //씬의 높이를 세팅한다 //활성화 시킬 씬을 결정한다 //this.prevScrollHeight = this.prevScrollHeight + this.sceneInfo[i].scrollHeight; //얘네는같은거임 this.prevScrollHeight += this.sceneInfo[i].scrollHeight; export default { name: 'App', components: { }, data() { return { errorText: "존재하지않는 데이터입니다", 이미지: "https://universe.leagueoflegends.com/images/championsBackground.jpg", sceneInfo: [ { type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { // container: document.querySelector('scroll-section-0') container : this.$refs.scrollSection0, massageA : this.$refs.message1, massageB : this.$refs.message2, massageC : this.$refs.message3, }, values: { messageA_opacity_in: [0,1, {start: 0.1, end: 0.2}], messageA_opacity_out: [1,0, {start: 0.25, end: 0.3}], } }, { type: 'normal', heightNum: 5, scrollHeight: 0, objs: { container: this.$refs.scrollSection1 } }, ], //window.pageYOffset 갱신 yOffset : 0, //현재 스크롤 위치(yOffset)보다 이전에 위치한 스크롤 섹션들의 스크롤 높이값의 합 prevScrollHeight : 0, //현재 활성화된 scene currentScene : 0, totalScrollHeight: 0, messageA_opacity_in: '', messageA_opacity_out: '', currentYOffset: 0, rv: 0, scrollRatio: 0, outerScrollRatio:0, enterNewScene: false, scrollHeight: 0, partSCrollStart: 0, partScrollEnd: 0, partScrollHeight: 0, currentSceneValues: '', infoCurretScene: 0, } }, setup() { let searchText = ref(""); let playerData = ref(); let noPlayer = ref(); let deleteMessage = ("존재하지않음"); let playerId = ref([]); let apiKey = "RGAPI-62f8907f-eab8-4333-bc43-94d32a09be28"; const setSearch = (검색어) => { searchText = 검색어 } const searchForPlayer = () => { playerData.value = null noPlayer.value = null //Handle the API call axios.get(`https://kr.api.riotgames.com/lol/summoner/v4/summoners/by-name/${searchText}?api_key=${apiKey}`) .then((response) => { playerData.value = response.data }).catch(error => { playerData.value = null noPlayer.value = deleteMessage; }); } return { searchText, playerData, playerId, setSearch, searchForPlayer, }; }, methods: { init() { this.setLayout(); this.scrollLoop(); }, setLayout() { // Sticky Conainer 의 높이를 설정함. // for( let i = 0; i < this.sceneInfo.length; i++ ){ // this.sceneInfo[i].scrollHeight = this.sceneInfo[i].heightNum + window.innerHeight; // this.sceneInfo[i].objs.container.style.height = `${this.sceneInfo[i].scrollHeight}px`; // } this.sceneInfo[0].scrollHeight = this.sceneInfo[0].heightNum + window.innerHeight; this.$refs.scrollSection0.style.height = `${this.sceneInfo[0].scrollHeight}px`; this.sceneInfo[1].scrollHeight = this.sceneInfo[1].heightNum + window.innerHeight; this.$refs.scrollSection1.style.height = `${this.sceneInfo[1].scrollHeight}px`; this.yOffset = window.pageYOffset; this.totalScrollHeight = 0; for( let i = 0; i < this.sceneInfo.length; i++ ){ this.totalScrollHeight += this.sceneInfo[i].scrollHeight; if(this.totalScrollHeight >= this.yOffset){ this.currentScene = i; break; } } }, calcValues(values, currentYOffset){ this.rv; this.scrollHeight = this.sceneInfo[this.currentScene].scrollHeight; //현재 scene에서 스크롤된 범위를 비율로 구하기 this.scrollRatio = this.currentYOffset / this.scrollHeight; this.outerScrollRatio = (this.yOffset - this.prevScrollHeight) / this.scrollHeight; this.infoCurretScene = this.sceneInfo[this.currentScene]; this.currentSceneValues = this.sceneInfo[this.currentScene].values; if(this.currentSceneValues.messageA_opacity_in.length === 3){ //start ~ end 사이에 애니메이션 실행 this.partSCrollStart = this.currentSceneValues.messageA_opacity_in[2].start * this.scrollHeight; this.partScrollEnd = this.currentSceneValues.messageA_opacity_in[2].end * this.scrollHeight; this.partScrollHeight = this.partScrollEnd - this.partSCrollStart; if(this.currentYOffset >= this.partSCrollStart && this.currentYOffset <= this.partScrollEnd){ this.rv = (this.currentYOffset - this.partSCrollStart) / this.partScrollHeight * ( this.currentSceneValues.messageA_opacity_in[1] - this.currentSceneValues.messageA_opacity_in[0]) + this.currentSceneValues.messageA_opacity_in[0]; }else if(this.currentYOffset < this.partSCrollStart){ this.rv = this.currentSceneValues.messageA_opacity_in[0]; }else if(this.currentYOffset > this.partScrollEnd){ this.rv = this.currentSceneValues.messageA_opacity_in[1]; } }else { this.rv = this.scrollRatio * ( this.currentSceneValues.messageA_opacity_in[1] - this.currentSceneValues.messageA_opacity_in[0]) + this.currentSceneValues.messageA_opacity_in[0]; } return this.rv; }, calcValues2(values, currentYOffset){ this.rv; this.scrollHeight = this.sceneInfo[this.currentScene].scrollHeight; //현재 scene에서 스크롤된 범위를 비율로 구하기 this.scrollRatio = this.currentYOffset / this.scrollHeight; this.outerScrollRatio = (this.yOffset - this.prevScrollHeight) / this.scrollHeight; this.infoCurretScene = this.sceneInfo[this.currentScene]; this.currentSceneValues = this.sceneInfo[this.currentScene].values; if(this.currentSceneValues.messageA_opacity_out.length === 3){ //start ~ end 사이에 애니메이션 실행 this.partSCrollStart = this.currentSceneValues.messageA_opacity_out[2].start * this.scrollHeight; this.partScrollEnd = this.currentSceneValues.messageA_opacity_out[2].end * this.scrollHeight; this.partScrollHeight = this.partScrollEnd - this.partSCrollStart; if(this.currentYOffset >= this.partSCrollStart && this.currentYOffset <= this.partScrollEnd){ this.rv = (this.currentYOffset - this.partSCrollStart) / this.partScrollHeight * ( this.currentSceneValues.messageA_opacity_out[1] - this.currentSceneValues.messageA_opacity_out[0]) + this.currentSceneValues.messageA_opacity_out[0]; }else if(this.currentYOffset < this.partSCrollStart){ this.rv = this.currentSceneValues.messageA_opacity_out[0]; }else if(this.currentYOffset > this.partScrollEnd){ this.rv = this.currentSceneValues.messageA_opacity_out[1]; } }else { this.rv = this.scrollRatio * ( this.currentSceneValues.messageA_opacity_out[1] - this.currentSceneValues.messageA_opacity_out[0]) + this.currentSceneValues.messageA_opacity_out[0]; } return this.rv; }, playAnimation(){ // const values = this.sceneInfo[this.currentScene].objs; // const values = this.sceneInfo[this.currentScene].values; this.currentYOffset = this.yOffset - this.prevScrollHeight; console.log(this.currentSceneValues[0]); switch (this.currentScene) { case 0: this.messageA_opacity_in = this.calcValues(this.sceneInfo[0].values.messageA_opacity_in, this.currentYOffset); this.messageA_opacity_out = this.calcValues2(this.sceneInfo[0].values.messageA_opacity_out, this.currentYOffset); if(this.outerScrollRatio <= 0.22){ //in this.$refs.message1.style.opacity = this.messageA_opacity_in; } else { //out this.$refs.message1.style.opacity = this.messageA_opacity_out; } break; case 1: break; } }, scrollLoop(){ this.enterNewScene = false; //scrollHeight값 누적되지않도록 0으로 this.prevScrollHeight = 0; for(let i = 0; i< this.currentScene; i++){ this.prevScrollHeight += this.sceneInfo[i].scrollHeight; } if(this.yOffset > this.prevScrollHeight + this.sceneInfo[this.currentScene].scrollHeight){ this.enterNewScene = true; this.currentScene++; // this.$refs.scrollWrap.setAttribute('id', `show-scene-${this.currentScene}`); } if(this.yOffset < this.prevScrollHeight){ if(this.currentScene === 0) return; this.enterNewScene = true; this.currentScene--; // this.$refs.scrollWrap.setAttribute('id', `show-scene-${this.currentScene}`); } this.$refs.scrollWrap.setAttribute('id', `show-scene-${this.currentScene}`); if(this.enterNewScene) return; this.playAnimation(); }, }, mounted() { this.init(); window.addEventListener('DOMContentLoaded',this.setLayout); window.addEventListener('resize', this.setLayout); window.addEventListener('scroll', () =>{ //스크롤이 일어날 때 yOffset 의 값을 window.pageYOffset 값으로 갱신 this.yOffset = window.pageYOffset; this.scrollLoop(); }); }, } </script> <style lang="scss"> body { margin: 0; } .scroll-section { border: 1px solid red } .text-test { position: relative; padding: 20px; z-index: 1; color: red; } </style>
- vue
- 클론코딩
- HTML/CSS
- svg
- 웹 디자인
- javascript
- 인터랙티브-웹





