1

I have a group of diagonal lines following the mouse on move.

This works fine if I only have one instance of the group on the page but I need to have multiple instances.

When I duplicate the HTML, they do not work independently of each other and doesn't produce the desired effect.

jQuery:

var dash = $(".graphic-wave__dash");
if(dash.length > 0){
  var offset = dash.offset();
  function mouse(evt){
    var center_x = (offset.left) + (dash.width()/2);
    var center_y = (offset.top) + (dash.height()/2);
    var mouse_x = evt.pageX; var mouse_y = evt.pageY;
    var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
    var degree = (radians * (180 / Math.PI) * -1) + 90;
    dash.css('-moz-transform', 'rotate('+degree+'deg)');
    dash.css('-webkit-transform', 'rotate('+degree+'deg)');
    dash.css('-o-transform', 'rotate('+degree+'deg)');
    dash.css('-ms-transform', 'rotate('+degree+'deg)');
    dash.removeClass('original');
  }
  $(document).mousemove(mouse);
}

HTML:

<div class="graphic-wave">
  <div class="graphic-wave__row">
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
  </div>
  <div class="graphic-wave__row">
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
  </div>
  <div class="graphic-wave__row">
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
  </div>
</div>

<div class="graphic-wave" style="left: 400px;">
  <div class="graphic-wave__row">
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
  </div>
  <div class="graphic-wave__row">
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
  </div>
  <div class="graphic-wave__row">
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
    <div class="graphic-wave__dash original"></div>
  </div>
</div>

https://jsfiddle.net/ob80/7nxf07vo/3/

Can anyone help?

ob80
  • 97
  • 1
  • 12
  • You're selecting every element with the `.graphic-wave__dash` class, then applying the same effect to each one. You'll need to calculate it per line/group of lines, perhaps using jQuery's `.each()` and using `$(this)` to select the relevant line inside your function. – DBS Nov 22 '17 at 11:03

2 Answers2

4

You will need to calculate the rotation of each line separately, at the moment you're working out a single rotation style and applying it to every element with the graphic-wave__dash class.

Here's a quick example I haven't done any optimisation, and this may be very inefficient. (I've not put it into a snippet since it appears SO doesn't support SCSS)

var dash = $(".graphic-wave__dash");
if (dash.length > 0) {

  function mouse(evt) {
    dash.each(function() { // Calculate per element, not just once
      var offset = $(this).offset(); // Workout the offset per element
      var center_x = (offset.left) + ($(this).width() / 2); // Use $(this) to reference the current element
      var center_y = (offset.top) + ($(this).height() / 2);
      var mouse_x = evt.pageX;
      var mouse_y = evt.pageY;
      var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
      var degree = (radians * (180 / Math.PI) * -1) + 90;
      $(this).css('-moz-transform', 'rotate(' + degree + 'deg)');
      $(this).css('-webkit-transform', 'rotate(' + degree + 'deg)');
      $(this).css('-o-transform', 'rotate(' + degree + 'deg)');
      $(this).css('-ms-transform', 'rotate(' + degree + 'deg)');
      $(this).removeClass('original');
    });
  }
  $(document).mousemove(mouse);
}

The changes made are:

  • Inside the function, loop through every element with your class
  • Calculate the offset per element, not all based on the first instance of that class
DBS
  • 9,110
  • 4
  • 35
  • 53
  • That's it! Thanks for the example :) – ob80 Nov 22 '17 at 11:14
  • Hi @ob80, please check my performance improved answer [below](https://stackoverflow.com/questions/47432972/rotate-multiple-groups-of-shapes-on-mousemove/47433845#47433845) – FcoRodr Nov 22 '17 at 11:46
1

I improved performance over DBS answer by setting as an attribute the center_x and center_y of all items, so it hasn't to be calculated everytime:

var dash = $(".graphic-wave__dash");
if (dash.length > 0) {

    dash.each(function() {
      var offset = $(this).offset();
      $(this).attr('center_x',(offset.left) + ($(this).width() / 2));
      $(this).attr('center_y',(offset.top) + ($(this).height() / 2));
  });

  function mouse(evt) {
    dash.each(function() {
      var mouse_x = evt.pageX;
      var mouse_y = evt.pageY;
      var radians = Math.atan2(mouse_x - $(this).attr('center_x'), mouse_y - $(this).attr('center_y'));
      var degree = (radians * (180 / Math.PI) * -1) + 90;
      $(this).css('-moz-transform', 'rotate(' + degree + 'deg)');
      $(this).css('-webkit-transform', 'rotate(' + degree + 'deg)');
      $(this).css('-o-transform', 'rotate(' + degree + 'deg)');
      $(this).css('-ms-transform', 'rotate(' + degree + 'deg)');
      $(this).removeClass('original');
    });
  }
  $(document).mousemove(mouse);
}

Here is the fiddle: https://jsfiddle.net/7nxf07vo/6/

FcoRodr
  • 1,583
  • 7
  • 15
  • If you're going for optimisation, there's a couple of other things you could also improve: The mouse position var's don't need to be inside the loop. And you could probably just ditch the radians/degrees conversion as CSS transforms should accept radians with the postfix `rad` instead of `deg`. – DBS Nov 22 '17 at 12:41
  • @DBS Well, the main performance killer was the position calculation. The `deg` calculation relies on a single math operation and so far the fiddle works very fuildly. – FcoRodr Nov 22 '17 at 12:52
  • Indeed, just throwing out some other possible tweaks :) – DBS Nov 22 '17 at 14:11