首页 > 解决方案 > 如何限制 360 度查看器在 180 度视图上停止 - 所以后面会被隐藏?

问题描述

我使用 jQuery 插件创建可拖动的 360 度查看器:http: //nick-jonas.github.io/threesixtyjs/

观众的对象是一个展台,我想将视图限制为 180 度,因为没有可用的对象的后视图。通过限制视图,我的意思是在对象到达其中一个侧视图时停止对象的“旋转”。使用现有代码,由于缺少后视图,在拖动时,视图在旋转时会从一侧视图跳转到对面。

是否可以对现有的 Javascript 代码进行一些更改以实现此结果?

HTML/CSS/JS 如下:

/*!
 * ThreeSixty: A jQuery plugin for generating a draggable 360 preview from an image sequence.
 * Version: 0.1.2
 * Original author: @nick-jonas
 * Website: http://www.nickjonas.nyc
 * Licensed under the Apache License Version 2.0
 */

;(function ( $, _window, document ) {


var scope,
    pluginName = 'threeSixty',
    defaults = {
        dragDirection: 'horizontal',
        useKeys: false,
        draggable: true
    },
    dragDirections = ['horizontal', 'vertical'],
    options = {},
    $el = {},
    data = [],
    total = 0,
    loaded = 0;

    /**
     * Constructor
     * @param {jQuery Object} element       main jQuery object
     * @param {Object} customOptions        options to override defaults
     */
    function ThreeSixty( element, customOptions ) {
        scope = this;
        this.element = element;
        options = options = $.extend( {}, defaults, customOptions) ;
        this._defaults = defaults;
        this._name = pluginName;

        // make sure string input for drag direction is valid
        if($.inArray(options.dragDirection, dragDirections) < 0){
            options.dragDirection = defaults.dragDirection;
        }

        this.init();
    }

    // PUBLIC API -----------------------------------------------------

    $.fn.destroy = ThreeSixty.prototype.destroy = function(){
        if(options.useKeys === true) $(document).unbind('keydown', this.onKeyDown);
        $(this).removeData();
        $el.html('');
    };

    $.fn.nextFrame = ThreeSixty.prototype.nextFrame = function(){
        $(this).each(function(i){
            var $this = $(this),
                val = $this.data('lastVal') || 0,
                thisTotal = $this.data('count');

            val = val + 1;

            $this.data('lastVal', val);

            if(val >= thisTotal) val = val % (thisTotal - 1);
            else if(val <= -thisTotal) val = val % (thisTotal - 1);
            if(val > 0) val = thisTotal - val;

            val = Math.abs(val);

            $this.find('.threesixty-frame').css({display: 'none'});
            $this.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'});
        });
    };

    $.fn.prevFrame = ThreeSixty.prototype.prevFrame = function(){
        $(this).each(function(i){
            var $this = $(this),
                val = $this.data('lastVal') || 0,
                thisTotal = $this.data('count');

            val = val - 1;

            $this.data('lastVal', val);

            if(val >= thisTotal) val = val % (thisTotal - 1);
            else if(val <= -thisTotal) val = val % (thisTotal - 1);
            if(val > 0) val = thisTotal - val;

            val = Math.abs(val);

            $this.find('.threesixty-frame').css({display: 'none'});
            $this.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'});
        });
    };



    // PRIVATE METHODS -------------------------------------------------

    /**
     * Initializiation, called once from constructor
     * @return null
     */
    ThreeSixty.prototype.init = function () {
        var $this = $(this.element);

        // setup main container
        $el = $this;

        // store data attributes for each 360
        $this.each(function(){
            var $this = $(this),
                link = $this.data('link'),
                count = $this.data('count');
            data.push({'link': link, 'count': count, 'loaded': 0, '$el': $this});
            total += count;
        });

        _disableTextSelectAndDragIE8();

        this.initLoad();
    };

    /**
     * Start loading all images
     * @return null
     */
    ThreeSixty.prototype.initLoad = function() {
        var i = 0, len = data.length, url, j;
        $el.addClass('preloading');
        for(i; i < len; i++){
            j = 0;
            for(j; j < data[i].count; j++){
                url = data[i].link.replace('{index}', j);
                $('<img/>').data('index', i).attr('src', url).load(this.onLoadComplete);
            }
        }
    };

    ThreeSixty.prototype.onLoadComplete = function(e) {
        var index = $(e.currentTarget).data('index'),
            thisObj = data[index];
        thisObj.loaded++;
        if(thisObj.loaded === thisObj.count){
            scope.onLoadAllComplete(index);
        }
    };

    ThreeSixty.prototype.onLoadAllComplete = function(objIndex) {
        var $this = data[objIndex].$el,
            html = '',
            l = data[objIndex].count,
            linkTemplate = data[objIndex].link,
            i = 0;

        // remove preloader
        $this.html('');
        $this.removeClass('preloading');

        // add 360 images
        for(i; i < l; i++){
            var display = (i === 0) ? 'block' : 'none';
            html += '<img class="threesixty-frame" style="display:' + display + ';" data-index="' + i + '" src="' + linkTemplate.replace('{index}', i) + '"/>';
        }
        $this.html(html);

        this.attachHandlers(objIndex);
    };

    var startY = 0,
        thisTotal = 0,
        $downElem = null,
        lastY = 0,
        lastX = 0,
        lastVal = 0,
        isMouseDown = false;
    ThreeSixty.prototype.attachHandlers = function(objIndex) {
        var that = this;
        var $this = data[objIndex].$el;

        // add draggable events
        if(options.draggable){
            // if touch events supported, use
            if(typeof document.ontouchstart !== 'undefined' &&
                typeof document.ontouchmove !== 'undefined' &&
                typeof document.ontouchend !== 'undefined' &&
                typeof document.ontouchcancel !== 'undefined'){
                var elem = $this.get()[0];
                elem.addEventListener('touchstart', that.onTouchStart);
                elem.addEventListener('touchmove', that.onTouchMove);
                elem.addEventListener('touchend', that.onTouchEnd);
                elem.addEventListener('touchcancel', that.onTouchEnd);
            }
        }

        // mouse down
        $this.mousedown(function(e){
            e.preventDefault();
            thisTotal = $(this).data('count');
            $downElem = $(this);
            startY = e.screenY;
            lastVal = $downElem.data('lastVal') || 0;
            lastX = $downElem.data('lastX') || 0;
            lastY = $downElem.data('lastY') || 0;
            isMouseDown = true;
            $downElem.trigger('down');
        });

        // arrow keys
        if(options.useKeys === true){
            $(document).bind('keydown', that.onKeyDown);
        }

        // mouse up
        $(document, 'html', 'body').mouseup(that.onMouseUp);
        $(document).blur(that.onMouseUp);
        $('body').mousemove(function(e){
            that.onMove(e.screenX, e.screenY);
        });
    };

    ThreeSixty.prototype.onTouchStart = function(e) {
        var touch = e.touches[0];
        e.preventDefault();
        $downElem = $(e.target).parent();
        thisTotal = $downElem.data('count');
        startX = touch.pageX;
        startY = touch.pageY;
        lastVal = $downElem.data('lastVal') || 0;
        lastX = $downElem.data('lastX') || 0;
        lastY = $downElem.data('lastY') || 0;
        isMouseDown = true;
        $downElem.trigger('down');
    };

    ThreeSixty.prototype.onTouchMove = function(e) {
        e.preventDefault();
        var touch = e.touches[0];
        scope.onMove(touch.pageX, touch.pageY);
    };

    ThreeSixty.prototype.onTouchEnd = function(e) {

    };

    ThreeSixty.prototype.onMove = function(screenX, screenY){
        if(isMouseDown){
            var x = screenX,
                y = screenY,
                val = 0;

            $downElem.trigger('move');

            if(options.dragDirection === 'vertical'){
                if(y > lastY){
                    val = lastVal + 1;
                }else{
                    val = lastVal - 1;
                }
            }else{
                if(x > lastX){
                    val = lastVal + 1;
                }else if(x === lastX){
                    return;
                }else{
                    val = lastVal - 1;
                }
            }

            lastVal = val;
            lastY = y;
            lastX = x;

            $downElem.data('lastY', lastY);
            $downElem.data('lastX', lastX);
            $downElem.data('lastVal', lastVal);

            if(val >= thisTotal) val = val % (thisTotal - 1);
            else if(val <= -thisTotal) val = val % (thisTotal - 1);
            if(val > 0) val = thisTotal - val;

            val = Math.abs(val);

            $downElem.find('.threesixty-frame').css({display: 'none'});
            $downElem.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'});
        }
    };

    ThreeSixty.prototype.onKeyDown = function(e) {
        switch(e.keyCode){
            case 37: // left
                $el.prevFrame();
                break;
            case 39: // right
                $el.nextFrame();
                break;
        }
    };

    ThreeSixty.prototype.onMouseUp = function(e) {
        isMouseDown = false;
        $downElem.trigger('up');
    };

    /**
     * Disables text selection and dragging on IE8 and below.
     */
    var _disableTextSelectAndDragIE8 = function() {
      // Disable text selection.
      document.body.onselectstart = function() {
          return false;
      };

      // Disable dragging.
      document.body.ondragstart = function() {
          return false;
      };
    };


    /**
     * A really lightweight plugin wrapper around the constructor,
        preventing against multiple instantiations
     * @param  {Object} options
     * @return {jQuery Object}
     */
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName,
                new ThreeSixty( this, options ));
            }
        });
    };

})( jQuery, window, document );
@charset "UTF-8";
@-webkit-keyframes ui-spinner-rotate-right {
  /* line 58, ../../scss/_ui-spinner.scss */
  0% {
    -webkit-transform: rotate(0deg);
  }

  /* line 59, ../../scss/_ui-spinner.scss */
  25% {
    -webkit-transform: rotate(180deg);
  }

  /* line 60, ../../scss/_ui-spinner.scss */
  50% {
    -webkit-transform: rotate(180deg);
  }

  /* line 61, ../../scss/_ui-spinner.scss */
  75% {
    -webkit-transform: rotate(360deg);
  }

  /* line 62, ../../scss/_ui-spinner.scss */
  100% {
    -webkit-transform: rotate(360deg);
  }
}

