Banana Sprite JS使用JSON数据定制前进和后退动画 [英] Banana sprite js bespoke forward and backward animations with json data

查看:103
本文介绍了Banana Sprite JS使用JSON数据定制前进和后退动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一些自定义的滚动动画-并希望开始探索制作一个简单块的动画。

I need to create some custom scroll animations - and wanted to start exploring animating a simple block.

使用json-我想提供块的骨架(类名,高度,宽度,背景),然后提供与滚动值相关的每个开始/结束帧的动作

Using json - I want to provide the skeleton for the block (classname, height, width, background), then the actions per start/end frames which relates to the scroll value.

我如何修改代码-使用数据json处理块的向前/向后动画

how do I modify the code -- to handle the forward/backward animations for the block using the data json

因此在此示例中。

-滚动为0时-或应用程序开始-创建块。

-- when the scroll is at 0 -- or start of application - create the block.

-如果滚动条在100-400的范围内-指示滚动条移动对。

-- if the scroll is between a range 100-400 - the scroll is instructed to move right.

-如果滚动条超过400,则破坏该块。

-- if the scroll hits over 400 - destroy the block.

所以动画要在前进方向上保持住,但是我想在相反方向上反转动画-因此时间轴可以向前,向后移动-取决于滚动速度-这样就可以控制慢动作或加速效果

so the animation is to take hold in a forward direction, but I want to reverse the animations in the opposite direction - so the timeline can be moved forward, backward - dependent on the speed of the scroll - so a slowmo or speedup affect can take hold

这是第一步-添加更复杂的动画,更长的复杂动画以及多个对象。

This is the first step - for adding more complicated animations, longer intricate ones, with multiple objects.

我试图捕获翻译细节,以使原汁原味的x或y翻译不会被覆盖-但我认为这是一个错误...。

I have tried to capture the translate details so the untouched x or y translation in place doesn't get overridden - but I think there is a bug....

请查看
获取a的translation3d值div?

// jsfiddle

< a href = https://jsfiddle.net/g10qe5m6/6/ rel = nofollow noreferrer> https://jsfiddle.net/g10qe5m6/6/

//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;

});


推荐答案

尽管问题过于笼统,无法一一解决答案,我会尽力给你一个想法。将代码分解为小模块,以处理滚动事件和动画操作。
subscription方法用于以Observable模式绑定事件侦听器。
代码的其余部分不言自明。如有疑问,请在下面评论。

Though the question is too broad to address in a single answer, I would try to give you an idea. Break your code to small modules to handle scroll event and animation actions. The subscribe method is used to bind event listeners in Observable pattern. The rest of the code is self explanatory. Comment below if you have any queries.

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>

这篇关于Banana Sprite JS使用JSON数据定制前进和后退动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