图片轮播Codepen图片未加载

时间:2018-06-26 00:06:41

标签: javascript jquery html carousel

我一直在尝试在我的网站上实现此Codepen [https://codepen.io/LokeshNagarajan/pen/apRmZe?editors=1111],但就像在Codepen中一样,即使我分配了https src也无法加载图像,并且我相信问题是由javascript引起的,但不确定确切地解决该问题。

(function ($) {
  'use strict';

  $.fn.waterwheelCarousel = function (startingOptions) {

// Adds support for intializing multiple carousels from the same selector group
if (this.length > 1) {
  this.each(function () {
    $(this).waterwheelCarousel(startingOptions);
  });
  return this; // allow chaining
}

var carousel = this;
var options = {};
var data = {};

function initializeCarouselData() {
  data = {
    itemsContainer: $(carousel),
    totalItems: $(carousel).children().length,
    containerWidth: $(carousel).width(),
    containerHeight: $(carousel).height(),
    currentCenterItem: null,
    previousCenterItem: null,
    items: [],
    calculations: [],
    carouselRotationsLeft: 0,
    currentlyMoving: false,
    itemsAnimating: 0,
    currentSpeed: options.speed,
    intervalTimer: null,
    currentDirection: 'forward',
    leftItemsCount: 0,
    rightItemsCount: 0,
    performingSetup: true
  };
  data.itemsContainer.children().removeClass(options.activeClassName);
}

/**
 * This function will set the autoplay for the carousel to
 * automatically rotate it given the time in the options
 * Can clear the autoplay by passing in true
 */
function autoPlay(stop) {
  // clear timer
  clearTimeout(data.autoPlayTimer);
  // as long as no stop command, and autoplay isn't zeroed...
  if (!stop && options.autoPlay !== 0) {
    // set timer...
    data.autoPlayTimer = setTimeout(function () {
      // to move the carousl in either direction...
      if (options.autoPlay > 0) {
        moveOnce('forward');
      } else {
        moveOnce('backward');
      }
    }, Math.abs(options.autoPlay));
  }
}

/**
 * This function will preload all the images in the carousel before
 * calling the passed in callback function. This is only used so we can
 * properly determine the width and height of the items. This is not needed
 * if a user instead manually specifies that information.
 */
function preload(callback) {

  var $imageElements = data.itemsContainer.find('img'),
      totalImages = $imageElements.length,
      loadedImages = 0;

  if (options.preloadImages === false || $imageElements.length === 0) {
    callback();
    return;
  }

  $imageElements.each(function () {
    $(this).bind('load', function () {
      // Add to number of images loaded and see if they are all done yet
      loadedImages += 1;
      if (loadedImages === totalImages) {
        // All done, perform callback
        callback();
        return;
      }
    });
    // May need to manually reset the src to get the load event to fire
    // http://stackoverflow.com/questions/7137737/ie9-problems-with-jquery-load-event-not-firing
    $(this).attr('src', $(this).attr('src'));

    // If browser has cached the images, it may not call trigger a load. Detect this and do it ourselves
    if (this.complete) {
      $(this).trigger('load');
    }
  });
}

/**
 * Makes a record of the original width and height of all the items in the carousel.
 * If we re-intialize the carousel, these values can be used to re-establish their
 * original dimensions.
 */
function setOriginalItemDimensions() {
  data.itemsContainer.children().each(function () {
    if ($(this).data('original_width') == undefined || options.forcedImageWidth > 0) {
      $(this).data('original_width', $(this).width());
    }
    if ($(this).data('original_height') == undefined || options.forcedImageHeight > 0) {
      $(this).data('original_height', $(this).height());
    }
  });
}

/**
 * Users can pass in a specific width and height that should be applied to every image.
 * While this option can be used in conjunction with the image preloader, the intended
 * use case is for when the preloader is turned off and the images don't have defined
 * dimensions in CSS. The carousel needs dimensions one way or another to work properly.
 */
function forceImageDimensionsIfEnabled() {
  if (options.forcedImageWidth && options.forcedImageHeight) {
    data.itemsContainer.children().each(function () {
      $(this).width(options.forcedImageWidth);
      $(this).height(options.forcedImageHeight);
    });
  }
}

/**
 * For each "visible" item slot (# of flanking items plus the middle),
 * we pre-calculate all of the properties that the item should possess while
 * occupying that slot. This saves us some time during the actual animation.
 */
function preCalculatePositionProperties() {
  // The 0 index is the center item in the carousel
  var $firstItem = data.itemsContainer.children().eq(0);

  data.calculations[0] = {
    distance: 0,
    offset: 0,
    opacity: 1
  }

  // Then, for each number of flanking items (plus one more, see below), we
  // perform the calcations based on our user options
  var horizonOffset = options.horizonOffset;
  var separation = options.separation;
  for (var i = 1; i <= options.flankingItems + 2; i++) {
    if (i > 1) {
      horizonOffset *= options.horizonOffsetMultiplier;
      separation *= options.separationMultiplier;
    }
    data.calculations[i] = {
      distance: data.calculations[i - 1].distance + separation,
      offset: data.calculations[i - 1].offset + horizonOffset,
      opacity: data.calculations[i - 1].opacity * options.opacityMultiplier
    }
  }
  // We performed 1 extra set of calculations above so that the items that
  // are moving out of sight (based on # of flanking items) gracefully animate there
  // However, we need them to animate to hidden, so we set the opacity to 0 for
  // that last item
  if (options.edgeFadeEnabled) {
    data.calculations[options.flankingItems + 1].opacity = 0;
  } else {
    data.calculations[options.flankingItems + 1] = {
      distance: 0,
      offset: 0,
      opacity: 0
    }
  }
}

/**
 * Here we prep the carousel and its items, like setting default CSS
 * attributes. All items start in the middle position by default
 * and will "fan out" from there during the first animation
 */
function setupCarousel() {
  // Fill in a data array with jQuery objects of all the images
  data.items = data.itemsContainer.children();
  for (var i = 0; i < data.totalItems; i++) {
    data.items[i] = $(data.items[i]);
  }

  // May need to set the horizon if it was set to auto
  if (options.horizon === 0) {
    if (options.orientation === 'horizontal') {
      options.horizon = data.containerHeight / 2;
    } else {
      options.horizon = data.containerWidth / 2;
    }
  }

  // Default all the items to the center position
  data.itemsContainer
      .css('position', 'relative')
      .children()
      .each(function () {
        // Figure out where the top and left positions for center should be
        var centerPosLeft, centerPosTop;
        if (options.orientation === 'horizontal') {
          centerPosLeft = (data.containerWidth / 2) - ($(this).data('original_width') / 2);
          centerPosTop = options.horizon - ($(this).data('original_height') / 2);
        } else {
          centerPosLeft = options.horizon - ($(this).data('original_width') / 2);
          centerPosTop = (data.containerHeight / 2) - ($(this).data('original_height') / 2);
        }
        $(this)
          // Apply positioning and layering to the images
            .css({
              'left': centerPosLeft,
              'top': centerPosTop,
              'visibility': 'visible',
              'position': 'absolute',
              'z-index': 0,
              'opacity': 0
            })
          // Give each image a data object so it remembers specific data about
          // it's original form
            .data({
              top: centerPosTop,
              left: centerPosLeft,
              oldPosition: 0,
              currentPosition: 0,
              depth: 0,
              opacity: 0
            })
          // The image has been setup... Now we can show it
            .show();
      });
}

/**
 * All the items to the left and right of the center item need to be
 * animated to their starting positions. This function will
 * figure out what items go where and will animate them there
 */
function setupStarterRotation() {
  options.startingItem = (options.startingItem === 0) ? Math.round(data.totalItems / 2) : options.startingItem;

  data.rightItemsCount = Math.ceil((data.totalItems - 1) / 2);
  data.leftItemsCount = Math.floor((data.totalItems - 1) / 2);

  // We are in effect rotating the carousel, so we need to set that
  data.carouselRotationsLeft = 1;

  // Center item
  moveItem(data.items[options.startingItem - 1], 0);
  data.items[options.startingItem - 1].css('opacity', 1);

  // All the items to the right of center
  var itemIndex = options.startingItem - 1;
  for (var pos = 1; pos <= data.rightItemsCount; pos++) {
    (itemIndex < data.totalItems - 1) ? itemIndex += 1 : itemIndex = 0;

    data.items[itemIndex].css('opacity', 1);
    moveItem(data.items[itemIndex], pos);
  }

  // All items to left of center
  var itemIndex = options.startingItem - 1;
  for (var pos = -1; pos >= data.leftItemsCount * -1; pos--) {
    (itemIndex > 0) ? itemIndex -= 1 : itemIndex = data.totalItems - 1;

    data.items[itemIndex].css('opacity', 1);
    moveItem(data.items[itemIndex], pos);
  }
}

/**
 * Given the item and position, this function will calculate the new data
 * for the item. One the calculations are done, it will store that data in
 * the items data object
 */
function performCalculations($item, newPosition) {
  var newDistanceFromCenter = Math.abs(newPosition);

  // Distance to the center
  if (newDistanceFromCenter < options.flankingItems + 1) {
    var calculations = data.calculations[newDistanceFromCenter];
  } else {
    var calculations = data.calculations[options.flankingItems + 1];
  }

  var distanceFactor = Math.pow(options.sizeMultiplier, newDistanceFromCenter)
  var newWidth = distanceFactor * $item.data('original_width');
  var newHeight = distanceFactor * $item.data('original_height');
  var widthDifference = Math.abs($item.width() - newWidth);
  var heightDifference = Math.abs($item.height() - newHeight);

  var newOffset = calculations.offset
  var newDistance = calculations.distance;
  if (newPosition < 0) {
    newDistance *= -1;
  }

  if (options.orientation == 'horizontal') {
    var center = data.containerWidth / 2;
    var newLeft = center + newDistance - (newWidth / 2);
    var newTop = options.horizon - newOffset - (newHeight / 2);
  } else {
    var center = data.containerHeight / 2;
    var newLeft = options.horizon - newOffset - (newWidth / 2);
    var newTop = center + newDistance - (newHeight / 2);
  }

  newTop -= heightDifference / 2;
  newLeft -= widthDifference / 2;

  var newOpacity;
  if (newPosition === 0) {
    newOpacity = 1;
  } else {
    newOpacity = calculations.opacity;
  }

  // Depth will be reverse distance from center
  var newDepth = options.flankingItems + 2 - newDistanceFromCenter;

  $item.data('width', newWidth);
  $item.data('height', newHeight);
  $item.data('top', newTop);
  $item.data('left', newLeft);
  $item.data('oldPosition', $item.data('currentPosition'));
  $item.data('depth', newDepth);
  $item.data('opacity', newOpacity);
  $item.data('distanceFactor', distanceFactor);
}

function moveItem($item, newPosition) {
  // Only want to physically move the item if it is within the boundaries
  // or in the first position just outside either boundary
  if (Math.abs(newPosition) <= options.flankingItems + 1) {
    performCalculations($item, newPosition);

    data.itemsAnimating++;

    $item
        .css('z-index', $item.data().depth)
      // Animate the items to their new position values
        .animate({
          'left': $item.data().left,
          'top': $item.data().top,
          'opacity': $item.data().opacity
        }, data.currentSpeed, options.animationEasing, function () {
          // Animation for the item has completed, call method
          itemAnimationComplete($item, newPosition);
        });

    TweenMax.to($item, data.currentSpeed / 1000, {
      scaleX: $item.data('distanceFactor'),
      scaleY: $item.data('distanceFactor'),
      ease: options.animationEasing
    });

  } else {
    $item.data('currentPosition', newPosition)
    // Move the item to the 'hidden' position if hasn't been moved yet
    // This is for the intitial setup
    if ($item.data('oldPosition') === 0) {
      $item
          .css({
            'left': $item.data().left,
            'top': $item.data().top,
            'opacity': $item.data().opacity,
            'z-index': $item.data().depth
          });

      TweenMax.to($item, 0, {
        scaleX: $item.data('distanceFactor'),
        scaleY: $item.data('distanceFactor')
      });
    }
  }

}

/**
 * This function is called once an item has finished animating to its
 * given position. Several different statements are executed here, such as
 * dealing with the animation queue
 */
function itemAnimationComplete($item, newPosition) {
  data.itemsAnimating--;

  $item.data('currentPosition', newPosition);

  // Keep track of what items came and left the center position,
  // so we can fire callbacks when all the rotations are completed
  if (newPosition === 0) {
    data.currentCenterItem = $item;
  }

  // all items have finished their rotation, lets clean up
  if (data.itemsAnimating === 0) {
    data.carouselRotationsLeft -= 1;
    data.currentlyMoving = false;

    // If there are still rotations left in the queue, rotate the carousel again
    // we pass in zero because we don't want to add any additional rotations
    if (data.carouselRotationsLeft > 0) {
      rotateCarousel(0);
      // Otherwise there are no more rotations and...
    } else {
      // Reset the speed of the carousel to original
      data.currentSpeed = options.speed;

      data.currentCenterItem.addClass(options.activeClassName);

      if (data.performingSetup === false) {
        options.movedToCenter(data.currentCenterItem);
        options.movedFromCenter(data.previousCenterItem);
      }

      data.performingSetup = false;
      // reset & initate the autoPlay
      autoPlay();
    }
  }
}

/**
 * Function called to rotate the carousel the given number of rotations
 * in the given direciton. Will check to make sure the carousel should
 * be able to move, and then adjust speed and move items
 */
function rotateCarousel(rotations) {
  // Check to see that a rotation is allowed
  if (data.currentlyMoving === false) {

    // Remove active class from the center item while we rotate
    data.currentCenterItem.removeClass(options.activeClassName);

    data.currentlyMoving = true;
    data.itemsAnimating = 0;
    data.carouselRotationsLeft += rotations;

    if (options.quickerForFurther === true) {
      // Figure out how fast the carousel should rotate
      if (rotations > 1) {
        data.currentSpeed = options.speed / rotations;
      }
      // Assure the speed is above the minimum to avoid weird results
      data.currentSpeed = (data.currentSpeed < 100) ? 100 : data.currentSpeed;
    }

    // Iterate thru each item and move it
    for (var i = 0; i < data.totalItems; i++) {
      var $item = $(data.items[i]);
      var currentPosition = $item.data('currentPosition');

      var newPosition;
      if (data.currentDirection == 'forward') {
        newPosition = currentPosition - 1;
      } else {
        newPosition = currentPosition + 1;
      }
      // We keep both sides as even as possible to allow circular rotation to work.
      // We will "wrap" the item arround to the other side by negating its current position
      var flankingAllowance = (newPosition > 0) ? data.rightItemsCount : data.leftItemsCount;
      if (Math.abs(newPosition) > flankingAllowance) {
        newPosition = currentPosition * -1;
        // If there's an uneven number of "flanking" items, we need to compenstate for that
        // when we have an item switch sides. The right side will always have 1 more in that case
        if (data.totalItems % 2 == 0) {
          newPosition += 1;
        }
      }

      moveItem($item, newPosition);
    }
  }
}

/**
 * The event handler when an image within the carousel is clicked
 * This function will rotate the carousel the correct number of rotations
 * to get the clicked item to the center, or will fire the custom event
 * the user passed in if the center item is clicked
 */
$(this).children().bind("click", function () {
  var itemPosition = $(this).data().currentPosition;

  if (options.imageNav == false) {
    return;
  }
  // Don't allow hidden items to be clicked
  if (Math.abs(itemPosition) >= options.flankingItems + 1) {
    return;
  }
  // Do nothing if the carousel is already moving
  if (data.currentlyMoving) {
    return;
  }

  data.previousCenterItem = data.currentCenterItem;

  // Remove autoplay
  autoPlay(true);
  options.autoPlay = 0;

  var rotations = Math.abs(itemPosition);
  if (itemPosition == 0) {
    options.clickedCenter($(this));
  } else {
    // Fire the 'moving' callbacks
    options.movingFromCenter(data.currentCenterItem);
    options.movingToCenter($(this));
    if (itemPosition < 0) {
      data.currentDirection = 'backward';
      rotateCarousel(rotations);
    } else if (itemPosition > 0) {
      data.currentDirection = 'forward';
      rotateCarousel(rotations);
    }
  }
});

function nextItemFromCenter() {
  var $next = data.currentCenterItem.next();
  if ($next.length <= 0) {
    $next = data.currentCenterItem.parent().children().first();
  }
  return $next;
}

function prevItemFromCenter() {
  var $prev = data.currentCenterItem.prev();
  if ($prev.length <= 0) {
    $prev = data.currentCenterItem.parent().children().last();
  }
  return $prev;
}

/**
 * Intiate a move of the carousel in either direction. Takes care of firing
 * the 'moving' callbacks
 */
function moveOnce(direction) {
  if (data.currentlyMoving === false) {
    data.previousCenterItem = data.currentCenterItem;

    options.movingFromCenter(data.currentCenterItem);
    if (direction == 'backward') {
      options.movingToCenter(prevItemFromCenter());
      data.currentDirection = 'backward';
    } else if (direction == 'forward') {
      options.movingToCenter(nextItemFromCenter());
      data.currentDirection = 'forward';
    }
  }

  rotateCarousel(1);
}

/**
 * Navigation with arrow keys
 */
$(document).keydown(function (e) {
  if (options.keyboardNav) {
    // arrow left or up
    if ((e.which === 37 && options.orientation == 'horizontal') || (e.which === 38 && options.orientation == 'vertical')) {
      autoPlay(true);
      options.autoPlay = 0;
      moveOnce('backward');
      // arrow right or down
    } else if ((e.which === 39 && options.orientation == 'horizontal') || (e.which === 40 && options.orientation == 'vertical')) {
      autoPlay(true);
      options.autoPlay = 0;
      moveOnce('forward');
    }
    // should we override the normal functionality for the arrow keys?
    if (options.keyboardNavOverride && (
            (options.orientation == 'horizontal' && (e.which === 37 || e.which === 39)) ||
            (options.orientation == 'vertical' && (e.which === 38 || e.which === 40))
        )) {
      e.preventDefault();
      return false;
    }
  }
});

/**
 * Public API methods
 */
this.reload = function (newOptions) {
  if (typeof newOptions === "object") {
    var combineDefaultWith = newOptions;
  } else {
    var combineDefaultWith = {};
  }
  options = $.extend({}, $.fn.waterwheelCarousel.defaults, newOptions);

  initializeCarouselData();
  data.itemsContainer.children().hide();
  forceImageDimensionsIfEnabled();

  preload(function () {
    setOriginalItemDimensions();
    preCalculatePositionProperties();
    setupCarousel();
    setupStarterRotation();
  });
}

this.next = function () {
  autoPlay(true);
  options.autoPlay = 0;

  moveOnce('forward');
}
this.prev = function () {
  autoPlay(true);
  options.autoPlay = 0;

  moveOnce('backward');
}

this.reload(startingOptions);

return this;
  };

  $.fn.waterwheelCarousel.defaults = {
// number tweeks to change apperance
startingItem: 1,   // item to place in the center of the carousel. Set to 0 for auto
separation: 175, // distance between items in carousel
separationMultiplier: 0.6, // multipled by separation distance to increase/decrease distance for each additional item
horizonOffset: 0,   // offset each item from the "horizon" by this amount (causes arching)
horizonOffsetMultiplier: 1,   // multipled by horizon offset to increase/decrease offset for each additional item
sizeMultiplier: 0.7, // determines how drastically the size of each item changes
opacityMultiplier: 0.8, // determines how drastically the opacity of each item changes
horizon: 0,   // how "far in" the horizontal/vertical horizon should be set from the container wall. 0 for auto
flankingItems: 3,   // the number of items visible on either side of the center

// animation
speed: 300,      // speed in milliseconds it will take to rotate from one to the next
animationEasing: 'linear', // the easing effect to use when animating
quickerForFurther: true,     // set to true to make animations faster when clicking an item that is far away from the center
edgeFadeEnabled: false,    // when true, items fade off into nothingness when reaching the edge. false to have them move behind the center image

// misc
linkHandling: 2,                 // 1 to disable all (used for facebox), 2 to disable all but center (to link images out)
autoPlay: 0,                 // indicate the speed in milliseconds to wait before autorotating. 0 to turn off. Can be negative
orientation: 'horizontal',      // indicate if the carousel should be 'horizontal' or 'vertical'
activeClassName: 'carousel-center', // the name of the class given to the current item in the center
keyboardNav: false,             // set to true to move the carousel with the arrow keys
keyboardNavOverride: true,              // set to true to override the normal functionality of the arrow keys (prevents scrolling)
imageNav: true,              // clicking a non-center image will rotate that image to the center

// preloader
preloadImages: true,  // disable/enable the image preloader.
forcedImageWidth: 0,     // specify width of all images; otherwise the carousel tries to calculate it
forcedImageHeight: 0,     // specify height of all images; otherwise the carousel tries to calculate it

// callback functions
movingToCenter: $.noop, // fired when an item is about to move to the center position
movedToCenter: $.noop, // fired when an item has finished moving to the center
clickedCenter: $.noop, // fired when the center item has been clicked
movingFromCenter: $.noop, // fired when an item is about to leave the center position
movedFromCenter: $.noop  // fired when an item has finished moving from the center
  };

})(jQuery);


   /*--water_wheel_carousel--*/
var carousel = $("#carousel").waterwheelCarousel({
     flankingItems: 2,
     separation:200,
     sizeMultiplier:0.8,
     separationMultiplier:0.9,
     speed:250,
 });

 $("#carousel").swipe( {
    swipeStatus:function(event, phase, direction, distance)
    {
        if (phase=="end"){
            if(direction == "right") { 
                carousel.prev();
            }
            else if(direction =="left") {
                carousel.next();
            }else { return false;}
        }
    },
    triggerOnTouchEnd:false,
    threshold:100
});
$('#prev').on('click', function (){
    carousel.prev();
    return false;
});
$('#next').on('click', function (){
    carousel.next();
    return false;
});
/*--water_wheel carousel_script_end--*/

请帮助我修复JavaScript,以便将解决方案应用于我的代码。谢谢

1 个答案:

答案 0 :(得分:0)

您的图像正在加载,但是在其顶部有白色背景的DIV在视觉上阻挡了图像。如果在这些DIV上删除背景色CSS声明,则图像将显示出来。只需更新此内容即可:

#carousel .caption {
    position: absolute;
    background-color:#FFF;
    top: 0px;
    left: 0px;
    height:100%;
    width:100%;
}

对此:

#carousel .caption {
    position: absolute;
    top: 0px;
    left: 0px;
    height:100%;
    width:100%;
}