@-webkit-keyframes ui-spinner-rotate-left {
  /* line 66, ../../scss/_ui-spinner.scss */
  0% {
    -webkit-transform: rotate(0deg);
  }

  /* line 67, ../../scss/_ui-spinner.scss */
  25% {
    -webkit-transform: rotate(0deg);
  }

  /* line 68, ../../scss/_ui-spinner.scss */
  50% {
    -webkit-transform: rotate(180deg);
  }

  /* line 69, ../../scss/_ui-spinner.scss */
  75% {
    -webkit-transform: rotate(180deg);
  }

  /* line 70, ../../scss/_ui-spinner.scss */
  100% {
    -webkit-transform: rotate(360deg);
  }
}

@-moz-keyframes ui-spinner-rotate-right {
  /* line 74, ../../scss/_ui-spinner.scss */
  0% {
    -moz-transform: rotate(0deg);
  }

  /* line 75, ../../scss/_ui-spinner.scss */
  25% {
    -moz-transform: rotate(180deg);
  }

  /* line 76, ../../scss/_ui-spinner.scss */
  50% {
    -moz-transform: rotate(180deg);
  }

  /* line 77, ../../scss/_ui-spinner.scss */
  75% {
    -moz-transform: rotate(360deg);
  }

  /* line 78, ../../scss/_ui-spinner.scss */
  100% {
    -moz-transform: rotate(360deg);
  }
}

