最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【你的性格主导色】揭秘

    正文概述 掘金(hezf)   2021-08-12   484

    介绍

    《你的性格主导色》是今年网易云音乐前端团队开发的一款测试用户主导色的 H5 应用,上线后反响很好,刷爆了微博和朋友圈。

    项目的主要开发者 imyzf 发表了一篇文章《官方揭秘!你的颜色是这样算出来的》,解释了一些动效和最后主导色的计算方面的问题。但由于涉及到了具体的业务,所以作者没有开源出源码,但是热心的作者给了很多的提示。我就是根据这些提示,揭秘了我比较感兴趣的部分。

    在线 Demo

    由于一直没有在生产环境中使用Vue3.0vite,所以源码部分我使用了 Vue3.0+vite实现。

    页面预加载

    由于活动页面使用了大量的视频和动效等,所以想在用户阅读选择题目的过程中把下一页的页面渲染完毕,这样切换到下一页面的时候会很流畅,体验很好。

    最初就想着怎么利用 vue-router 完成页面的预加载。但是搞了一圈发现,都是基于webpack或者vite的懒加载,提前加载了一些资源,并不会提前渲染出页面。

    后来通过看vue-router文档,才找到了灵感,利用命名视图,同时展示 2 个视图,使用css隐藏下一页,这时候虽然不显示,但是页面已经渲染出来了。

    通过修改router-viewname 属性,完成页面的切换。也就是说,其实我的路由是没有变化的。

    // App.vue
    <template>
      <router-view :name="currentViewName"></router-view>
      <router-view :name="nextViewName"></router-view>
    </template>
    
    // 注意 ,这里使用两个 viewName 完成了页面的跳转,next 的页面被预加载
    const currentViewName = computed(() => store.getters.currentViewName);
    const nextViewName = computed(() => store.getters.nextViewName);
    
    // router的定义部分
    const routes = [
      {
        path: '/',
        components: {
          default: Index1,
          index2: Index2,
          session1: Session1,
          session2: Session2,
          session5: Session5
        }
      }
    ];
    

    看上面的代码,Index1Index2Session1等其实就是每一页的组件了,通过修改currentViewNamenextViewName就可以达到页面切换的目的。

    最终的效果是下图这样的,下一页已经提前渲染出来:

    【你的性格主导色】揭秘

    翻页动效

    作者提示说使用canvas实现了页面切换时候的幕布拉动效果,主要运用了最核心的 canvas APIbezierCurveTo

    通过查询得知,bezierCurveTo 需要 3 个 点用来绘制三次贝赛尔曲线,在线体验

    看下图,想要实现拉动动画,P1 P2 P3X轴坐标需要持续变化,然后绘制曲线,就能够实现拉动的效果了。

    【你的性格主导色】揭秘

    我这里使用了比较轻量的JavaScript 动画库animejs,用来控制上面几个点的持续移动。3 个动画效果分别移动了P1 P2 P3X轴坐标 ,再配合曲线的绘制,就达到了基本的拉动幕布效果。

      const heights = [0, 0.5 * pageHeight, pageHeight];
      points = {
        p1: {
          x: pageWidth,
          y: heights[0]
        },
        p2: {
          x: pageWidth,
          y: heights[1]
        },
        p3: {
          x: pageWidth,
          y: heights[2]
        },
        p4: {
          x: pageWidth,
          y: heights[2]
        },
        p5: {
          x: pageWidth,
          y: heights[0]
        }
      };
    
      // P1点的变化
      anime({
        targets: points.p1,
        x: 0,
        easing: 'easeInQuart',
        delay: 50,
        duration: 500
      });
    
      // P2点的变化
      anime({
        targets: points.p2,
        x: 0,
        easing: 'easeInSine',
        duration: 500
      });
    
      anime({
        targets: points.p2,
        y: 0.6 * pageHeight,
        easing: 'easeInSine',
        duration: 500
      });
    
      // P3点的变化
      anime({
        targets: points.p3,
        x: 0,
        easing: 'easeInQuart',
        delay: 50,
        duration: 500
      });
    
      // 画曲线
      anime({
        duration: 550,
        update: function () {
          // 清除上一次的绘制
          ctx.clearRect(0, 0, pageWidth, pageHeight);
          ctx.beginPath();
          ctx.moveTo(points.p1.x, points.p1.y);
          // 幕布的上半区域
          ctx.bezierCurveTo(
            points.p1.x,
            points.p1.y,
            points.p2.x,
            points.p2.y - 0.2 * pageHeight,
            points.p2.x,
            points.p2.y
          );
          // 幕布的下半区域
          ctx.bezierCurveTo(
            points.p2.x,
            points.p2.y + 0.2 * pageHeight,
            points.p3.x,
            points.p3.y,
            points.p3.x,
            points.p3.y
          );
          // 已拉动部分的矩形区域
          ctx.lineTo(points.p4.x, points.p4.y);
          ctx.lineTo(points.p5.x, points.p5.y);
          ctx.closePath();
          ctx.fill();
          ctx.strokeStyle = '#f1f1f1';
          ctx.stroke();
        }
      });
    

    最终完成的效果是这样的:

    【你的性格主导色】揭秘

    这个动效由于每一页都需要使用,所以考虑完成一个通用的全局组件。

    考虑到使用的时候一般组件需要写到vue 模板上面,很不方便,所以最好通过一个全局函数直接显示这段动效,类似于showAnimation();

    首先需要完成一个独立的组件,由于想覆盖掉页面的所有信息,所以使用了 Vue3.0 最新提供的teleport 组件:

    <!-- 这个canvas会被渲染为 app 的子级 -->
      <teleport to="#app">
        <canvas class="mask-canvas" ref="canvas" :class="{ 'mask-canvas-posi': isShow }"></canvas>
      </teleport>
    

    然后需要把组件通过 Vue 插件的方式注册到全局属性,由于我想使用 Composition API ,所以最终决定使用 provide + inject 的方式注册和使用全局 property。一般的情况下使用app.config.globalProperties就可以了,但是这种配合Composition API写起来会比较麻烦,不推荐。

    (Mask as any).install = (app: App): void => {
      // Vue3 的 Composition API 建议使用 provide + inject 的方式注册和使用全局 property
      app.provide('mask', Mask);
    };
    
    // 使用的时候
    const Mask = inject('mask');
    

    最后,由于翻页动效和路由都在一起使用,就继续封装了个useNext函数,这样在一般的view组件使用的话,就非常简单了,同时做了翻页动效和翻页的操作:

    nextPage();
    

    到这里我可以夸夸Composition API了,非常的简单和方便,通过这个全局通用组件的封装,我彻底喜欢上了这种方式。

    云层动效

    这部分是我觉得最有趣的,以前用three.js实现过一个 3D 照片墙,但是这个云层动效真的牛,也是最难破解的,还好被我搞定了,下篇详细说明破解的过程。

    【你的性格主导色】揭秘

    源码

    最后放上源码,感兴趣的同学可以看一下,欢迎 Star 和提出建议。


    起源地下载网 » 【你的性格主导色】揭秘

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元