整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

带你手写一个轮播图之JavaScript逻辑实现

了控制篇幅,本打算分3篇文章来讲述轮播图实现的,后来想了想,JS代码量其实很少,完全没必要,所以这篇文章就是收尾。

昨天,我们完成了结构和布局设计,今天我们来完成JavaScript逻辑部分。我这人比较有代码洁癖,不喜欢过多的变量污染全局作用域,习惯使用自执行的匿名函数包裹一个功能块。我们所有的JS代码都在如下函数内部编写:

(function () {
  // ... ... 我们的代码都写到这儿
})();

我们的程序中需要用到多个DOM元素,所以我们先拿到它们的引用存储到变量中。

/** @type {HTMLDivElement} 轮播图容器 */
  const carouselWrapper = document.querySelector('.carousel-wrapper')
  /** @type {HTMLUListElement} banner列表元素 */
  const slides = carouselWrapper.querySelector('.slides')
  /** @type {HTMLDivElement} 指示器 */
  const indicator = carouselWrapper.querySelector('.indicators')
  /** @type {NodeListOf<HTMLLIElement>} 指示器节点列表 */
  const indicatorItems = indicator.querySelectorAll('.indicator-item')
  /** @type {HTMLUListElement} 导航按钮列表元素 */
  const nav = carouselWrapper.querySelector('.nav')

接下来,我们定义一些常量和变量,建议大家定义常量名使用全大写字母下划线分割。

 /** 活动类名 */
  const ACTIVE_CLS_NAME = 'active'
  /** 左导航按钮类名 */
  const CLS_NAME_NAV_LEFT = 'nav-left'
  /** 右导航按钮类名 */
  const CLS_NAME_NAV_RIGHT = 'nav-right'
  /** 取消过渡的类名 */
  const CLS_NAME_NO_TRANSITION = 'no-transition'
  /** 定时器间隔 */
  const TIMER_DELAY = 3000

  /** 定时器id */
  let timerId
  /** 当前指示器索引 */
  let currentIndex = 0
  /** 当前banner索引 */
  let currentslideItemIndex = 0
  /** 过渡结束标识 */
  let transitionendFlag = true

要做到左右滚动的无缝切换,我们必须至少拷贝banner列表中的第一和最后一个元素,将其追加到banner列表尾部,并更新banner列表的宽度。为了节省代码,我完全拷贝了一份banner列表的子元素。我们用一个函数来做这件事,代码如下:

function updateSlides() {
    slides.innerHTML += slides.innerHTML
    slides.style.width = `${slides.childElementCount * 100}%`
  }

当用户单击指示器项的时候,我们需要切换当前显示的banner图。首先需要确定被单击指示器项的索引。我们用一个函数来实现,代码如下:

function getTargetIndex(el) {
    for (let i = 0, len = indicatorItems.length; i < len; i++) {
      if (indicatorItems[i] === el) {
        return i
      }
    }
    return -1
  }

索引确定了,我们需要根据索引来更新X轴的平移值。当然,要实现左右滚动,我们还有其它实现方案,例如:改变可滚动元素的滚动条位置,改变元素的左右定位等。那么,为什么使用3D平移变换呢?原因之一就是,浏览器会对3D平移变换开启GPU硬件加速渲染,以获得更好的性能,直观感受就是动画非常丝滑,毫无拖泥带水之感。我们用一个函数来更新X轴平移,代码如下:

function updateTranslateX(index, targetIndex = -1) {
    // 如果过渡没有结束,直接返回
    if (!transitionendFlag) return
    // 当前指示器移除活动类
    indicatorItems[currentIndex].classList.remove(ACTIVE_CLS_NAME)
    // 如果没有提供目标索引,就把index赋给它
    if (targetIndex < 0) {
      targetIndex = index
    }
    // 目标指示器添加活动类
    indicatorItems[targetIndex].classList.add(ACTIVE_CLS_NAME)
    // 将当前索引设为目标索引
    currentIndex = targetIndex
    // 将当前banner索引设为index
    currentslideItemIndex = index
    // 改变banner列表元素的X轴平移变换
    slides.style.transform = `translateX(-${index / slides.childElementCount * 100}%)`
  }

