跳到主要内容

使用JavaScript构建360度视图图像滑块

这篇文章首次出现在问题224.net杂志-世界上最畅销的网页设计师和开发者杂志。

我们要建立一个360视图图像滑块。你能用它做什么?嗯,当你的客户想要从各个角度展示他们的产品而不只是展示几个简单的角度镜头时,它会非常方便。

我们已经看到很多来自汽车和手机制造商的漂亮互动示例,他们使用这种技术展示他们的产品,但在大多数情况下他们使用Flash。

我喜欢交互性,但我不喜欢使用插件,除非它是必不可少的,所以在本教程中我们将使用HTML,CSS和JavaScript构建我们自己的360视图应用程序。

它将如何运作?

我们将使用预渲染的图像序列,显示围绕其y轴旋转的3D对象。该序列包含180个图像,以尽可能平滑地显示动画。用户可以通过水平拖动鼠标或通过在触摸屏上的图像滑块上滑动手指来“旋转对象”。

我们怎么做?

首先我们将构建我们的HTML标记,然后我们将添加一些自定义CSS,包括媒体查询,然后我们将使用JavaScript进行常规。为了让它更令人兴奋,我们不仅可以在桌面电脑上使用,还可以在iPhone和iPad上使用,因为该应用程序可以很好地处理触摸事件。

在我们开始之前,请允许我非常感谢你Mateusz Sypien玛雅普罗达诺娃因为他们惊人的360艺术品!

01.文件夹

在里面项目文件夹我们有一个CSS文件夹,aJS文件夹和IMG夹。 Css文件夹包含Reset.css文件,img文件夹包含图像序列,js文件夹包含jQuery和Heartcode CanvasLoader库。

02.新项目

创建一个新的HTML文件并将其保存到项目根目录中的index.html。在里面我们通过使内容不可扩展来为移动设备设置视口。我们包括两个CSS文件:Eric MeyerReset.cssThreesixty.css,它将包含我们的自定义样式。






360






