Банановый спрайт js делал анимацию вперед и назад с данными json - PullRequest
1 голос
/ 28 июня 2019

Мне нужно создать несколько пользовательских анимаций прокрутки - и я хотел бы начать изучать анимацию простого блока.

enter image description here

Использование json - я хочу предоставитьскелет для блока (имя класса, высота, ширина, фон), затем действия для начального / конечного кадров, которые относятся к значению прокрутки.

как изменить код - для обработки вперед / назаданимации для блока с использованием данных json

Так что в этом примере.

- когда прокрутка в 0 - или запуск приложения - создайте блок.enter image description here

- если прокрутка находится в диапазоне 100-400 - свиток получает указание двигаться вправо.enter image description here

- если свиток превышает 400 - уничтожить блок.

, поэтому анимация должна завладеть вперед, но я хочупереверните анимацию в противоположном направлении - чтобы временная шкала могла быть перемещена вперед, назад - в зависимости от скорости прокрутки - чтобы эффект замедления или ускорения вступил в силу

Это первый шаг - для добавления дополнительныхсложные анимации, более сложные, с несколькими объектами.

Я пытался захватить детали перевода, чтобы нетронутый перевод x или y на месте не был переопределен - но я думаю, что есть ошибка ....

пожалуйста, просмотрите Получить значения translate3d для div?

// jsfiddle
https://jsfiddle.net/g10qe5m6/6/

var data = [{
  "structure": {
    "name": "square",
    "height": 30,
    "width": 30,
    "x": 10,
    "y": 10,
    "background": 'url("https://i.pinimg.com/originals/74/f3/5d/74f35d5885e8eb858e6af6b5a7844379.jpg")'
  },
  "frames": [{
    "create": [{
      "s": 0
    }, {
      "e": 0
    }]
  }, {
    "moveRight": [{
      "s": 1
    }, {
      "e": 400
    }]
  }, {
    "destroy": [{
      "s": 400
    }, {
      "e": 400
    }]
  }]
}]

//console.log(data)

function getCurrentValues(el) {
  var results = $(el).css('transform').match(/matrix(?:(3d)\(\d+(?:, \d+)*(?:, (\d+))(?:, (\d+))(?:, (\d+)), \d+\)|\(\d+(?:, \d+)*(?:, (\d+))(?:, (\d+))\))/)

if(!results) return [0, 0, 0];
if(results[1] == '3d') return results.slice(2,5);

results.push(0);
return results.slice(5, 8);
};


var animations = {
  createObj: function(obj) {
    //create object
    var block = $('<div></div>');
    $(block).addClass(obj.name);
    $(block).addClass("animatedblock");
    $(block).css("height", obj.height);
    $(block).css("width", obj.width);
    $(block).css("transform", 'translate(' + obj.x + 'px, ' + obj.y + 'px)');
    $(block).css("background", obj.background);
  $(block).css("background-size", "cover");

    $('.container').append($(block));
  },
  deleteObj: function(el) {
    //destroy object
    el.remove()
  },
  moveRight: function(el, pixels) {
    //el.css('')
    //move right

  console.log("x", getCurrentValues(el)[0])
   console.log("y", getCurrentValues(el)[1])

  el.css('transform', 'translate(' + pixels + 'px, ' + getCurrentValues(el)[1] + 'px');

    //el.css('transform', 'translate(' + pixels + 'px, ' + getCurrentValues(el).y + 'px');
  },
  moveLeft: function(el, pixels) {
    //move left     
    //el.css('transform', 'translate(' + -pixels + 'px, ' + getCurrentValues(el).y + 'px');


  console.log("x", getCurrentValues(el)[0])
   console.log("y", getCurrentValues(el)[1])


  el.css('transform', 'translate(' + -pixels + 'px, ' + getCurrentValues(el)[1] + 'px');

  },
  moveDown: function(el, pixels) {
    //move down     
    //el.css('transform', 'translate(' + getValues(el).x + 'px, ' + pixels + 'px)');


  el.css('transform', 'translate(' + getCurrentValues(el)[0] + 'px, ' + pixels + 'px');


  },
  moveUp: function(el, pixels) {
    //move up       
    // el.css('transform', 'translate(' + getValues(el).x + 'px, ' + -pixels + 'px)');

        el.css('transform', 'translate(' + getCurrentValues(el)[0] + 'px, ' + -pixels + 'px');

  }
}



//app.deleteObj($('.square'));

//data.skeleton

/*
    var instructor = {
      action: function(data, position) {

        console.log("position", position)

        $.each(data, function(i, item) {
          //alert(item.PageName);
          console.log("item", item.frames)
        });
      }
    }
*/


var frames = data[0].frames;

var instructor = {
  action: function(scroll, direction) {

    var sequence = [{
      "create": 0,
      "moveRight": 100,
      "moveDown": 200,
      "destroy": 400
    }]

    //if down - forward animation

    //if up - reverse animation

    ///use the data to detect what the block can do at what start and end frame
    if (scroll == 0) {
      //create block
      //animations.createObj(data[0].structure);
    }

    if (scroll > 100 && scroll < 400) {
      //move right
      animations.moveRight($('.square'), scroll);
    }


    if (scroll > 400 && scroll < 800) {
      //move right
      animations.moveDown($('.square'), scroll);
    }

    if (scroll > 800) {
      //animations.deleteObj($('.square'));
    }


    //move left
    //animations.moveLeft($('.square'), scroll);

  }
}



animations.createObj(data[0].structure);

var position = $(window).scrollTop();