以下是指示器单击处理函数的实现。这个代码很简单,首先获取目标指示器项的索引,如果找到了,就根据该索引更新banner列表的X轴平移。

/** @param {MouseEvent} e */
  function indicatorClickHandler(e) {
    const index = getTargetIndex(e.target)
    index >= 0 && updateTranslateX(index)
  }

接下来,我们实现左右导航按钮的单击。首先,我们需要一个向左和向右滚动的函数,代码如下:

function toNext() {
    // 指示器项的数量
    const len = indicatorItems.length
    if (currentIndex < len) {
      if (currentIndex === len - 1) {
        // 继续滚动到下一个索引位置,并将目标索引设为0
        updateTranslateX(currentIndex + 1, 0)
      } else {
        updateTranslateX(currentIndex + 1)
      }
    } else {
      updateTranslateX(0)
    }
  }

  function toPrev() {
    const len = indicatorItems.length
    if (currentIndex < 1) {
      // 去掉过渡
      slides.classList.add(CLS_NAME_NO_TRANSITION)
      // 让索引为len的banner图可见
      updateTranslateX(len, len - 1)
      setTimeout(() => {
        // 添加过渡
        slides.classList.remove(CLS_NAME_NO_TRANSITION)
        // 让索引为len-1的banner图可见,此时有过渡
        updateTranslateX(len - 1)
      }, 0)
    } else {
      updateTranslateX(currentIndex - 1)
    }
  }

以下是左右导航按钮单击事件处理函数的实现。我们根据是否包含指定的类名,来判断单击的哪个按钮,进而执行不同的导航函数。

/** @param {MouseEvent} e */
  function navClickHandler(e) {
    /** @type {{target: HTMLElement}} */
    const { target } = e
    if (target.classList.contains(CLS_NAME_NAV_RIGHT)) {
      toNext()
    } else if (target.classList.contains(CLS_NAME_NAV_LEFT)) {
      toPrev()
    }
  }

我们还需要监听banner列表的过渡开始和结束事件。过渡开始事件处理函数非常简单,只是将过渡结束标志设为了false,代码如下:

function slidesTransitionstartHandler(e) {
    transitionendFlag = false
  }

下面是过渡结束事件处理函数定义,其实也很简单。

  function slidesTransitionendHandler(e) {
    transitionendFlag = true
    if (currentslideItemIndex >= indicatorItems.length) {
      // 取消过渡
      slides.classList.add(CLS_NAME_NO_TRANSITION)
      updateTranslateX(0)
      setTimeout(() => {
        // 再添加回过渡
        slides.classList.remove(CLS_NAME_NO_TRANSITION)
      }, 0)
    }
  }

我们还需要让轮播图可以间隔一定时间自动切换。所以,我们需要实现开始和结束定时器的函数。这两个函数非常简单,代码如下:

function startTimer() {
    timerId = setInterval(toNext, TIMER_DELAY)
  }

  function stopTimer() {
    clearInterval(timerId)
    timerId = null
  }

现在,是时候让我们的轮播图动起来了。我们首先调用更新banner列表函数,然后开始定时器,最后注册事件监听器。

  updateSlides()
  startTimer()
  // 指针进入容器的时候停止定时器
  carouselWrapper.addEventListener('mouseenter', stopTimer)
  // 指针离开容器的时候开始定时器
  carouselWrapper.addEventListener('mouseleave', startTimer)
  nav.addEventListener('click', navClickHandler)
  indicator.addEventListener("click", indicatorClickHandler)
  slides.addEventListener('transitionstart', slidesTransitionstartHandler)
  slides.addEventListener('transitionend', slidesTransitionendHandler)

最终实现的效果图如下:

童鞋们都学废了吗?是不是很简单?感谢阅读!

不多说,直接进入正题。

首先,图片轮播类的视频该怎么做?

如何剪辑“图片轮播”、“卡点视频”?详细的制作步骤介绍 江苏麒麟互娱

步骤一:选择一张素色背景,或是你心仪的背景,但你要知道这张背景的色调一定要配合接下来你的几张轮播图;

步骤二:准备好你的轮播图片(至少五张),图片尺寸一致,记得做好修图。不懂PS的,那就出绝招,拿手的美图秀秀、美颜相机修图;

