如何为Dart中的滚动动画?

爱德

我想平滑滚动到页面的一部分。在jQuery中是这样完成的:

$('html, body').animate({
    scrollTop: $('#anchorOfMyTargetSection').offset().top
}, 'slow');

在Dart中,我可以进行滚动,但是我不知道如何对其进行动画处理:

int targetSection = querySelector('#anchorOfMyTargetSection').offsetTop;
window.scrollTo( 0, targetSection );

更具体地说,我正在做一个页面,其中包含指向自身页面中各个部分的链接。

这里是链接:

<nav>
    <ul class="nav-list">
        <li><a href="http://example.com/#title">Home</a></li>
        <li><a href="http://example.com/#about">About us</a></li>
        <li><a href="http://example.com/#products">Products</a></li>
        <li><a href="http://example.com/#services">Services</a></li>
        <li><a href="http://example.com/#contact">Contact</a></li>
    </ul>
</nav>

这是完整的jQuery代码:

// Generated by LiveScript 1.2.0
var smoothScrolling;
smoothScrolling = function(selector, offset){
  return $(selector).click(function(click){
    var link, anchor;
    click.preventDefault();
    link = $(this).attr('href');
    anchor = link.substring(link.indexOf('#'));
    return $('html ,body').animate({
      scrollTop: $(anchor).offset().top + offset
    }, 'slow');
  });
};
smoothScrolling('.nav-list a', -45);

这是Dart代码(当然没有动画部分):

import 'dart:html';

void main() {
  smoothScrollingOffset = -45;
  querySelectorAll('.nav-list a').onClick.listen(smoothScrolling);
}

int smoothScrollingOffset = 0;

void smoothScrolling(MouseEvent click) {
  click.preventDefault();
  String link = click.target.toString();
  String anchor = link.substring( link.indexOf('#') );
  int targetPosition = querySelector('$anchor').offsetTop;

  window.scrollTo( 0 , targetPosition + smoothScrollingOffset );
}

请记住,我不是Dart的新手,还是一般编程的新手。如果您发现Dart代码中无法改进的地方,也请告诉它。

爱德

更新:仅使用dart:html库。

这些是链接

<nav>
    <ul class="nav-list">
        <li><a href="http://example.com/#title">Home</a></li>
        <li><a href="http://example.com/#about">About us</a></li>
        <li><a href="http://example.com/#products">Products</a></li>
        <li><a href="http://example.com/#services">Services</a></li>
        <li><a href="http://example.com/#contact">Contact</a></li>
    </ul>
</nav>

在您的Dart代码中,导入dart:html库以访问DOM。

import 'dart:html';

这是函数,它的作用是:

  • 单击链接时,将对其进行分析并提取锚点
  • 它使用锚来确定哪个元素/节比您要查找的
  • 然后获取元素/截面位置
  • 滚动到元素/部分