@-moz-keyframes ui-spinner-rotate-left {
  /* line 82, ../../scss/_ui-spinner.scss */
  0% {
    -moz-transform: rotate(0deg);
  }

  /* line 83, ../../scss/_ui-spinner.scss */
  25% {
    -moz-transform: rotate(0deg);
  }

  /* line 84, ../../scss/_ui-spinner.scss */
  50% {
    -moz-transform: rotate(180deg);
  }

  /* line 85, ../../scss/_ui-spinner.scss */
  75% {
    -moz-transform: rotate(180deg);
  }

  /* line 86, ../../scss/_ui-spinner.scss */
  100% {
    -moz-transform: rotate(360deg);
  }
}

@keyframes ui-spinner-rotate-right {
  /* line 90, ../../scss/_ui-spinner.scss */
  0% {
    transform: rotate(0deg);
  }

  /* line 91, ../../scss/_ui-spinner.scss */
  25% {
    transform: rotate(180deg);
  }

  /* line 92, ../../scss/_ui-spinner.scss */
  50% {
    transform: rotate(180deg);
  }

  /* line 93, ../../scss/_ui-spinner.scss */
  75% {
    transform: rotate(360deg);
  }

  /* line 94, ../../scss/_ui-spinner.scss */
  100% {
    transform: rotate(360deg);
  }
}

