Dcat-admin 轮播图组件

实现功能:定义宽度,高度,切换时间等 效果图:

使用方法

php 复制代码
public function index(Content $content)
{
    return $content
        ->header('Dashboard')
        ->description('Description...')
        ->body(function (Row $row) {
            $row->column(6, function (Column $column) {
                // 创建轮播图实例
                $carousel = new Carousel();
                // 配置轮播图
                $carousel->addImages([
                    'https://gjba.cn/img/1.jpg',
                    'https://gjba.cn/img/2.jpg',
                    'https://gjba.cn/img/3.jpg',
                    'https://gjba.cn/img/4.jpg',
                ])
                    ->width('100%')     // 设置宽度
                    ->height('400px')    // 设置高度
                    ->interval(3000);
                $column->row($carousel->render());
            });


        });
}
复制代码
Carousel
ini 复制代码
<?php

namespace App\Admin\Extensions;

use Illuminate\Contracts\Support\Renderable;

class Carousel implements Renderable
{
    protected $images = [];
    protected $height = '300px';
    protected $width = '100%';
    protected $interval = 3000;
    protected $id;

    public function __construct()
    {
        $this->id = 'carousel-' . uniqid();
    }

    /**
     * 添加图片
     * @param string $src 图片地址
     * @return $this
     */
    public function addImage($src)
    {
        $this->images[] = $src;
        return $this;
    }

    /**
     * 批量添加图片
     * @param array $images 图片地址数组
     * @return $this
     */
    public function addImages(array $images)
    {
        foreach ($images as $image) {
            $this->addImage($image);
        }
        return $this;
    }

    /**
     * 设置轮播图高度
     * @param string|int $height 高度值(支持px、%、vh等单位)
     * @return $this
     */
    public function height($height)
    {
        $this->height = $this->formatSize($height);
        return $this;
    }

    /**
     * 设置轮播图宽度
     * @param string|int $width 宽度值(支持px、%、vw等单位)
     * @return $this
     */
    public function width($width)
    {
        $this->width = $this->formatSize($width);
        return $this;
    }

    /**
     * 格式化尺寸值
     * @param string|int $size
     * @return string
     */
    protected function formatSize($size)
    {
        if (is_numeric($size)) {
            return $size . 'px';
        }
        return $size;
    }

    /**
     * 设置自动播放间隔时间(毫秒)
     * @param int $interval
     * @return $this
     */
    public function interval($interval)
    {
        $this->interval = $interval;
        return $this;
    }

    /**
     * 渲染轮播图
     * @return string
     */
    public function render()
    {
        $containerStyle = "position: relative; width: {$this->width}; height: {$this->height}; overflow: hidden; margin: 0 auto;";
        
        $html = <<<HTML
        <div class="carousel-container {$this->id}" style="{$containerStyle}">
            <div class="carousel-wrapper" style="display: flex; transition: transform 0.5s ease;">
HTML;

        foreach ($this->images as $image) {
            $html .= <<<HTML
                <img src="{$image}" style="width: 100%; height: 100%; object-fit: cover; flex-shrink: 0;">
HTML;
        }

        $html .= <<<HTML
            </div>
            <button class="carousel-prev" style="position: absolute; left: 10px; top: 50%; transform: translateY(-50%); z-index: 2; background: rgba(0,0,0,0.5); color: white; border: none; padding: 10px 15px; cursor: pointer; border-radius: 50%; font-size: 18px;">←</button>
            <button class="carousel-next" style="position: absolute; right: 10px; top: 50%; transform: translateY(-50%); z-index: 2; background: rgba(0,0,0,0.5); color: white; border: none; padding: 10px 15px; cursor: pointer; border-radius: 50%; font-size: 18px;">→</button>
            <div class="carousel-dots" style="position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px;">
HTML;

        for ($i = 0; $i < count($this->images); $i++) {
            $html .= <<<HTML
                <span class="carousel-dot" data-index="{$i}" style="width: 12px; height: 12px; border-radius: 50%; background: white; cursor: pointer; transition: all 0.3s ease;"></span>
HTML;
        }

        $html .= <<<HTML
            </div>
        </div>

        <script>
        (function() {
            const container = document.querySelector('.{$this->id}');
            const wrapper = container.querySelector('.carousel-wrapper');
            const slides = wrapper.querySelectorAll('img');
            const prevBtn = container.querySelector('.carousel-prev');
            const nextBtn = container.querySelector('.carousel-next');
            const dots = container.querySelectorAll('.carousel-dot');
            let currentIndex = 0;
            const totalSlides = slides.length;

            function updateCarousel() {
                wrapper.style.transform = `translateX(-${currentIndex * 100}%)`;
                dots.forEach((dot, index) => {
                    dot.style.background = index === currentIndex ? '#007bff' : 'white';
                    dot.style.transform = index === currentIndex ? 'scale(1.2)' : 'scale(1)';
                });
            }

            function nextSlide() {
                currentIndex = (currentIndex + 1) % totalSlides;
                updateCarousel();
            }

            function prevSlide() {
                currentIndex = (currentIndex - 1 + totalSlides) % totalSlides;
                updateCarousel();
            }

            // 添加过渡动画效果
            wrapper.style.transition = 'transform 0.5s ease';

            // 事件监听
            prevBtn.addEventListener('click', prevSlide);
            nextBtn.addEventListener('click', nextSlide);

            dots.forEach((dot, index) => {
                dot.addEventListener('click', () => {
                    currentIndex = index;
                    updateCarousel();
                });
            });

            let autoplayInterval = setInterval(nextSlide, {$this->interval});

            // 鼠标悬停控制
            container.addEventListener('mouseenter', () => {
                clearInterval(autoplayInterval);
                prevBtn.style.opacity = '1';
                nextBtn.style.opacity = '1';
            });

            container.addEventListener('mouseleave', () => {
                autoplayInterval = setInterval(nextSlide, {$this->interval});
                prevBtn.style.opacity = '0.5';
                nextBtn.style.opacity = '0.5';
            });

            // 初始化显示
            updateCarousel();
            
            // 设置按钮初始透明度
            prevBtn.style.opacity = '0.5';
            nextBtn.style.opacity = '0.5';
            prevBtn.style.transition = 'opacity 0.3s ease';
            nextBtn.style.transition = 'opacity 0.3s ease';
        })();
        </script>
HTML;

        return $html;
    }
} 
相关推荐
两个人的幸福11 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo13 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack13 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820713 天前
PHP 扩展——从入门到理解
php
鹏仔先生14 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下14 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip14 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒15 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25015 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis15 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel