jQuery插件 - 分离所有实例的问题

时间:2017-12-07 19:48:31

标签: jquery jquery-plugins

在使用jQuery样板练习jQuery插件开发时,我尝试根据屏幕类型创建一个可以拖动和悬停的旋转木马。然而,在运行多个DOM元素的插件后,我发现我并没有完全分离它。可拖动的实例在旋转木马之间共享,并且全局迫使它们中的每一个同时移动。

说实话,我不知道应该在哪里寻找问题。这是我的第一个带有样板的项目,我觉得此刻有点迷失。

你能这么善良并看看我的代码吗?

https://codepen.io/Nikolaus91/pen/LOoERJ

(function($, window, document, undefined) {
// undefined is used here as the undefined global
// variable in ECMAScript 3 and is mutable (i.e. it can
// be changed by someone else). undefined isn't really
// being passed in so we can ensure that its value is
// truly undefined. In ES5, undefined can no longer be
// modified.

// window and document are passed through as local
// variables rather than as globals, because this (slightly)
// quickens the resolution process and can be more
// efficiently minified (especially when both are
// regularly referenced in your plugin).

// Create the defaults once
var pluginName = "finiteCarousel",
defaults = {
  singleRowClass: "finite-carousel__inner",
  singleSlideClass: "finite-carousel__slide"
};

// The actual plugin constructor
function Plugin(element, options) {
this.element = element;

// jQuery has an extend method that merges the
// contents of two or more objects, storing the
// result in the first object. The first object
// is generally empty because we don't want to alter
// the default options for future instances of the plugin
this.options = $.extend({}, defaults, options);

this._defaults = defaults;
this._name = pluginName;

this.init();
}

Plugin.prototype = {
init: function() {
  // Place initialization logic here
  // You already have access to the DOM element and
  // the options via the instance, e.g. this.element
  // and this.options
  //console.clear();
  console.log("Initiating");

  this.buildCache();
  console.log(this);
  console.log(this.$element);
  console.log(this.$container);
  console.log(this.$slides);

  this.buildDraggable();

  if (typeof Modernizr == "object") {
    if (!Modernizr.touchevents) {
      console.log("Binding mouse events");
      this.bindEvents();
      console.log(this.$draggable);
      //this.$draggable[0].disable();
    }
  }

  //console.log("Touchevents: " + Modernizr.touchevents);
},
// Cache DOM nodes for performance
buildCache: function() {
  /*
            Create variable(s) that can be accessed by other plugin
            functions. For example, "this.$element = $(this.element);"
            will cache a jQuery reference to the elementthat initialized
            the plugin. Cached variables can then be used in other methods. 
        */
  this.$element = $(this.element);
  this.$container = this.$element.find("." + defaults.singleRowClass);
  this.$slides = this.$element.find("." + defaults.singleSlideClass);

  this.$totalWidth = 0;
  this.$lastX = 0;
  this.$diffX;
  this.$currentX;
},
// Build draggable instance
buildDraggable: function() {
  var plugin = this;
  var isDragging = false;

  // Count all slides outer width
  plugin.$slides.each(function(index, elem) {
    plugin.$totalWidth += $(elem).outerWidth();
  });
  console.log("\nWidth of all slides: " + plugin.$totalWidth);

  // Build draggable instance
  plugin.$draggable = Draggable.create('<div />', {
    type: "x",
    trigger: plugin.$container,
    throwProps: true,
    edgeResistance: 0.95,
    onDrag: updateProgress,
    onThrowUpdate: updateProgress,
    onThrowComplete: function() {
      isDragging = false;
    },
    onPress: function() {
      //console.clear();
      //console.log(this);
      //console.log(plugin.$draggable[0]);
      plugin.$draggable[0].update();
      plugin.$lastX = plugin.$draggable[0].x;
      updatePosition(plugin.$draggable[0]);
      isDragging = true;
      TweenMax.killTweensOf(plugin.$draggable[0].target);
    },
    onComplete: function() {
      console.log("On Complete");
    }
  });

  function updateProgress() {
    plugin.$diffX = plugin.$draggable[0].x - plugin.$lastX;
    TweenMax.set("." + defaults.singleSlideClass, {
      x: "+=" + plugin.$diffX
    });
    plugin.$lastX = plugin.$draggable[0].x;
  }
  // Updates the position of all slides
  function updatePosition(draggableInstance) {
    plugin.$currentX = draggableInstance.target._gsTransform.x;
    plugin.$lastX = draggableInstance.target._gsTransform.x;

    plugin.$slides.each(function(index, elem) {
      TweenMax.set(elem, { x: plugin.$currentX });
      //currentX += $(elem).outerWidth();
    });
  }

  $(window).resize(applyBorders(plugin.$draggable[0]));
  applyBorders(plugin.$draggable[0]);
  // Apply borders to our carousel
  function applyBorders(draggableInstance) {
    var minx = plugin.$container.outerWidth() - plugin.$totalWidth;
    var maxx = 0;

    draggableInstance.applyBounds({ minX: minx, maxX: maxx });

    updatePosition(draggableInstance);
  }
},

// Bind mouse events
bindEvents: function() {
  var plugin = this;

  var isMouseOver = false;
  var direction;
  var mouseX, mouseY;
  var isDragging = false;
  var animateX;
  var animation = TweenMax.to({}, 0, {});
  var animationTimescale = 1;

  plugin.$container.on("mouseleave", function() {
    console.log("Mouse left");
    isMouseOver = false;
    TweenMax.killTweensOf(animation);
  });

  plugin.$container.on("mousemove", function(e) {
    var container = this;
    var rect = container.getBoundingClientRect();

    //console.log(rect);

    mouseX = e.pageX - rect.left;
    if (mouseX < rect.width / 5) {
      direction = 1;
      animationTimescale = Math.abs(mouseX / (rect.width / 25) - 5);
      isMouseOver = true;
    } else if (mouseX > rect.width - rect.width / 5) {
      direction = -1;
      animationTimescale = Math.abs(
        (rect.width - mouseX) / (rect.width / 25) - 5
      );
      isMouseOver = true;
    } else {
      isMouseOver = false;
    }
    //console.log(animationTimescale);
    animateX = rect.width / 5;

    if (!animation.isActive()) {
      animateSlides();
    } else {
      animation.timeScale(animationTimescale);
    }
  });

  function animateSlides() {
    if (
      plugin.$draggable[0].target._gsTransform.x < 0 ||
      plugin.$draggable[0].target._gsTransform.x >
        plugin.$container.outerWidth() - plugin.$totalWidth
    ) {
      if (isMouseOver && !isDragging) {
        animation = TweenMax.to(plugin.$draggable[0].target, 0.3, {
          ease: Linear.easeNone,
          x: "+=" + animateX * direction,
          modifiers: { x: checkBounds },
          onComplete: animateSlides,
          onUpdate: updateSlides
        });
      }
    }

    animation.timeScale(animationTimescale);
  }

  // Uses modifiers plugin to make sure slides remain within bound
  function checkBounds(value) {
    if (value > 0) {
      TweenMax.killTweensOf(plugin.$draggable[0].target);
      return 0;
    } else if (
      value <
      plugin.$container.outerWidth() - plugin.$totalWidth
    ) {
      TweenMax.killTweensOf(plugin.$draggable[0].target);
      return plugin.$container.outerWidth() - plugin.$totalWidth;
    }
    return value;
  }

  // Updates slides along with proxy element
  function updateSlides() {
    plugin.$diffX =
      plugin.$draggable[0].target._gsTransform.x - plugin.$lastX;
    TweenMax.set(plugin.$slides, { x: "+=" + plugin.$diffX });
    plugin.$lastX = plugin.$draggable[0].target._gsTransform.x;
    }
  } // end Bind events
};

// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function(options) {
console.clear();
return this.each(function() {
  console.log('Creating');
  if (!$.data(this, "plugin_" + pluginName)) {
    $.data(this, "plugin_" + pluginName, new Plugin(this, options));
  }
  });
};
})(jQuery, window, document);

$(".finite-carousel").finiteCarousel();

1 个答案:

答案 0 :(得分:0)

一切都运转良好,我在第283行遇到了拼写错误,我在全球范围内调用所有轮播元素:

    TweenMax.set("." + defaults.singleSlideClass), {
      x: "+=" + plugin.$diffX
    });

我必须将其更改为:

TweenMax.set(plugin.$slides, {
      x: "+=" + plugin.$diffX
    });

其中:

var plugin = this;
plugin.$slides = this.$element.find("." + defaults.singleSlideClass);