【问题标题】:How do I make this "carousel" show three divs instead of one?如何让这个“轮播”显示三个 div 而不是一个?
【发布时间】:2022-02-04 21:39:47
【问题描述】:

我有这个轮播显示一张图片,我想将其更改为包含三个 div,每个 div 包含图片和文本。出于测试目的,我只添加了带有测试的文本。

我的原型不能像我想要的那样工作,但我的代码如下:

HTML:

<div class="carousel-container" style="margin-bottom: 20px;margin-top: 40px;">
<div class="flex-container marginimg">
  <div class="carousel">     
    <div class="slide">
        Test1
    </div>
     <div class="slide">
        Test2
         </div>
         <div class="slide">
        Test3
         </div>
         <div class="slide">
        Test4
           </div>
         <div class="slide">
        Test5
    </div>
  </div>
 
  <button class="hide carousel-prev slider-button slider-black slider-display-left left-slider-button">
    &#10094;
  </button>
  <button class="hide carousel-next slider-button slider-black slider-display-right right-slider-button">
    &#10095;
  </button>
</div>
</div>
<script src="~/js/newsreel.js"></script>

我的 newsreel.js 包含以下内容:

class CarouselController {

    defaultSettings = {
        loop: true,
        delay: 8000,
        autoplay: false
    }

    /**
     * @@param {object} settings
     */
    constructor(settings) {
        this.carousel = settings.element;
        delete settings.element;

        this.current = 0;
        this.hooks = {};
        this.settings = settings;

        if (!this.carousel) {
            throw 'A carousel element is required. For example: new CarouselController({ element: document.getElementById(\'carousel\') })';
        }

        /**
         * Sanitize `loop` setting
         */
        this.addFilter('setting.loop', value => {
            return String(value).toLowerCase() === 'true';
        });

        /**
         * Sanitize `delay` setting
         */
        this.addFilter('setting.delay', value => parseInt(value));

        /**
         * Sanitize `autoplay` setting
         */
        this.addFilter('setting.autoplay', value => {
            return String(value).toLowerCase() === 'true';
        });

        // Autoplay on init.
        if (this.getSetting('autoplay')) {
            this.play();
        }
    }

    /**
     * Get the carousel container element.
     * @@returns {Element}
     */
    getCarousel() {
        return this.carousel;
    }

    /**
     * Get a setting value.
     * @@param {string} name
     * @@param defaultValue
     * @@returns {*}
     */
    getSetting(name, defaultValue) {
        if (!defaultValue && name in this.defaultSettings) {
            defaultValue = this.defaultSettings[name]
        }

        /**
         * Apply value filters.
         * @@example carousel.addFilter('setting.delay', function(value) { return value + 500; });
         */
        return this.applyFilters(`setting.${name}`, name in this.settings ? this.settings[name] : defaultValue);
    }

    /**
     * Get hooks by type and name. Ordered by priority.
     * @@param {string} type
     * @@param {string} name
     * @@returns {array}
     */
    getHooks(type, name) {
        let hooks = [];

        if (type in this.hooks) {
            let localHooks = this.hooks[type];
            localHooks = localHooks.filter(el => el.name === name);
            localHooks = localHooks.sort((a, b) => a.priority - b.priority);
            hooks = hooks.concat(localHooks);
        }

        return hooks;
    }

    /**
     * Add a hook.
     * @@param {string} type
     * @@param {object} hookMeta
     */
    addHook(type, hookMeta) {

        // Create new local hook type array.
        if (!(type in this.hooks)) {
            this.hooks[type] = [];
        }

        this.hooks[type].push(hookMeta);
    }

    /**
     * Add action listener.
     * @@param {string} action Name of action to trigger callback on.
     * @@param {function} callback
     * @@param {number} priority
     */
    addAction(action, callback, priority = 10) {
        this.addHook('actions', {
            name: action,
            callback: callback,
            priority: priority
        });
    }

    /**
     * Trigger an action.
     * @@param {string} name Name of action to run.
     * @@param {*} args Arguments passed to the callback function.
     */
    doAction(name, ...args) {
        this.getHooks('actions', name).forEach(hook => {
            hook.callback(...args);
        });
    }

    /**
     * Register filter.
     * @@param {string} filter Name of filter to trigger callback on.
     * @@param {function} callback
     * @@param {number} priority
     */
    addFilter(filter, callback, priority = 10) {
        this.addHook('filters', {
            name: filter,
            callback: callback,
            priority: priority
        });
    }

    /**
     * Apply all named filters to a value.
     * @@param {string} name Name of action to run.
     * @@param {*} value The value to be mutated.
     * @@param {*} args Arguments passed to the callback function.
     * @@returns {*}
     */
    applyFilters(name, value, ...args) {
        this.getHooks('filters', name).forEach(hook => {
            value = hook.callback(value, ...args);
        });

        return value;
    }

    /**
     * Get all the children (slides) elements.
     * @@returns {Element[]}
     */
    getSlides() {
        return Array.from(this.getCarousel().children);
    }

