Skip to content

Instantly share code, notes, and snippets.

@ykob
Last active May 18, 2020 11:52
Show Gist options
  • Save ykob/67dec659024ab4defbf6a6bfc44ab039 to your computer and use it in GitHub Desktop.
Save ykob/67dec659024ab4defbf6a6bfc44ab039 to your computer and use it in GitHub Desktop.

Revisions

  1. ykob revised this gist May 18, 2020. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions App.vue
    Original file line number Diff line number Diff line change
    @@ -7,8 +7,7 @@ export default {
    created() {
    window.addEventListener("resize", this.resize);
    window.addEventListener("scroll", this.scroll);
    },
    mounted() {
    this.resize();
    },
    methods: {
  2. ykob revised this gist May 18, 2020. No changes.
  3. ykob created this gist May 18, 2020.
    28 changes: 28 additions & 0 deletions App.vue
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    <template>
    <div></div>
    </template>

    <script>
    export default {
    created() {
    window.addEventListener("resize", this.resize);
    window.addEventListener("scroll", this.scroll);
    },
    mounted() {
    this.resize();
    },
    methods: {
    resize() {
    this.$store.commit("resize", {
    x: document.body.clientWidth,
    y: window.innerHeight
    });
    },
    scroll() {
    this.$store.commit("scroll", window.pageYOffset);
    }
    }
    };
    </script>

    <style></style>
    64 changes: 64 additions & 0 deletions ScrollEffectBlock.vue
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    <template>
    <div>
    <slot
    :isIncludedScroll = "isIncludedScroll"
    />
    </div>
    </template>

    <script>
    export default {
    data() {
    return {
    updateClientRectIterate: 0,
    top: 0,
    bottom: 0,
    isIncludedScroll: false
    };
    },
    watch: {
    "$store.state.resolution"() {
    this.updateClientRectIterate = 0;
    this.updateClientRect();
    },
    "$store.state.scrollTop"() {
    this.judgeBeIncludedScroll();
    }
    },
    mounted() {
    this.updateClientRect();
    },
    methods: {
    updateClientRect() {
    const rect = this.$el.getBoundingClientRect();
    const top = this.$store.state.scrollTop + rect.top;
    // ページロード直後はスクロールイベントが多発することがあるため、
    // 正常に要素の位置を取得できない。
    // なので数回位置情報取得の処理を実行して、
    // 位置のズレがなくなったのを見越して要素の位置情報を確定とする。
    if (this.updateClientRectIterate < 10) {
    if (this.top === top) {
    this.updateClientRectIterate++;
    }
    this.top = top;
    requestAnimationFrame(this.updateClientRect);
    } else {
    this.bottom = top + rect.height;
    this.judgeBeIncludedScroll();
    }
    },
    judgeBeIncludedScroll() {
    const { state } = this.$store;
    if (
    state.visibleAreaTop >= this.top &&
    state.visibleAreaBottom <= this.bottom
    ) {
    this.isIncludedScroll = true;
    }
    }
    }
    };
    </script>

    <style></style>
    27 changes: 27 additions & 0 deletions store.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    import Vue from "vue";
    import Vuex from "vuex";

    Vue.use(Vuex);

    export default new Vuex.Store({
    state: {
    scrollTop: 0,
    visibleAreaTop: 0,
    visibleAreaBottom: 0,
    resolution: {
    x: 0,
    y: 0
    }
    },
    mutations: {
    resize(state, { x, y }) {
    state.resolution.x = x;
    state.resolution.y = y;
    },
    scroll(state, scrollTop) {
    state.scrollTop = scrollTop;
    state.visibleAreaTop = state.scrollTop + state.resolution.y * 0.9;
    state.visibleAreaBottom = state.scrollTop + state.resolution.y * 0.1;
    }
    }
    });