步骤三;下载并打开你的视频剪辑工具:剪映;点击开始创作;

步骤四:选择那种背景图添加到项目,回到剪辑页面,拖拉白色框至适合的视频播放时间,15秒内;预留出两秒的背景展示;

步骤五:在预留两秒的背景图上添加文本,选择样式、花字、气泡;

步骤六:看到下面选项“画中画”,添加第一张轮播图,拖动适合的播放秒数:控制在1.5-2秒;依次按照此步骤添加剩下的几张轮播图;

步骤七:添加文本在几张轮播图上,同样选择样式、花字…

步骤八:你可以尝试播放此视频看下效果;添加音频,选择热门、合适的音乐,当然你也可以录音;注意在你的视频结尾处,可能还有一部分的音乐延长,你可以进行分割并删除



如何剪辑“图片轮播”、“卡点视频”?详细的制作步骤介绍 江苏麒麟互娱

再来看下完整的图片轮播的视频,至于特效和贴纸,你可适当添加,简单就是美。接下来,我们说说卡点视频,快速便捷的方式制作。

步骤一:可以选择多张图片或是一段或几段视频做卡点

步骤二:下载并打开美册,上面有很多抖音视频的模板下载并提供参考使用

步骤三:选择你喜欢的模板,根据要求添加图片、视频,同样注意每段播放时间不超过2秒,当然你可以加上一段小视频和多张图配合做卡点,像:武林外传的“嫂子”+真人图片

步骤四:可能你选择的卡点视频模板会自带卡点音乐;如果你想更换卡点音乐,可以保存已经做好的视频,重新到剪映中打开。

步骤五:选择你喜欢的卡点音乐,回到视频剪辑,看到下面的音频“踩点”,完成即可

步骤六:和上面图片轮播一样的最后一步。

如何剪辑“图片轮播”、“卡点视频”?详细的制作步骤介绍 江苏麒麟互娱

好了,简单做两种类型的热门视频剪辑交给你们,尝试操作,不懂的可以留言交流。

金分割大家应该早就有所耳闻,作为一名设计师,可能一直感觉它离我们很遥远。那么怎么能利用黄金分割线更加完美的构图呢?

说实话呢,构图的时候是否使用黄金分割线构图并不是绝对的,它只是方法之一。但是黄金分割比例,在全世界乃至全宇宙确实都是至高无上的。

一、至高无上的黄金分割比例

这种东西是很神奇的事情,你了解的越多越会绝的这是一个不可思议的事情,甚至有人称之为上帝的密码。那黄金分割线到底是个什么东西呢?它在什么位置?它在画面中的什么地方?

有一条线条,如果我们从中切一段,如果左边是0.618这么一个比列,右边是1这么一个比例。如果符合这样的左右比例我们称之为黄金分割比,那么中间切割的位置就是我们黄金分割线的位置。

我们大体概括一下:黄金分割线是指将整体一分为二,较大部分与整体部分的比值,等于较小部分与较大部分的比值,其比值约为0.618,这个比例被公认为是最能引起美感的比例。

总结一句话就是:0.618的比值最美。

0.618的比例怎么来的?

有人做了一个实验,他们拿着一些长方形去问全世界的人,说哪个长方形最好看?

结果所以的人都不约而同的选择了这种长方形。西方的、东方的、土著的都选择了如下图的这种长方形。

科学家们就很奇怪它到底奥秘在哪?

要分析分析它。这个长方形如果从中间画一条线,把它分割成俩个形状的话,右边可以是一个正方形,左边小的长方形的比例和原来的长方形的比例是一摸一样的。小的长方形也可以切割出一个正方形和一个等比例的更小的长方形,这种长方形只有黄金风格的长方形才能做到。

二、运用黄金分割线构图

画面长宽比不同,黄金分割线位置也不同,这里我们列举常用的长宽比尺寸4:3/3:2/16:9/1:1。

在移动端主流尺寸中,iOS尺寸使用750*1334,安卓尺寸使用1080*1920,这俩个尺寸正好等同于一倍图375*667的比例。

不同长宽比的画面我们按照0.618:1的比例,一个画面可以切割出4条黄金分割线,上分割线/下分割线/左分割线/右分割线。我们在实际构图怎么利用黄金分割线快速排版?