    /**
     * Get a specific slide by index.
     * @@param {int} index
     * @@returns {Element|null}
     */
    getSlide(index) {
        return this.getSlides()[index];
    }

    /**
     * Show a specific slide by index.
     * @@param {int} index
     * @@returns {int}
     */
    goTo(index) {
        const slides = this.getSlides();
        const slide = this.getSlide(index);
        const slide2 = this.getSlide(index + 1);
        const slide3 = this.getSlide(index + 2);

        if (slide) {
            slides.forEach((el) => {
                el.classList.remove('active');
            });

            slide.classList.add('active');
            slide2.classList.add('active');
            slide3.classList.add('active');

            this.current = slides.indexOf(slide);

            /**
             * Trigger goto event.
             * @@example carousel.addAction('goto', function(slide, index) { ... });
             */
            this.doAction('goto', slide, this.current);
        }

        return this.current;
    }

    /**
     * Show the next slide (if has one).
     */
    next() {
        let replay = false;

        // Check if carousel is looping through slides automatically.
        if (this.playing) {
            replay = true;
        }

        const slides = this.getSlides();
        let nextIndex = this.current + 1;

        // If the next slide is greater than the total, reset to 0 if looping else use -1 to stop `goTo` method.
        if (nextIndex > (slides.length - 1)) {
            if (this.getSetting('loop')) {
                nextIndex = 0;
            } else {
                nextIndex = -1;
            }
        }

        // Only go to slide if next index is valid.
        if (nextIndex >= 0) {
            this.goTo(nextIndex);

            // Continue with auto play.
            if (replay) {
                this.play();
            }
        }
    }

    /**
     * Show the previous slide (if has one).
     */
    previous() {
        let replay = false;

        // Check if carousel is looping through slides automatically.
        if (this.playing) {
            replay = true;
        }

        const slides = this.getSlides();
        let prevIndex = this.current - 1;

        // If the prev slide is less than 0, reset to the last slide if looping else use -1 to stop `goTo` method.
        if (prevIndex < 0) {
            if (this.getSetting('loop')) {
                prevIndex = slides.length - 1;
            } else {
                prevIndex = -1;
            }
        }

        // Only go to slide if next index is valid.
        if (prevIndex >= 0) {
            this.goTo(prevIndex);

            // Continue with auto play.
            if (replay) {
                this.play();
            }
        }
    }

    /**
     * Automatically go to the next slide (or start if loop is true).
     * @@returns {number}
     */
    play() {
        this.stop();

        this.goTo(this.current);

        this.playing = setInterval(() => {
            this.next();
        }, this.getSetting('delay'));

        return this.playing;
    }

    /**
     * Stop the automatic carousel if running.
     */
    stop() {
        if (this.playing) {
            clearInterval(this.playing);
        }
    }


}

/**
 * Get the carousel container element.
 * @@type {Element}
 */
const carouselContainer = document.querySelector('.carousel-container');

/**
 * Create a new controller instance for our carousel.
 * @@type {CarouselController}
 */
const carousel = new CarouselController({
    element: carouselContainer.querySelector('.carousel'),
    loop: true,
    delay: 8000,
    autoplay: true
});

/**
 * Lazy load each image only when the slide is in view.
 */
carousel.addAction('goto', function (slide, index) {
    let images = [];

    if (slide.tagName.toLowerCase() === 'img') {
        //$(".slider-text").hide();
        //$("#slidert"+slide.dataset.src.split("slider")[1].charAt(0) ).show();
        images.push(slide);
    } else {
        images.concat(slide.querySelectorAll('img'));
    }

    images.forEach((img) => {
        if (!img.src && img.dataset.src) {
            img.src = img.dataset.src;
        }
    });
});

/**
 * Show previous slide (if has one) when clicking previous button.
 */
document.querySelector('.carousel-prev').addEventListener('click', function (event) {
    event.preventDefault();
    carousel.previous();
});

/**
 * Show next slide (if has one) when clicking next button.
 */
document.querySelector('.carousel-next').addEventListener('click', function (event) {
    event.preventDefault();
    carousel.next();
});

我遇到的错误:

TypeError: can't access property "classList", slide3 is undefined
  • 我猜这是一个越界问题,也就是超出范围的问题?

  • 我做错了什么?

【问题讨论】:

    标签: javascript html css twitter-bootstrap carousel


    【解决方案1】:

    您可以使用现有的滑块库,例如 Slick.js,这将为您提供类似的设置,而无需自己执行轮播功能。

    【讨论】:

    • 对我来说它会抛出这个错误:Uncaught TypeError: $(...).slick is not a function。是的,我已经导入了 jQuery
    • 只有在没有正确导入 jQuery 时才会出现该错误,您是通过 CDN 执行此操作还是将 src 文件本身入队?
    • 我在 ASP.NET Core 中使用它,它已经在本地包含了 jQuery,我也在 HTML 中导入了它
    猜你喜欢
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 2019-08-21
    • 2012-04-28
    • 2020-04-08
    相关资源
    最近更新 更多