0%




    03.装载百分比

    创建一个包装器

    对于滑块。它包含一个
      ,将图像序列保持为
    1. S,并且还拥有预加载器
      抱着一个对于加载百分比显示。我们将使用JavaScript动态添加图像。






      360






      0%




        04.添加互动

        就在之前,包括我们将使用的JS文件。 jQuery帮助我们快速添加交互,Heartcode CanvasLoader将添加平滑的预加载器动画。该Threesixty.js文件将包含控制图像滑块的JavaScript。






        360






        0%








          05.造型

          现在创建Threesixty.css文件。该Reset.cssFile设置所有默认行为,因此我们可以转到有趣的位。风格#threesixty首先包装。默认图像滑块为960像素×540像素,水平和垂直居中。我们也设定了

            要隐藏的元素。

            #threesixty {
            位置:绝对的;
            溢出:隐藏;
            顶部:50%;
            左:50%;
            宽度:960像素;
            高度:540px;
            保证金左:-480px;
            边距:-270px;
            }
            #threesixty_images {
            Display:none;
            }

            06.设置显示

            为了使界面在不同的屏幕上工作,同时保持比例一致,我们将使用媒体查询控制显示。您可以在上面的代码段中看到我们如何定义不同的分辨率和方向设备标准MAX-装置宽度取向物业结合运营商。上面的代码片段设置了iPad(1024px宽)和iPhone / iPod触摸屏的显示屏,包括横向和纵向模式(480px宽)。图像将占用包装器内的所有可用空间。

            @media屏幕和(max-device-width:1024px)和(orientation:portrait){
            #threesixty {
            宽度:720像素;
            高度:450像素;
            保证金左:-360px;
            边距:-225px;
            }
            }
            @media屏幕和(max-device-width:480px)和(orientation:landscape),
            屏幕和(-webkit-min-device-pixel-ratio:2)和(orientation:landscape){
            #threesixty {
            宽度:360像素;
            高度:225px;
            保证金左:-180px;
            边距:-113px;
            }
            }
            @media屏幕和(max-device-width:480px)和(orientation:portrait),
            屏幕和(-webkit-min-device-pixel-ratio:2)和(orientation:portrait){
            #threesixty {
            宽度:320像素;
            高度:200像素;
            保证金左:-160px;
            边距:-100px;
            }
            }

            07.图像

            所有图像都将被放入

              。首先,我们为包装器中的每个图像设置样式。我们不希望图像全部可见,因此我们定义了当前图像以前的图像控制其可见性的类。我们将使用JavaScript在这些状态之间切换。

              #threesixty Img {
              位置:绝对的;
              顶部:0;
              宽度:100%;
              高度:自动;
              }
              .current-image {
              能见度:可见;
              宽度:100%;
              }
              .previous-image {
              Visibility:hidden的;
              宽度:0;
              }

              08. Preloader风格

              通过制作我们的预加载器样式#spinner隐藏,设置其尺寸并将其放置在包装的中心。我们还设置了跨度内的样式#spinner水平和垂直居中,使文本位于圆形动画的中间。

              #spinner {position:absolute;左:50%;顶部:50%;宽度:90像素;高度:90像素;保证金左:-45px;边距:-50px; display:none;} #spinner span {position:absolute;顶部:50%;宽度:100%;颜色:#333;字体:0.8em Arial,Verdana,sans;文本对齐:中心;行高:0.6em;边距:-0.3em;}

              09.做好准备

              创建一个新的JS文件并将其另存为Threesixty.js在js文件夹中。将代码放入jQuery DOM-Ready函数中,以便在脚本开始运行时,DOM元素已经到位。准备我们的应用程序准备好后,将启用用户交互。

              拖动告诉我们用户是否正在使用指针。使用speedMultiplier,我们设置图像滑动的速度;我们有一些变量来存储指针位置 - 定时器将跟踪指针变化 - 我们定义一些变量来跟踪帧计算和图像加载。

              $(document).ready(function(){
              Var Ready = False,
              Dragging = False,
              PointerStartPosX = 0,
              PointerEndPosX = 0,
              PointerDistance = 0,

              MonitorStartTime = 0,
              MonitorInt = 10,
              Ticker = 0,
              SpeedMultiplier = 10,
              飞旋,

              TotalFrames = 180,
              CurrentFrame = 0,
              Frames = [],
              EndFrame = 0,
              LoadedImages = 0;
              });

              10.旋转器

              我们创造了AddSpinner添加一个的功能CanvasLoader实例中包含自定义设置#spinner。旋转器将是一个90x90px的螺旋形装载机,具有平滑的圆形动画。调用它的show方法,然后使用jQuery显示它淡入

              function addSpinner(){spinner = new CanvasLoader(“spinner”); spinner.setShape( “螺旋”); spinner.setDiameter(90); spinner.setDensity(90); spinner.setRange(1); spinner.setSpeed(4); spinner.setColor( “#333333”); spinner.show(); $( “#微调”)淡入( “慢”);};

              11.图像加载和帧阵列

              加载图像功能创建一个

            1. 内。使用隐藏图像以前的图像类。该LoadedImages变量生成图像名称,每次加载新图像时,图像名称都会递增;如果成功,我们称之为ImageLoaded功能。

              在一行代码中,我们创建了一个新代码,将其源指向生成的文件名,然后通过应用隐藏它以前的图像类。所有这一切都归功于jQuery!我们将jQuery返回的每个图像对象存储在frames数组中,这对于动画来说非常方便。

              Function LoadImage(){
              var li = document.createElement(“li”);
              var imageName =“img / threesixty_”+(loadedImages + 1)+“.jpg”;
              var image = $(' ')。attr('src',imageName).addClass(“previous-image”)。appendTo(li);
              Frames.push(图像);
              $( “#threesixty_images”)追加(LI);
              $(image)。load(function(){
              ImageLoaded();
              });
              };

              12.图像过载

              有太多图像一次加载,所以我们打电话的LoadImage递归。通过将百分比文本写入文本来显示图像加载过程#spinner。加载完所有图像后,我们会使第一张图像可见并隐藏预加载器。

              Function ImageLoaded(){
              LoadedImages ++;
              $(“#spinner span”)。text(Math.floor(loadedImages / totalFrames * 100)+“%”);
              If(loadedImages == TotalFrames){
              帧[0] .removeClass( “先前图像”)addClass( “当前图像”)。
              $(“#spinner”)。fadeOut(“slow”,function(){
              Spinner.hide();
              ShowThreesixty();
              });
              } Else {
              的LoadImage();
              }
              };

              13.顺利过渡

              使用平滑过渡显示图像滑块ShowThreesixty功能。我们通过致电启动应用程序AddSpinner()的LoadImage()。测试时,预加载器淡入,加载图像时,转换会隐藏它并显示第一个图像。

              Function ImageLoaded(){
              LoadedImages ++;
              $(“#spinner span”)。text(Math.floor(loadedImages / totalFrames * 100)+“%”);
              If(loadedImages == TotalFrames){
              帧[0] .removeClass( “先前图像”)addClass( “当前图像”)。
              $(“#spinner”)。fadeOut(“slow”,function(){
              Spinner.hide();
              ShowThreesixty();
              });
              } Else {
              的LoadImage();
              }
              };

              Function ShowThreesixty(){
              $( “#threesixty_images”)淡入( “慢”)。
              Ready = True;
              };

              AddSpinner();
              的LoadImage();

              14.帧值

              滑块动画将很简单:我们将当前帧值补间到设置的结束帧值并显示当前图像。自定义缓动方法计算帧之间的距离,并在任一方向上创建平滑旋转动画。

              创建更新帧动画的渲染功能。如果当前帧尚未到达结束帧,请通过更改其值将其移近:当它到达结束帧时,停止渲染。使用更新图像HidePreviousFrameShowCurrentFrame功能。

              Function Render(){
              If(currentFrame!== EndFrame)
              {
              var frameEasing = endFrame <currentFrame? Math.floor((endFrame - currentFrame)* 0.1):Math.ceil((endFrame - currentFrame)* 0.1);
              HidePreviousFrame();
              CurrentFrame + = FrameEasing;
              ShowCurrentFrame();
              } Else {
              Window.clearInterval(股票);
              Ticker = 0;
              }
              };

              15. Ticker

              Refresh函数调用我们的render函数,它创建一个的setInterval我们存储在自动收报机变量中。为确保我们不进行任何不必要的呼叫,请检查自动收报机是否已在运行。我将FPS值设置为60,因此我们可以拥有一个漂亮,流畅的动画。

              Function Refresh(){
              If(ticker === 0){
              ticker = self.setInterval(render,Math.round(1000/60));
              }
              };

              16.标准化值

              HidePreviousFrameShowCurrentFrame交换当前图像的状态。呼叫GetNormalizedCurrentFrame()获取1-180之间的帧值,返回“标准化”值设置currentFrame我们用来操纵当前图像。

              为了获得'swooshy'效果,当前帧值不能超出定义的范围TotalFrames。随着GetNormalizedCurrentFrame函数命令,我们可以计算出的值TotalFrames范围使动画准确移动。

              Function HidePreviousFrame(){
              帧[getNormalizedCurrentFrame()] RemoveClass( “当前图像”)addClass( “先前图像”)。;
              };

              Function ShowCurrentFrame(){
              帧[getNormalizedCurrentFrame()] RemoveClass( “先前图像”)addClass( “当前图像”)。。
              };

              Function GetNormalizedCurrentFrame(){
              var c = -Math.ceil(currentFrame%totalFrames);
              if(c <0)c + =(totalFrames - 1);
              返回c;
              };

              17.测试

              让我们快速测试吧。在里面ShowThreesixty函数我们将添加两件事:首先我们将endFrame设置为-720,其次,我们调用refresh方法。如果您测试应用程序,您会看到图像在淡入时快速晃动。

              Function ShowThreesixty(){
              $( “#threesixty_images”)淡入( “慢”)。
              Ready = True;
              EndFrame = -720;
              刷新();
              };

              18.用户互动

              添加用户交互。从鼠标事件侦听器开始,然后添加自定义函数GetPointerEvent,告诉我们用户是否使用鼠标或手指。在鼠标按下时,我们存储指针X的位置,并在鼠标移动时调用TrackPointer()

              Function GetPointerEvent(event){
              return event.originalEvent.targetTouches? event.originalEvent.targetTouches [0]:event;
              };

              $(“#threesixty”)。mousedown(function(event){
              Event.preventDefault();
              pointerStartPosX = getPointerEvent(event).pageX;
              Dragging = True;
              });

              $(document).mouseup(function(event){
              Event.preventDefault();
              Dragging = False;
              });

              $(document).mousemove(function(event){
              Event.preventDefault();
              TrackPointer(事件);
              });

              19.触摸事件

              现在添加触摸事件。我们用的是GetPointerEvent()将正确的事件传递给TrackPointer功能。对于所有事件,我们会阻止defaultbehaviour并将拖动值设置为真正如果用户正在拖动指针,那么当他们释放时

              $(“#threesixty”)。live(“touchstart”,function(event){
              Event.preventDefault();
              pointerStartPosX = getPointerEvent(event).pageX;
              Dragging = True;
              });

              $(“#threesixty”)。live(“touchmove”,function(event){
              Event.preventDefault();
              TrackPointer(事件);
              });

              $(“#threesixty”)。live(“touchend”,function(event){
              Event.preventDefault();
              Dragging = False;
              });

              20.跟踪运动

              TrackPointer()我们定期跟踪指针移动,以便在拖动指针时使帧动画流动。如您所见,如果拖动为true且应用程序已准备就绪,我们只跟踪指针。我们之所以这样做是因为渲染可能非常强大,而且我们必须要善于处理。

              存储开始和结束x指针位置,然后在时间段内检查它们之间的距离。运用PointerDistance,计算动画EndFrame并通过调用刷新函数来更新它。SpeedMultiplier让我们完全控制纺纱速度。

              Function TrackPointer(event){
              if(ready && dragging){
              pointerEndPosX = getPointerEvent(event).pageX;
              if(monitorStartTime <new Date()。getTime() - monitorInt){
              pointerDistance = pointerEndPosX - pointerStartPosX;
              endFrame = currentFrame + Math.ceil((totalFrames - 1)* speedMultiplier *(pointerDistance / $(“#threesixty”)。width()));
              刷新();
              monitorStartTime = new Date()。getTime();
              pointerStartPosX = getPointerEvent(event).pageX;
              }
              }
              };

              我们完成了!

              如果您测试应用程序,您可以看到百分比加载器动画淡入和淡出,然后图像显示'swooshy'旋转。现在,您可以使用鼠标或触摸移动设备上的图像滑块,使360度图像滑块旋转,并具有响应性,流畅的动画效果。

              在移动设备上测试应用程序的最佳方法是将项目文件放在服务器上,或与设备共享本地主机。您还可以查看媒体查询如何处理不同的设备屏幕分辨率和方向。

              我决定让这个滑块开源,并创建了一个Git存储库允许其他人合作并帮助其变得令人敬畏。

              罗伯特帕塔基是一位具有多年Flash技术和创意广告经验的创意技术专家,目前在数字代理商工作浪费创意在伦敦。

              喜欢这个?阅读这些!



        翻译字数超限