void smoothScrolling(String selector, {int offset: 0, int duration: 500}) {

  // The detection of the clicks and the selectors of the links are specified at the bottom of the function
  // Let's suppose you click a link to visit 'http://example.com/#contact'
  // When you click the link
  void trigger(MouseEvent click) {
    // Prevent to visit the resources, like normally does
    click.preventDefault();
    // Get the resource link of the clicked element. In this case: 'http://example.com/#contact'
    String link = click.target.toString();
    // Extract the anchor. In this case from 'http://example.com/#contact' will extract '#contact'
    String anchor = link.substring( link.indexOf('#') );
    // With the extracted anchor, search the corresponding element and get his position.
    // In this case gets the position of the element with 'contact' in the 'id' attribute 
    int targetPosition = querySelector('$anchor').offsetTop;

    // Before to translate to the element,
    // you can specify if you want to translate some distance before or after the element
    targetPosition += offset;

    // Let's move in direction to the section
    // We know than in Dart there are 60 frames per second, that means a frame duration is 
    // 1000 milliseconds divided in 60 frames = per frame is 16.66 milliseconds long.
    // But 16.66 milliseconds multiplied by 60 = 999.99 milliseconds. That is ALMOST a second.
    // And that means than there will be 59.99 frames in 999.99 milliseconds
    // But we cannot handle frame fractions, we should round frames to integers
    // So 59.99 frames will be rounded to 60 frames

    // Calculate the total number of frames
    int totalFrames = ( duration / (1000 / 60) ).round();
    // The first animation frame will be the number 1, the number 0 will be the start point
    int currentFrame = 0;
    // In this case the start point will be the current position
    int currentPosition = window.scrollY;
    // The end point will be the target position, we should know how many distance there is between the start and end point.
    // The positive and negative numbers represents the same distance, that means than 'y' and '-y' are the same.
    // Example: 10 and -10 are the same distance.

    // Calculate the distance between the start and end point.
    int distanceBetween =  targetPosition - currentPosition;
    // Then calculate how many distance should move per frame
    num distancePerFrame = distanceBetween / totalFrames;

    // The animation function is triggered by first time more later in the code
    // And when is triggered
    void animation(num frame) { 
      // First we look the number of the frame we are going to run.
      // When all the frames are complete the animation function will not be executed again
      if ( totalFrames >= currentFrame ) {

        // In every frame we are going to move some distance with direction to the target.
        // The direction (in this case will be only up or down) depends of the 'distanceBetween' number.
        // Let's explore this part with an example: You are 10 pixels from your target, your target is at the point 20,
        // Remember, to calculate the distance between you and the target we do 'targetPosition - currentPosition'.
        // If you are 10 pixels on from the target (at the point 10) the result will be: 20 - 10 = 10.
        // If you are 10 pixels down from the target (at the point 30) the result will be: 20 - 30 = -10.
        // You see how the number is the same but with different polarity?. And 10 and - 10 represent the same distance
        // The direction depends of the number 0, if you move closer to the 0 you will go down, if you move away the 0 you will move up.
        // Let's move 5 pixels:
        // 10 + 5 = 15. You will move down, because you will be more away of the 0, your target is at the number 20. 
        // -10 + 5 = -5. You will move up, because you will be more closer to the 0, your target is at the number 0.

        // Let's move to the point where we should be in this frame
        window.scrollTo( 0, currentPosition );
        // Calculate the point where we should be in the next frame
        currentPosition += distancePerFrame;

        // We get ready to execute the next frame
        currentFrame++;
        // When the time of this frame (16.66 milliseconds) is complete immediately starts the next frame.
        window.animationFrame.then(animation);      
      }
    } 

    // Here is triggered the animation by first time
    window.animationFrame.then(animation);  
  }

  // Here are the links' selectors and the detection of the clicks
  querySelectorAll(selector).onClick.listen(trigger);
}

要使用该功能,我们应该指定链接的选择器,并可选地指定偏移量和/或滚动持续时间。

void main() {
  // To use the function we should specify the links' selectors,
  // and optionally an offset and/or the duration of the scrolling,
  smoothScrolling('.nav-list a',
                  offset: -45,
                  duration: 2500);
}

动画

我将解释要点,所有细节均在代码中进行了注释。

值得一提的是,除了我使用Blender很长时间以来,这是一个开放源代码3D动画软件,这要归功于Blender,我进入了编程领域。所以我知道我在说动画。

1. Dart文档

这是第一个困难。如果您在Dart文档中搜索一些要处理动画的内容,则会发现animationFrame,这似乎还可以。

但是首先,什么是框架?也许您听到了每秒24帧的声音。这意味着,在这种情况下,一帧为1秒除以24 =每帧为0.0416秒长=每41.66毫秒为一帧。

然后让我们将帧作为时间块来处理,并且通常将这些时间块作为整数来处理。我们通常这样说:该屏幕为每秒24帧,但不是这样的屏幕为每秒24.6帧。

但是文档中有一个问题。

