那些好看的页面都是怎么做出来的——前端动效研究:JS篇

一起养成写作习惯!这是我参与「日新计划 4 月更文挑战」的第7天,点击查看活动详情。

这篇文章同样来自我们的约稿作者——杨鹏军同学,既上一篇3D地球后,鹏军同学这一容器英文期主要要聊的是动效场景~

一、前言

JS动效其实属于前端动效的进阶了,因为大部分网页的效果使用简单前端工程师的css微动效已经能够达到足够的视觉呈现效果,但是我们有时候去浏览一些品牌页面浏览器的历史,会发现他们的页面炫酷程度绝对不监控安装容器对桌面的压强怎么算简单的css就能够处理的:

iphone13Pro的官网页面就呈现监控系统出另人惊叹的视觉效果,其中用到了一些诸如渐变,视差错位,图形变换等常用前端动画技术。

结合华为云官网监控拍下东航客机坠落瞬间当前的动效场景,我们当前使用的两种核心js动效技术:

1.scrol电池l

2.req容器对桌面的压强怎么算uestAnimationFrame

我们分节研究。

二、scroll

滚动动画一般是对滚动条滚轮事件的监听,官网当前通过监听滚动条实现入场出场视差滚动动画

2.1 入场出场

入场出场的关键电池不耐用了怎么修复在于如何计算元素何时浏览器历史上的痕迹在哪里入场,何时出场。

入场

private isWillEnter(element: any) {
    let { enterClass, enterDiff, customEnterDiffAttr } = this.opts;
    if (element.classList.contains(enterClass)) return false;
    const customEnterDiff = parseFloat(element.getAttribute(customEnterDiffAttr));
    if (!isNaN(customEnterDiff)) {
        enterDiff = customEnterDiff;
    }
    const elementEnterLength = utils.getElementEnterLength(element);
    return elementEnterLength > enterDiff;
}

Ele浏览器网站删除了怎么恢复m电池型号ent浏览器推荐.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。

getElementEnterLength(element) {
    const rect = element.getBoundingClientRect();
    return window.innerHeight - rect.top;
}

ge监控系统tElementEnterLengt前端和后端哪个工资高h获得入场元素距离视窗底部浏览器怎么打开网站的高度,如果这个高度大于我们设定的入场高度,则触发入场动画。

那些好看的页面都是怎么做出来的——前端动效研究:JS篇

出场

private isWillOut(element: any) {
    let { outClass, outDiff, customOutDiffAttr } = this.opts;
    if (element.classList.contains(outClass)) return false;
    const customOutDiff = parseFloat(element.getAttribute(customOutDiffAttr));
    if (!isNaN(customOutDiff)) {
        outDiff = customOutDiff;
    }
    const elementEnterLength = utils.getElementEnterLength(element);
    return elementEnterLength < outDiff;
}

如果这个高度小于我们设定的退场高度,监控安装则触发出场动画。

监听滚动条改变元素style

window.addEventListener('scroll', () => {
    this.update();
});
public update() {
    const { enterClass, outClass, disableOut } = this.opts;
    this.elements.forEach((element: any) => {
        if (this.isWillEnter(element)) {
            element.classList.remove(outClass);
            element.classList.add(enterClass);
        } else if (!disableOut && this.isWillOut(element)) {
            element.classList.remove(enterClass);
            element.classList.add(outClass);
        }
    });
}

2.2 视差滚动

视差滚动的基本原理类似电池不耐用了怎么修复,监听滚动条与元素的位置,触发对应的元素样式变更,相对于入场出场,视差滚动还需要关注元素的动效进度信息。监控安装流程

public setInnersStyle() {
    const containerMoveRatio = this.opts.neverEnd
        ? utils.limitNumber(this.getContainerMoveRatio(), 0)
        : utils.limitNumber(this.getContainerMoveRatio(), 0, 1);
    this.dispatchWatcher(containerMoveRatio);
    if (this.oldMoveRatio !== containerMoveRatio) {
        this.oldMoveRatio = containerMoveRatio;
        this.events.emit('progress', this, containerMoveRatio);
    }
}
private getContainerMoveRatio() {
    const top2Window = utils.getTop2Window(this.$container[0]);
    const baseRange = this.opts.endTop - this.opts.startTop;
    return (top2Window - this.opts.startTop) / baseRange;
}

我们需要计算滚动容器当前滚动的距离占总长距离的百分比,然后将百分比转化为元素移动位置的百分比,作出视动画的效果

public update(progress) {
    let { el, startProgress, endProgress, startStyleValues, endStyleValues, styleRenderers } = this;
    if (startProgress === undefined) {
        startProgress = 0;
    }
    let pro = utils.limitNumber(progress, startProgress, endProgress);
    if (pro < startProgress || pro > endProgress) return;
    const ratio = endProgress !== undefined ?
        (pro - startProgress) / (endProgress - startProgress) :
        (pro - startProgress) / (1 - startProgress);
    const currentValues = utils.getStyleValuesByRatio(startStyleValues, endStyleValues, ratio);
    const style = {};
    Object.keys(styleRenderers).forEach(property => {
        style[property] = styleRenderers[property](currentValues[property]);
    });
    $(el).css(style);
}

那些好看的页面都是怎么做出来的——前端动效研究:JS篇

华为云的品牌页就通过这种原理实现了错位展示效果:

那些好看的页面都是怎么做出来的——前端动效研究:JS篇

www.huawei监控安装流程cloud.com/about/overv…

三、requ容器云estAnimationFrame

引入MDN的解释:

window.requestAnimationF容器中有某种酒精含量的酒精溶液rame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定电池型号5号和7号的回浏览器历史记录设置调函数更新动画。该方法需要传入一个回调函数作为参数,该浏览器推荐回调函数会在浏览器下一次重绘之前执行

注意前端开发需要掌握什么技术:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()

其实就是递归调用自己不断进行前端下一帧画面的宣传,因为在大多数浏览器里,当requestAnimationFrame()运行在后台标签页或者隐藏的video前端开发里时,requestAnimationFrame()会被暂停调用以提升性能和电池寿命。

实例(来自MDN):

const element = document.getElementById('some-element-you-want-to-animate');
let start;
function step(timestamp) {
  if (start === undefined)
    start = timestamp;
  const elapsed = timestamp - start;
  //这里使用`Math.min()`确保元素刚好停在200px的位置。
  element.style.transform = 'translateX(' + Math.min(0.1 * elapsed, 200) + 'px)';
  if (elapsed < 2000) { // 在两秒后停止动画
    window.requestAnimationFrame(step);
  }
}
window.requestAnimationFrame(step);

很多炫酷的js动效,包括3D场景动效,其中一个核电池不耐用了怎么修复心原理就是requestAnimationFrame的循环调用。

3.1 PortalAnim监控家用远程手机ation 通用js前端开发动效

PortalAnimati监控拍下东航客机坠落瞬间on的通用js动效又是针对视差动效的前端开发进一步升级监控app下载,即计算p电池品牌排行榜rogress进度进度百监控摄像头分比配合缓动函数曲线识别计算元素或者对象的属性与样式电池回收

外层动画引擎

  public play() {
    this.raf = requestAnimationFrame(t => this.step(t));
  }
  public step(time) {
    const animeInstancesLen = this.instances.length;
    if (animeInstancesLen) {
      for (let i = 0; i < animeInstancesLen; i++) {
        if (this.instances[i]) {
          this.instances[i].tick(time);
        }
      }
      this.play();
    } else {
      cancelAnimationFrame(this.raf);
      this.raf = null;
    }
  }
  public animeEngine() {
    this.play();
  }

遍历初始化PortalAnimation的相关实例,每一次重绘触前端开发需要学什么发动效状态更新

动效执行实例

const baseOptions = {
  start: 0,
  end: 0,
  duration: 1000,
  delay: 0,
  loop: false,
  update: null,
  complete: null,
};

baseOptions主要想表达一个js动画要执行,我们需要电池型号告诉动效库实例的初始状态,结束状态,持续时间,延迟多久,是否循环,并且可以前端开发需要掌握什么技术在动效更新和结束时加入一些回调函数。

计算动效进度

const eased = isNaN(elapsed) ? 1 : tween.easing(elapsed);
for (let n = 0; n < toNumbersLength; n++) {
  let value;
  const toNumber = tween.to.numbers[n];
  const fromNumber = tween.from.numbers[n] || 0;
  value = fromNumber + eased * (toNumber - fromNumber);
  if (round) {
    if (!(tween.isColor && n > 2)) {
      value = Math.round(value * round) / round;
    }
  }
  numbers.push(value);
}

除了本身的数值百分比,我们还需要根据使用人员选择的缓动函数方式进行二次计算。

部分缓动曲线

const baseEasings = ['Quad', 'Cubic', 'Quart', 'Quint', 'Expo'];
baseEasings.forEach((name, i) => {
	functionEasings[name] = () => time => Math.pow(time, i + 2);
});
// a b参数专属elastic ease
Object.keys(functionEasings).forEach(name => {
const easeIn = functionEasings[name];
eases['easeIn' + name] = easeIn;
eases['easeOut' + name] = (a, b) => time => 1 - easeIn(a, b)(1 - time);
eases['easeInOut' + name] = (a, b) => time => time < 0.5 ? easeIn(a, b)(time * 2) / 2 : 1 - easeIn(a, b)(time * -2 + 2) / 2;
eases['easeOutIn' + name] = (a, b) => time => time < 0.5 ? (1 - easeIn(a, b)(1 - time * 2)) / 2 : (easeIn(a, b)(time * 2 - 1) + 1) / 2;
});

应用

PortalAnimation动效库通过通用动效可以实现非常丰富多样的动效,包括数字动画,帧动前端和后端的区别画,物体运动动画,我们使用简单的函数调用就可以轻松做到:

数字动画

那些好看的页面都是怎么做出来的——前端动效研究:JS篇

运动曲线动画

那些好看的页面都是怎么做出来的——前端动效研究:JS篇

更多js动效访问Port前端开发需要掌握什么技术alAnimation查看。

3.2 3D动效

Three.j监控眼s基础动效也是通过requestAnimationFrame的原理实现的,具体方式就是通过渲染器renderer不断更新场景容器是什么与摄像机实现:

function animate() {
    requestAnimationFrame( animate );
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render( scene, camera );
};
animate();

那些好看的页面都是怎么做出来的——前端动效研究:JS篇

当然我们借浏览器推荐助一些类似于po容器设计rtal animation的动画插件可以实电池回收现更加酷炫的动画效果,这个我们后续在前端动效3D的篇章介绍。

我们是华为云的Web能力中心团队,专注于大前端工具建设,团队业务涉及低代码平台浏览器推荐、UI组件库、前端监控、前端门电池型号禁、API编排等方向,我容器技术们的愿景是将前端技术再更多的领域落地开花,并通过QCon、GMTC等各类平台进行赋能分享,交流学习,如果你也认可我们的“诗和远方”,欢迎关注我们的账号~

发表评论

提供最优质的资源集合

立即查看 了解详情