2.1 基本的运用方法

2.1.1 把主体放线上,当然线状的主体才能放线上

在构图中我们经常遇到正方形/长方形等规则的形状,前期我们把规则的形状中心放在黄金分割线上,等所以内容添加完成后再分析画面的重量,微调来平衡画面。

不是所有的物体都是刚刚好放在黄金分割线上,轮廓化的形状应该根据什么来跟黄金分割线重合呢?

应该是形状的重心,而不是中心。

如上图:长方形的图片是有规律的形状,我们把它的中心暂时先放在右黄金分割线上,从平衡角度来看还是右边重,因为我们还没有把页面所以元素放进去,到时候可以根据画面的平衡感来微调。

2.1.2 多条黄金风割线构图

一个画面中,可以切割成上下左右四个黄金分割线,前期练习时可以尽可能把黄金分割线利用好。

如上图:我们把图片放在右黄金分割线上,正文大标题放在上黄金分割线上。这样就搭上俩条黄金分割线了,再加上logo/分类/导航等信息整个界面就更完整了,如下图:

2.2 具体选择哪一条?

初期进行练习的时候,黄金分割线能搭上几条就搭上几条。这么多黄金风格线,如果我用1条到2条,到底选择哪一条?

2.2.1 根据元素选择

界面设计时,要根据元素多少进行选区更合适的黄金分割线?

如上图:最终所以元素都确定后,我们把图片放右黄金分割线上,正文大标题放在上黄金分割线上,正文跟按钮的中心放在下黄金分割线上,图片轮播按钮的中心放在左黄金分割线上。这样四条黄金分割线搭上都利用起来,在这基础之上再去微调相信画面会更出彩的。

2.2.2 根据那边更精彩选择画面

把上下或左右俩条黄金分割线对比一下,就能确定参考哪一条黄金分割线了。

如上图:我们开始把图片放在下黄金分割线上,上面留了太多空间,图片的内容展示的也很少,画面感不够丰富。

如上图:根据画面的丰富程度,我们把图片放在靠近上黄金分割线的位置,把图片中主体的放在靠近右黄金分割线附近。然后再添加内容丰富画面,我们为画面添加logo/数据/导航/分类/按钮,让画面更丰满。如下图:

2.2.3 视线的影响

人和动物的视线朝向,会影响到它的摆放位置。

如上图:小狗狗的视觉朝向是左边,所以我们肯定得把小狗狗放右边。因为它是一个不规则造型,当遇到不规则造型时我们应该尝试找到它的重心,正好它整个形态成一条直线,它的重心应该是沿鼻子的往右的一条隐形的线。

主体确认好后,我们在加上logo/标题/正文/导航进行排版,保证画面平衡进行微调。如下图:

简化的黄金分割线——三分线

我们还有个困难,那就是0.618:1的黄金分割线的位置确实不是很好找。所以对于设计师来说,我们有一种简化黄金风格线的做法?

就是三分线。

什么意思呢?

左边是黄金风格线,右边是三分线。三分线就是均匀的把长方形的长和宽切三段,均匀的砍三段,每个方格都是一样大小。

三分线的位置跟黄金风格线的位置差不了多少,但是黄金风格线比起三分线更靠近中央的位置,是这么一个概念。

如上图:绿色的虚线是右黄金分割线的位置,黄色的虚线是右三分线的位置,我们没有直接把主体的重心直接放在黄金分割线上,在这个画面中,因为左右的信息量很大给人很重的压迫感,所以主体如果太靠近左边就会让画面失去平衡,这时候我们就把主体放在了三分线上。

不要说很严谨的把它重心摆在三分线上,一来黄金风格线真实所在的位置是三分线往里靠一点的位置,二来我们说黄金风格线构图/三分线构图不是说让你一定要完全重叠,大差不差就行,具体情况还是要具体分析。

黄金风格线还不止这么多的表现形式,它还有一种更复杂的表现形式叫黄金螺旋线,而从黄金螺旋线里呢,可以推倒出一个黄金兴趣点

于是我们就把黄金螺旋线和最佳兴趣点,都统称为黄金分割的衍生品,在设计中应该是算比较高级的一种构图技法了。