$(window).scroll(function() {
  var scroll = $(window).scrollTop();
  console.log("scroll", scroll);

  if (scroll > position) {
    console.log('scrollDown');
    instructor.action(scroll, "down");
  } else {
    console.log('scrollUp');
    instructor.action(scroll, "up");
  }
  position = scroll;

});

1 Ответ

4 голосов
/ 30 июня 2019

Хотя вопрос слишком широкий, чтобы его можно было ответить в одном ответе, я постараюсь дать вам идею.Разбейте ваш код на небольшие модули для обработки событий прокрутки и анимации.Метод подписки используется для привязки слушателей событий в шаблоне Observable.Остальная часть кода не требует пояснений.Комментарий ниже, если у вас есть какие-либо вопросы.

let data = [{
    "structure": {
      "name": "square",
      "height": 30,
      "width": 30,
      "x": 0,
      "y": 0,
      "background": 'url("https://i.pinimg.com/originals/74/f3/5d/74f35d5885e8eb858e6af6b5a7844379.jpg")'
    },
    "frames": [{
      "animation": "move",
      "start": 0,
      "stop": 300,
      "startPositionX": 0,
      "startPositionY": 0,
      "endPositionX": 90,
      "endPositionY": 0,
    }, {
      "animation": "move",
      "start": 301,
      "stop": 600,
      "startPositionX": 90,
      "startPositionY": 0,
      "endPositionX": 90,
      "endPositionY": 80,
    }, {
      "animation": "move",
      "start": 601,
      "stop": 900,
      "startPositionX": 90,
      "startPositionY": 80,
      "endPositionX": 0,
      "endPositionY": 0,
    }, {
      "animation": "show",
      "start": 601,
      "stop": 9999,
      "positionX": 0,
      "positionY": 0,
    }],
  },
  {
    "structure": {
      "name": "pear",
      "height": 30,
      "width": 30,
      "x": 90,
      "y": 80,
      "background": 'url("https://i.pinimg.com/originals/74/f3/5d/74f35d5885e8eb858e6af6b5a7844379.jpg")'
    },
    "frames": [{
      "animation": "move",
      "start": 0,
      "stop": 300,
      "startPositionX": 90,
      "startPositionY": 80,
      "endPositionX": 0,
      "endPositionY": 80,
    }, {
      "animation": "move",
      "start": 301,
      "stop": 600,
      "startPositionX": 0,
      "startPositionY": 80,
      "endPositionX": 0,
      "endPositionY": 0,
    }, {
      "animation": "move",
      "start": 601,
      "stop": 900,
      "startPositionX": 0,
      "startPositionY": 0,
      "endPositionX": 90,
      "endPositionY": 80,
    }, {
      "animation": "show",
      "start": 601,
      "stop": 9999,
      "positionX": 90,
      "positionY": 80,
    }],
  }
]

let animations = {
  setup: function($container) {
    this.$container = $container;
    this.viewportWidth = $container.width();
    this.viewportHeight = $container.height();
  },
  createBlock: function(blockSpec) {
    let $block = $('<div>');
    $block.addClass(blockSpec.name);
    $block.addClass("animatedblock");
    $block.css("height", blockSpec.height);
    $block.css("width", blockSpec.width);
    $block.css("background", blockSpec.background);
    $block.css("background-size", "cover");
    this.$container.append($block);
    this.setPosition($block, blockSpec.x, blockSpec.y)
    return $block;
  },
  setPosition($block, x, y) {
    $block.css({
      left: x / 100 * this.viewportWidth,
      top: y / 100 * this.viewportHeight,
    });
  },
  moveBlock($block, frame, scrollProgress) {
    let blockPositionX = frame.startPositionX + scrollProgress * (frame.endPositionX - frame.startPositionX);
    let blockPositionY = frame.startPositionY + scrollProgress * (frame.endPositionY - frame.startPositionY);
    this.setPosition($block, blockPositionX, blockPositionY);
  },
  showBlock: function($block, frame) {
    $block.show()
    this.setPosition($block, frame.positionX, frame.positionY);
  },
  hideBlock: function($block) {
    $block.hide()
  },
}

class ScrollObserver {
  constructor() {
    let $window = $(window);
    this.STOP_DISPATCH = 'STOP_DISPATCH';
    this.subscribers = [];
    $window.scroll(event => this.dispatch($window.scrollTop()));
  }
  subscribe(subscriberFn) {
    this.subscribers.push(subscriberFn);
  }
  dispatch(scrollPosition) {
    for (let subscriberFn of this.subscribers) {
      if (subscriberFn(scrollPosition) == this.STOP_DISPATCH) break;
    }
  }
}

jQuery(function($) {
  animations.setup($('.container'));
  $(window).resize(event => animations.setup($('.container')));
  for (let obj of data) {
    let scrollObserver = new ScrollObserver();
    let blockSpec = obj.structure;
    let $block = animations.createBlock(blockSpec);
    for (let frame of obj.frames) {
      scrollObserver.subscribe(scrollPosition => {
        if (scrollPosition >= frame.start && scrollPosition <= frame.stop) {
          let scrollProgress = (scrollPosition - frame.start) / (frame.stop - frame.start);
          switch (frame.animation) {
            case 'move':
              animations.moveBlock($block, frame, scrollProgress);
              break;
            case 'show':
              animations.showBlock($block, frame);
          }
          return scrollObserver.STOP_DISPATCH;
        }
      });
    }
  }
});
body {
  height: 1500px;
}

.container {
  background: grey;
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: 100vw;
  box-sizing: content-box;
}

.animatedblock {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"></div>
...