@keyframes ui-spinner-rotate-left {
  /* line 98, ../../scss/_ui-spinner.scss */
  0% {
    transform: rotate(0deg);
  }

  /* line 99, ../../scss/_ui-spinner.scss */
  25% {
    transform: rotate(0deg);
  }

  /* line 100, ../../scss/_ui-spinner.scss */
  50% {
    transform: rotate(180deg);
  }

  /* line 101, ../../scss/_ui-spinner.scss */
  75% {
    transform: rotate(180deg);
  }

  /* line 102, ../../scss/_ui-spinner.scss */
  100% {
    transform: rotate(360deg);
  }
}

/* line 110, ../../scss/_ui-spinner.scss */
.ui-spinner {
  position: relative;
  border-radius: 100%;
}
/* line 114, ../../scss/_ui-spinner.scss */
.ui-spinner .side {
  width: 50%;
  height: 100%;
  overflow: hidden;
  position: absolute;
}
/* line 120, ../../scss/_ui-spinner.scss */
.ui-spinner .side .fill {
  border-radius: 999px;
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-animation-iteration-count: infinite;
  -moz-animation-iteration-count: infinite;
  -ms-animation-iteration-count: infinite;
  -o-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
  -moz-animation-timing-function: linear;
  -ms-animation-timing-function: linear;
  -o-animation-timing-function: linear;
  animation-timing-function: linear;
}
/* line 130, ../../scss/_ui-spinner.scss */
.ui-spinner .side-left {
  left: 0;
}
/* line 133, ../../scss/_ui-spinner.scss */
.ui-spinner .side-left .fill {
  left: 100%;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  -webkit-animation-name: ui-spinner-rotate-left;
  -moz-animation-name: ui-spinner-rotate-left;
  -ms-animation-name: ui-spinner-rotate-left;
  -o-animation-name: ui-spinner-rotate-left;
  animation-name: ui-spinner-rotate-left;
  -webkit-transform-origin: 0 50%;
  -moz-transform-origin: 0 50%;
  -ms-transform-origin: 0 50%;
  -o-transform-origin: 0 50%;
  transform-origin: 0 50%;
}
/* line 142, ../../scss/_ui-spinner.scss */
.ui-spinner .side-right {
  left: 50%;
}
/* line 145, ../../scss/_ui-spinner.scss */
.ui-spinner .side-right .fill {
  left: -100%;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  -webkit-animation-name: ui-spinner-rotate-right;
  -moz-animation-name: ui-spinner-rotate-right;
  -ms-animation-name: ui-spinner-rotate-right;
  -o-animation-name: ui-spinner-rotate-right;
  animation-name: ui-spinner-rotate-right;
  -webkit-transform-origin: 100% 50%;
  -moz-transform-origin: 100% 50%;
  -ms-transform-origin: 100% 50%;
  -o-transform-origin: 100% 50%;
  transform-origin: 100% 50%;
}

/* line 1, ../../scss/_ui.scss */
.ui {
  width: 100%;
  position: relative;
  margin: 30px 0 0 0;
}
/* line 6, ../../scss/_ui.scss */
.ui .next {
  font-size: 1em;
  position: absolute;
  display: inline-block;
  color: rgb(0, 0, 0);
  cursor: pointer;
  right: 17px;
}
/* line 14, ../../scss/_ui.scss */
.ui .prev {
  font-size: 1em;
  position: absolute;
  display: inline-block;
  color: rgb(0, 0, 0);
  cursor: pointer;
  left: 17px;
}