三、最佳兴趣点

来看看黄金螺旋线衍生的最佳兴趣点在什么位置?

如下图:

在设计中实际应用的时候,想找出这个点来绝对不是很容易的事情,所以怎么办呢?有简单找到最佳兴趣点的方法吗?

长方形的一条斜线链接起来,另一个顶点画一条垂直于这条斜线的点基本就是最佳兴趣点的位置,如下图:

画面中不止一个最佳兴趣点,一个画面中会有四个兴趣点,会更好的方便我们利用,如下图:

画面长宽比不同,最佳兴趣点的位置也不同,这里我们列举常用的长宽比尺寸4:3/3:2/16:9/1:1,如下图:

案例分析

如上图:图片案例来自摄影师7kidz的摄影作品,图片质量很高,整体风格很符合现在主流的抖音风,那就顺便做个直播类的ui界面设计来诠释最佳兴趣点的魅力。

案例一,同样大小的图片我们按照俩种方式进行摆放,左边的图片我们参考黄金分割线,把人物的眼睛靠近上黄金分割线的位置;右边的图片我们把人物的右眼放在了右上的最佳兴趣点的位置。然后我们去掉辅助线再对比下。

如下图:

虽然我们参考了俩种方式进行排版,图片本身就很精美,很多人就感觉随便放放就好了,左边的黄金分割线构图单看也是很棒的,所谓没有对比就没有伤害,当黄金分割线遇上最佳兴趣点,哪个好效果是显而易见的。

从画面的饱和度跟视觉引导,显然右边的整体感觉更饱满一些,加上直播平台元素整个界面。

如下图:

案例二画面中人物前方的效果很出彩,想办法尽可能保留,所以把人物右眼放在右上最佳兴趣点的位置,正好左前方灯管不规则的物体的重心,也恰巧在左上最佳兴趣点的位置,这样就有运用了俩个最佳兴趣点,画面更加丰富起来,加上直播平台元素整个界面。

如下图:

案例三画面中人物的睫毛放在右上最佳兴趣点的位置,刚看到画面的时候我们第一眼会被美美的胸部所吸引,但是我们眼神会顺势往右上看到美女的睫毛。是的因为我们把它放在了最佳兴趣点的位置,不会因为它占的面积很小而被忽略。

这个案例其实最具代表性,加上直播平台元素整个界面,如下图:

最佳兴趣点是不是和黄金分割线是重叠的?

最佳兴趣点和黄金分割线交点不重合的,黄金分割线的交叉点比最佳兴趣点更靠近画面中心。

那是不是就是三分线的横竖线相交处啊?

最佳兴趣点和三分线交点也不重合?

最佳兴趣点比三分线还要更外一点。

最佳兴趣点可以和黄金分割线或三分线一起使用吗?

答案是肯定的,一起使用会增加我们布局的多样性,内容可以排的更加丰富。

如上图:画面中最突出的是人物的头发,我们把头发的形成的点放在了左上最佳兴趣点的位置,微调人物,在画面中的人物重心差不多在三分线所在的这条直线上。

标题和正好的做为一个整体的中心,放在下黄金分割线的位置上,再加上音乐封面/歌曲名/播放按钮再微调画面使画面达到视觉平衡。

如上图:音乐专辑封面为正方面,最佳兴趣点就是正方形的中心点,封面人物重心放在正方形的中心,封面放在靠近上黄金分割线的位置。大标题差不多在左上最佳兴趣点的位置,整个画面重心在左黄金分割线的位置。

为了达到视觉平衡,右上角加了一个头像形成大小对比,让画面更稳定,不至于左边太重而失去平衡。加上播放按钮/推荐的封面后再调整,如下图:

四、黄金螺旋线

斐波那契螺旋线也称“黄金螺旋”,是根据斐波那契数列画出来的螺旋曲线,自然界中存在许多斐波那契螺旋线的图案,是自然界最完美的经典黄金比例。

斐波那契螺旋线,以斐波那契数为边的正方形拼成的长方形,然后在正方形里面画一个90度的扇形,连起来的弧线就是斐波那契螺旋线。

斐波那契数列(FibonacciSequence)数列是这样一个数列:

1、1、2、3、5、8、13、21、34、55、89…

在数学上,斐波那契数列是以递归的方法来定义:

F0=1

F1=1

Fn=F(n-1)+F(n-2)

(n>=2,n∈N*)

斐波那契数列比在字号大小、界面布局、Logo设计上具体有哪些用法?

4.1 字号大小

4.1.1 大字体与小字体比例系统

我们在选择一个字号大小做为参考时,我们正常会选择最大字号或最小字号做为参考。按照黄金比1:1.618可以得到比它大的字体,按照黄金比1:0.618可以得到比它小的字体。

为了方便排版,我们除了可以使用黄金分割比例外,还可以使用斐波那契数列比。可以有更多灵活的排版方式,通过对比可以选择最适合的。

斐波那契数列比:1:1/1:2/1:3/2:3/1:5/2:5/3:5 …

如上图,我们可以根据字体的高度比来排版,这里我们大字高度:间距:小字高度比为8:5:5,可以灵活使用斐波那契数列比,多排几个版式找到最适合的一个。

4.1.2 文字的长度比例

在设计字体大小的时候,可以根据字体的长度来做为参考,黄金螺旋线整体长度为140px。下面的字体比较长,我们就乘以1.618来得到比较大的比例226.52,取整数为226,我们对应长度字号取整数即可。

4.2 界面布局

上图案例由UISTAR提供,整个界面的布局很舒服,字间距也恰到好处。在做后台界面,客户端界面时候很多时候会出现界面分段布局,很多时候认为后台不是特别重要而忽略了它的美观性。

看下图,我们应该怎么通过斐波那契数列比来切割画面?

我们通过斐波那契数列比8:5:3:2:1绘制了正方形,在后台复杂的界面中,我们肯定要参考画面中重要的最小宽度来确定这个比例大小。红框框就是我们确定的最小宽度,确定宽度后8:5:3:2:1得到大小不一的方格,剩下来就是根据内容自由组合合适的方格。

很神奇的事情发生了,好的作品大体都符合这个规律,几像素的偏差已经不重要的,所以前期我们可以参考方法论,当你的能力上来之后,就可以放弃它,慢慢凭自己的感觉来判断作品的好坏。

4.3 LOGO设计

黄金斐波那契螺旋法,是国际上通用的LOGO设计手法,也是最工整最严谨的设计手法。

BIGD牛大大已经出了类似教程,具体请查看。《Ai中用黄金比例法快速作图》

这边引用BIGD视频教程是想让知识更系统,也省点精力撸其他的干货。我写了一篇《如何学习Yoga Style?》,里面有圆切法的基础教程。

这里说一下为什么要用黄金螺旋线去重新定义标识呢?

打个比方:很多时候我们会找一张动物图片用圆切法去绘制它,但是我们绘制时候因为不知道怎么去做减法,会让这个形态变的复杂,绘制结果更多像是图案或者图形,而不是标识。我们使用黄金螺旋比例去切形态的时候要抓住动物的主体形态和特征,尽可能的抽象化简单化。

黄金螺旋线在logo中的应用

黄金螺旋比例用圆去切割很多人已经会了,但是最最最高级的就利用好黄金螺旋线。最近站酷很火的一个设计师DAINOGO,它的作品中就用到了黄金螺旋线,能用一个圆解决的绝对不用俩个圆。我们在设计中,如果有运用到弧线的地方,可以考虑使用黄金螺旋线做为参考。

总结

最后还是要感谢UISTAR、贼哥、小朋友的优秀案例,真心感谢。

黄金分割线、三分线、最佳兴趣点,每个还可以分上下左右4个构图方案,这里我们就已经有12种排版方式可以考虑了。构图的时候是否使用黄金分割线、三分线、最佳兴趣点并不是绝对的,它只是方法之一。如果你有排版基础,以这个为参考相信一定排出不错的版式。

黄金分割上中下就写完了,最近跟一线大厂设计师交流,他们给我的反馈是做设计的时候不单单只是视觉上的美感,更多的需要方法论的东西,这样才更具有说服力。

希望以后多写方法论的文章,大家一起学习。

本文由 @水手哥 原创发布于人人都是产品经理。未经许可,禁止转载

题图作者提供