Future完成到一个时间戳,该时间戳表示自页面开始加载以来经过的毫秒数的浮点值(这也是对animationFrame的调用中的时间戳)。

好的,这意味着比我可以知道页面中的用户已有多少时间,但是没有任何关于每秒我可以知道多少次的引用,而这是我在谈论框架时希望知道的内容:一秒钟有几帧?

2. Dart框架

经过一些实验,我发现在Dart中每秒有60帧

1000毫秒分为60帧=每帧长16.66毫秒。但是16.66毫秒乘以60 = 999.99毫秒。那几乎是一秒钟。这意味着在999.99毫秒内将有59.99帧。但是我们无法处理帧分数,我们应该将帧四舍五入为整数。因此59.99帧将舍入为60帧

请记住,一帧的长度为16.66毫秒

3. Dart中的动画

// Set the duration of your animation in milliseconds
int duration = 1000;
// Calculate the total number of frames
int totalFrames = ( duration / (1000 / 60) ).round();
// The first animation frame will be the number 1, the number 0 will be the start point
int currentFrame = 0;

// The animation function is triggered by first time more later in the code
// And when is triggered
void animation(num frame) { 
  // First we look the number of the frame we are going to run.
  // When all the frames are complete the animation function will not be executed again
  if ( totalFrames >= currentFrame ) {

    // =========================================== 
    // Here what we are going to do in every frame 
    // ===========================================        

    // We get ready to execute the next frame
    currentFrame++;
    // When the time of this frame (16.66 milliseconds) is complete immediately starts the next frame.
    window.animationFrame.then(animation);      
  }
} 

// Here is triggered the animation by first time
window.animationFrame.then(animation);

注意:

1.我在编写smoothScrolling函数时发现了一个错误,但是不用担心,仅会影响Dart虚拟机中的JavaScript编译效果。我试图找出导致错误的确切原因,因此可以报告它。

我发现的是在动画函数make中使用数字distancePerFrame而不是函数不循环。

2.从技术上讲,这不是“平滑滚动”,而是“线性滚动”。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在NavigationView中滚动动画

来自分类Dev

jQuery中的滚动动画

来自分类Dev

jQuery中的滚动动画

来自分类Dev

如何在Google搜索中实现ActionBar滚动动画?

来自分类Dev

如何在颤动中制作水平滚动动画

来自分类Dev

在CSS中悬停时如何停止自动滚动动画?

来自分类Dev

如何为Google Plus / Google报亭等滚动动画制作recyclerview?

来自分类Dev

如何为UIView创建拖动动画?

来自分类Dev

如何制作水平/垂直滚动动画?

来自分类Dev

ListView滚动动画

来自分类Dev

如何为FAB(扩展)创建新的活动动画

来自分类Dev

如何为UIButton iOS创建脉动动画?

来自分类Dev

如何向此Jquery滚动动画添加Easing属性

来自分类Dev

如何在列表视图中滚动动画?

来自分类Dev

如何使滚动动画工作(轮盘赌)

来自分类Dev

CSS滚动动画在Edge中不起作用

来自分类Dev

Android:WebView滚动动画

来自分类Dev

禁用ViewPager滚动动画

来自分类Dev

停止窗口滚动动画

来自分类Dev

RecyclerView 平滑滚动动画

来自分类Dev

如何为WinForms滚动制作动画

来自分类Dev

(jQuery)当滚动显示div时,如何为可滚动div中的元素设置动画?

来自分类Dev

(jQuery)当滚动显示div时,如何为可滚动div中的元素设置动画?

来自分类Dev

Ionic:如何在没有滚动动画的情况下滚动到页面底部?

来自分类Dev

滚动到HTML文件中的位置-带有滚动动画

来自分类Dev

滚动动画代码不起作用

来自分类Dev

软滚动动画NSScrollView scrollToPoint:

来自分类Dev

导航栏特定的jQuery滚动动画

来自分类Dev

google plus recyclerView滚动动画