/* line 26, ../../scss/_ui-spinner.scss */
.ui-spinner {
  width: 46px;
  height: 46px;
  background: #dddddd;
}
/* line 31, ../../scss/_ui-spinner.scss */
.ui-spinner .side .fill {
  background: #3c76ca;
  -webkit-animation-duration: 3s;
  -moz-animation-duration: 3s;
  -ms-animation-duration: 3s;
  -o-animation-duration: 3s;
  animation-duration: 3s;
  opacity: 0.8;
}
/* line 39, ../../scss/_ui-spinner.scss */
.ui-spinner:after {
  content: "";
  background: transparent;
  position: absolute;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  top: 9px;
  left: 9px;
  display: block;
}

/* line 11, ../../scss/main.scss */
body {
  font-size: 12px;
  font-family: roc-grotesk, sans-serif;
  font-weight: 300;
  background-color: rgb(255, 255, 255);
  text-align: center;
  margin: 0 auto;
  width: 100%;
}

/* line 39, ../../scss/main.scss */
body .threesixty-wrapper {
  margin: 0;
  height: 100vh;
  width: 100%;
  position: relative;
}
/* line 43, ../../scss/main.scss */
body .threesixty-wrapper .threesixty {
  display: block;
  width: 100%;
  
}
/* line 26, ../../scss/_ui-spinner.scss */
body .threesixty-wrapper .threesixty .ui-spinner {
  width: 50px;
  height: 50px;
  background: #c2fccc;
}
/* line 31, ../../scss/_ui-spinner.scss */
body .threesixty-wrapper .threesixty .ui-spinner .side .fill {
  background: #55fc5a;
  -webkit-animation-duration: 3s;
  -moz-animation-duration: 3s;
  -ms-animation-duration: 3s;
  -o-animation-duration: 3s;
  animation-duration: 3s;
  opacity: 0.8;
}
/* line 39, ../../scss/_ui-spinner.scss */
body .threesixty-wrapper .threesixty .ui-spinner:after {
  content: "";
  background: transparent;
  position: absolute;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  top: 10px;
  left: 10px;
  display: block;
}
/* line 49, ../../scss/main.scss */
body .threesixty-wrapper .threesixty .ui-spinner {
  margin: 270px auto;
}
/* line 54, ../../scss/main.scss */
body .threesixty-wrapper .label {
  margin: 0 auto;
  display: inline-block;
}

.threesixty img {
  width: auto;
  margin: 0 auto;
  height: 80vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<html>
    <head>
        <title>ThreeSixty</title>
        <link rel="stylesheet" href="https://use.typekit.net/spl8uhp.css">
    </head>

    <body>

        <div class="threesixty-wrapper">

            <div class="threesixty" data-link="https://ergoncreative-my.sharepoint.com/personal/anna_ergoncreative_com/Documents/src/Finnplay{index}.png" data-count="19">
                <!-- put your preloader here -->
                <div class="ui-spinner">
                    <span class="side side-left">
                        <span class="fill"></span>
                    </span>
                    <span class="side side-right">
                        <span class="fill"></span>
                    </span>
                </div>
                <!-- end preloader -->
            </div>

            <div class="ui">
                <div class="next">next frame</div>
                <div class="prev">previous frame</div>
            </div>

            <img src="assets/img/label.png" alt="" class="label"/>

        </div>

        <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script>
            $(document).ready(function(){

                var $threeSixty = $('.threesixty');

                $threeSixty.threeSixty({
                    dragDirection: 'horizontal',
                    useKeys: true,
                    draggable: true
                });

                $('.next').click(function(){
                    $threeSixty.nextFrame();
                });

                $('.prev').click(function(){
                    $threeSixty.prevFrame();
                });

                $threeSixty.on('down', function(){
                    $('.ui, h1, h2, .label, .examples').stop().animate({opacity:0}, 300);
                });

                $threeSixty.on('up', function(){
                    $('.ui, h1, h2, .label, .examples').stop().animate({opacity:1}, 500);
                });
            });
        </script>
    </body>
</html>

标签: javascriptjquery360-degrees

解决方案


推荐阅读