Move from jQuery based logic to a VueJS one

I have this kind of code in jQuery:

$('.selector').mousemove(function (e) {
  $position = Math.round(e.pageX / $(window).width() * 100000) / 1000;
  $('.selector').css('background-position', $position + '% center');
});

I have to transform it to Vue 3 js logic (classic way, I am not using composition api), but I am not sure how to do it and I would like to avoid to add other libraries as jquery etc…. to keep it fast and small.

My solution (Thx to kissu):

Div with parallax:

<div @mousemove="doParallaxStuff($event)" ref="parallaxDiv">... </div>

Vue js method :

        doParallaxStuff(e) {
            this.backgroundPosition =
                Math.round((e.pageX / window.innerWidth) * 100000) / 1000;
            this.$refs.parallaxDiv.setAttribute(
                "style",
                "background-position:" + this.backgroundPosition + "% center"
            );
        },

Answer

You could create a custom directive for it:

2.x syntax:

Vue.directive('moving-background', {
  inserted: function(el) {
    el.addEventListener('mousemove', (e) => {
      const position = Math.round(e.pageX / windowWidth() * 1e5) / 1e3;
      el.style.backgroundPosition = `${position}% center`;
    })
  }
})

new Vue({
  el: '#app'
})

function windowWidth() {
  const prop = window.document.documentElement.clientWidth;
  const body = window.document.body;
  return window.document.compatMode === "CSS1Compat" && prop ||
    body && body.clientWidth ||
    prop;
}
.test-element {
  background: url('https://vuejs.org/images/logo.png') center no-repeat;
  width: 100%;
  height: 300px;
  border: solid #35495e;
  border-width: 10px 0;
  margin: 2rem auto;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app">
  <div v-moving-background class="test-element"></div>
</div>

3.x syntax:

const app = Vue.createApp({})

app.directive('moving-background', {
  beforeMount: function(el) {
    el.addEventListener('mousemove', (e) => {
      const position = Math.round(e.pageX / windowWidth() * 1e5) / 1e3;
      el.style.backgroundPosition = `${position}% center`;
    })
  }
})


app.mount('#app')

function windowWidth() {
  const prop = window.document.documentElement.clientWidth;
  const body = window.document.body;
  return window.document.compatMode === "CSS1Compat" && prop ||
    body && body.clientWidth ||
    prop;
}
.test-element {
  background: url('https://vuejs.org/images/logo.png') center no-repeat;
  width: 100%;
  height: 300px;
  border: solid #35495e;
  border-width: 10px 0;
  margin: 2rem auto;
}
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
<div id="app">
  <div v-moving-background class="test-element"></div>
</div>

Note the windowWidth() function is a replacement for jQuery’s $(window).width(), taken from here. It should be placed in a helper file and imported in your directive (and wherever else you might need it).

Now you can place v-moving-background directive on any DOM element or Vue component you want this behavior on, as shown on div.test-element above.
The CSS is not needed, I added it for this demo only.

Leave a Reply

Your email address will not be published. Required fields are marked *