分类 js 下的文章

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <title>强制横屏显示框架</title>
    <style>
        *{margin:0;padding:0;box-sizing:border-box}
        body,html{width:100%;height:100%;font-family:'PingFang SC','Helvetica Neue',Arial,sans-serif}
        .landscape-container{width:100vh;height:100vw;transform-origin:0 0;transform:rotate(90deg) translateY(-100vh);position:absolute;top:0;left:0;overflow:auto;-webkit-overflow-scrolling:touch;background-color:#f5f7fa}
        .content{width:100%;min-height:100%;padding:20px;display:flex;flex-direction:column}
        .orientation-message{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.9);color:#fff;z-index:9999;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:20px}
        .orientation-message.show{display:flex}
        .orientation-icon{font-size:80px;margin-bottom:30px;animation:rotate 2s infinite ease-in-out}
        @keyframes rotate{0%,100%{transform:rotate(0)}
        50%{transform:rotate(90deg)}
        }
        .header{background:linear-gradient(135deg,#6a11cb 0,#2575fc 100%);color:#fff;padding:25px 20px;border-radius:10px;margin-bottom:25px;box-shadow:0 5px 15px rgba(0,0,0,.1)}
        .header h1{font-size:28px;margin-bottom:10px}
        .header p{opacity:.9;font-size:16px}
        .card-container{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:20px;margin-bottom:25px}
        .card{background-color:#fff;border-radius:10px;padding:20px;box-shadow:0 3px 10px rgba(0,0,0,.08);transition:transform .3s ease,box-shadow .3s ease}
        .card:hover{transform:translateY(-5px);box-shadow:0 8px 20px rgba(0,0,0,.12)}
        .card h3{color:#2c3e50;margin-bottom:15px;padding-bottom:10px;border-bottom:2px solid #f0f2f5}
        .card p{color:#546e7a;line-height:1.6}
        .scroll-indicator{position:fixed;bottom:20px;right:20px;background-color:#6a11cb;color:#fff;width:50px;height:50px;border-radius:50%;display:flex;justify-content:center;align-items:center;font-size:24px;box-shadow:0 4px 10px rgba(106,17,203,.3);z-index:100;cursor:pointer;opacity:.7;transition:opacity .3s}
        .scroll-indicator:hover{opacity:1}
        .device-info{background-color:#fff;border-radius:10px;padding:15px;margin-top:20px;box-shadow:0 3px 10px rgba(0,0,0,.08)}
        .device-info h3{color:#2c3e50;margin-bottom:10px}
        .info-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
        .info-item{padding:8px 0;border-bottom:1px solid #f0f2f5}
        .info-label{font-weight:700;color:#546e7a}
        .info-value{color:#2c3e50}
        @media (max-width:768px){.header h1{font-size:24px}
        .card-container{grid-template-columns:1fr}
        .info-grid{grid-template-columns:1fr}
        }
        .ios-scroll-fix{-webkit-overflow-scrolling:touch;overflow-y:auto}
        .landscape-locked{width:100vh;height:100vw;transform-origin:0 0;transform:rotate(90deg) translateY(-100vh);position:absolute;top:0;left:0;overflow:auto}
        #container{overflow:auto}

    </style>
</head>
<body>
    <!-- 横屏提示 -->
    <div id="orientationMessage" class="orientation-message">
        <div class="orientation-icon">🔄</div>
        <h2>请将设备旋转为横屏模式</h2>
        <p>此页面需要横屏显示以获得最佳体验</p>
    </div>
    
    <!-- 横屏内容容器 -->
    <div id="container"  >
        <div class="content">
            <div class="header">
                <h1>强制横屏显示框架</h1>
                <p>此页面在移动设备上强制横屏显示,内容区域可自由滚动</p>
            </div>
            
            <div class="card-container">
                <div class="card">
                    <h3>横屏显示优势</h3>
                    <p>横屏模式在移动设备上提供更宽阔的视野,特别适合数据展示、阅读和多媒体内容。在横屏模式下,用户可以同时看到更多信息,减少滚动次数,提升浏览效率。</p>
                </div>
                
                <div class="card">
                    <h3>iOS设备兼容性</h3>
                    <p>本框架专门针对iOS Safari进行了优化,解决了iOS上横屏滚动卡顿、回弹异常等问题。通过CSS属性-webkit-overflow-scrolling:touch确保平滑滚动体验。</p>
                </div>
                
                <div class="card">
                    <h3>自由滚动设计</h3>
                    <p>页面内容在横屏模式下可以自由垂直滚动,不受设备屏幕高度限制。滚动行为经过优化,确保在iOS和Android设备上都有流畅的滚动体验。</p>
                </div>
            </div>
            
            <div class="card-container">
                <div class="card">
                    <h3>框架实现原理</h3>
                    <p>通过CSS transform将整个容器旋转90度,实现横屏效果。使用JavaScript检测设备方向,并在竖屏时显示提示信息。针对iOS Safari的特殊滚动行为进行了专门处理。</p>
                </div>
                
                <div class="card">
                    <h3>响应式设计</h3>
                    <p>即使在横屏模式下,内容布局也会根据实际显示宽度进行响应式调整。在小宽度设备上,卡片会自动调整为单列布局,确保可读性。</p>
                </div>
                
                <div class="card">
                    <h3>使用场景</h3>
                    <p>适用于数据仪表板、电子书阅读器、视频播放界面、游戏界面、横向表格等需要横屏显示的Web应用,提供更佳的用户体验。</p>
                </div>
            </div>
            
            <div class="device-info">
                <h3>设备与方向信息</h3>
                <div class="info-grid">
                    <div class="info-item">
                        <span class="info-label">当前方向:</span>
                        <span id="currentOrientation" class="info-value">横屏</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">设备类型:</span>
                        <span id="deviceType" class="info-value">检测中...</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">屏幕尺寸:</span>
                        <span id="screenSize" class="info-value">检测中...</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">支持触摸:</span>
                        <span id="touchSupport" class="info-value">是</span>
                    </div>
                </div>
            </div>
            
            <!-- 模拟内容,用于展示滚动效果 -->
            <div style="height: 800px; padding: 20px; margin-top: 20px; background-color: white; border-radius: 10px; box-shadow: 0 3px 10px rgba(0,0,0,0.08);">
                <h3>额外内容区域(用于演示滚动)</h3>
                <p>此区域高度为800px,用于展示页面在横屏模式下的自由滚动效果。即使内容超出屏幕高度,用户也可以顺畅地滚动浏览。</p>
                <p>在iOS设备上,滚动行为经过特殊优化,确保不会出现卡顿或异常回弹现象。这是通过CSS属性<code>-webkit-overflow-scrolling: touch</code>实现的。</p>
                <p>向下滚动可以看到更多内容,体验横屏模式下的流畅滚动效果。</p>
                <div style="height: 400px; display: flex; justify-content: center; align-items: center; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; border-radius: 10px; margin-top: 20px;">
                    <h2>滚动到底部了!</h2>
                </div>
            </div>
        </div>
    </div>
    
   <script type="text/javascript" >
    function crossFun(ele) {
    var width = document.documentElement.clientWidth;
    var height = document.documentElement.clientHeight;
    //第一次进来  判断是不是横屏
    if (width < height) {
        ele.style.width = height + 'px';
        ele.style.height = width + 'px';
        ele.style.top = (height - width) / 2 + 'px';
        ele.style.left = 0 - (height - width) / 2 + 'px';
        ele.style.transform = 'rotate(90deg)';
        ele.style.transformOrign = '50% 50%';
        ele.style.position = 'relative';

        document.getElementById('container').classList.add("shu")
        document.getElementById('container').classList.remove("heng")
        document.body.classList.add("shus")
        document.body.classList.remove("hengs")
    }
    else {
        document.getElementById('container').classList.add("heng")
        document.getElementById('container').classList.remove("shu")
        document.body.classList.add("hengs")
        document.body.classList.remove("shus")
    }
    //设备旋转或者窗口变化时候进行  横竖屏处理     在来回切换的时候回出现BUG  使用定时器解决
    var evt = "onorientationchange" in window ? "orientationchange" : "resize";

    window.addEventListener(evt, function () {
        setTimeout(function () {
            var width = document.documentElement.clientWidth;
            var height = document.documentElement.clientHeight;
            if (width > height) {
                ele.style.width = width + 'px';
                ele.style.height = height + 'px';
                ele.style.top = 0;
                ele.style.left = 0;
                ele.style.transform = 'none';
                ele.style.transformOrign = '50% 50%';
                ele.style.position = 'relative';

                document.getElementById('container').classList.add("heng")
                document.getElementById('container').classList.remove("shu")
                document.body.classList.add("hengs")
                document.body.classList.remove("shus")

                //location.reload();
            } else {
                ele.style.width = height + 'px';
                ele.style.height = width + 'px';
                ele.style.top = (height - width) / 2 + 'px';
                ele.style.left = 0 - (height - width) / 2 + 'px';
                ele.style.transform = 'rotate(90deg)';
                ele.style.transformOrign = '50% 50%';
                ele.style.position = 'relative';

                document.getElementById('container').classList.add("shu")
                document.getElementById('container').classList.remove("heng")

                document.body.classList.add("shus")
                document.body.classList.remove("hengs")
                //location.reload();
            }
        }, 100);
    }, false);
}
crossFun(document.getElementById('container')); 
//注意 方法里面用的是原生的方法  传入的DOM应该用原生的方式获取  或者对原方法进行修改即可 
   </script>
</body>
</html>

<script type="text/javascript">
var path = document.getElementById('s4');
var length = path.getTotalLength();
console.log("Path length:", length);
</script>

function getSwiper(itemWrap, groupNum, swiperOpt) {
  if (swiperOpt === void 0) {
    swiperOpt = {};
  }

  var $wrap = $(itemWrap);
  var $items = $wrap.children('.item');

  if (!$items.length) return;

  var swiperId = 'swiper-' + Date.now() + Math.random().toString(36).substr(2, 5);
  var paginationId = swiperId + '-pagination';

  var swiperHtml =
    '<div class="swiper-container ' + swiperId + '">' +
      '<div class="swiper-wrapper"></div>' +
      '<div class="swiper-pagination" id="' + paginationId + '"></div>' +
    '</div>';

  $wrap.after(swiperHtml);

  var $wrapper = $('.' + swiperId + ' .swiper-wrapper');

  for (var i = 0; i < $items.length; i += groupNum) {
    var $slide = $('<div class="swiper-slide"></div>');
    $items.slice(i, i + groupNum).appendTo($slide);
    $wrapper.append($slide);
  }
  var defaultOpt = {
    pagination: { el: '#' + paginationId, clickable: true },
    spaceBetween: 10,
    slidesPerView: 1
  };

  var finalOpt = {};
  for (var key in defaultOpt) {
    finalOpt[key] = defaultOpt[key];
  }
  for (var key in swiperOpt) {
    finalOpt[key] = swiperOpt[key];
  }

  $wrap.remove();

  new Swiper('.' + swiperId, finalOpt);
}
//调用
getSwiper('.slide-p1a', 4, {
      loop: true,
      autoplay: {delay: 6000,stopOnLastSlide: false,disableOnInteraction: false,},
      navigation: { nextEl: ".slide-p1ap .next", prevEl: ".slide-p1ap .prev" },
});
  

 // 封装的Canvas视频播放器函数
        function createCanvasVideoPlayer(container, videoUrl) {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            const video = document.createElement('video');
            video.src = videoUrl;
            video.crossOrigin = 'anonymous';
            video.loop = true;
            video.muted = true; 
            video.playsInline = true;

            function resizeCanvas() {
                canvas.width = container.clientWidth;
                canvas.height = container.clientHeight;
            }
            
            resizeCanvas();
            window.addEventListener('resize', resizeCanvas);
            
            container.appendChild(canvas);
            
            function drawVideoFrame() {
                if (video.paused || video.ended) return;
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                const videoAspectRatio = video.videoWidth / video.videoHeight;
                const canvasAspectRatio = canvas.width / canvas.height;
                
                let renderWidth, renderHeight, offsetX, offsetY;
                if (videoAspectRatio > canvasAspectRatio) {
                    renderHeight = canvas.height;
                    renderWidth = video.videoWidth * (renderHeight / video.videoHeight);
                    offsetX = (canvas.width - renderWidth) / 2;
                    offsetY = 0;
                } else {
                    renderWidth = canvas.width;
                    renderHeight = video.videoHeight * (renderWidth / video.videoWidth);
                    offsetX = 0;
                    offsetY = (canvas.height - renderHeight) / 2;
                }
                
                ctx.drawImage(video, offsetX, offsetY, renderWidth, renderHeight);
                ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                requestAnimationFrame(drawVideoFrame);
            }
            video.addEventListener('loadedmetadata', () => {
                video.play().then(() => {
                    drawVideoFrame();
                }).catch(e => {
                    console.error('自动播放失败:', e);
                    // 如果自动播放失败,用户交互后重新尝试
                    document.addEventListener('click', () => {
                        video.play();
                    }, { once: true });
                });
            });
            
            video.addEventListener('ended', () => {
                video.currentTime = 0;
                video.play();
            });
            return {
                play: function() {
                    video.play();
                    drawVideoFrame();
                },
                pause: function() {
                    video.pause();
                }
            };
        }
        
        // 使用示例
        const videoUrl = 'bg5.mp4';
        const player = createCanvasVideoPlayer(document.getElementById('videoBackground'), videoUrl);
        console.log(player)

1.放入以下函数到conf/FunctionsExt.php
//修正多附件字段
    function fixFile($data){
           if($data){
                $inputStr = $data;
                $segments = explode('||', $inputStr);
                $segments = array_filter($segments, function($item) {
                    return trim($item) !== '';
                });
                //提取标题和顺序
                $pathToTitle = [];  
                $pathOrderMap = [];  
                $order = 1;
                foreach ($segments as $segment) {
                    if (empty(trim($segment))) continue;
                    $parts = explode('|', $segment, 2); 
                    if (count($parts) === 2) {
                        $path = trim($parts[0]);
                        $title = trim($parts[1]);
                        $pathToTitle[$path] = $title;
                        $pathOrderMap[$path] = $order++;
                    }
                }
                
     
                //获取url字符串
                $quotedUrls = [];
                foreach ($segments as $item) {
                    $parts = explode('|', $item, 2); 
                    $url = trim($parts[0] ?? '');
                    if (!empty($url)) {
                        $quotedUrls[] = '"' . $url . '"';
                    }
                }
                
                $orders = 'addtime desc';
                $sql = ' litpic in ('.implode(',',$quotedUrls).') ';
                $fres = M('pictures')->findAll($sql,$orders);
                
                foreach($fres as $k=>$v){
                     $url = $fres[$k]['litpic'];
                     $fres[$k]['title'] = $pathToTitle[$url]; 
                     $fres[$k]['orders'] = $pathOrderMap[$url];
                }
                usort($fres, function($a, $b) {
                    return $a['orders'] - $b['orders'];
                });
               return $fres;
             }else{
                 return [];  
             }   
    }
2.前台HomeController.php在function jizhi_details($id){}中使用
//重构附件files字段

    if(array_key_exists('files',$details)){
        $this->files = fixFile($details['files']);
    }
3.在前台Common控制器添加下载处理函数
    function download() {
        if($_POST){
            $id = $this->frparam('fid',1,'POST');
            $file_name =$this->frparam('file_name',1,'POST');
            if(!$id||!$file_name){
               http_response_code(405);
               //echo "错误:参数缺失";
               exit; 
            }
            if (!preg_match('/^[\w\x{4e00}-\x{9fa5}\-]+$/u', $file_name)) {
            http_response_code(405);
            //echo "错误:文件名包含非法字符";
            exit;
           }
            $fres = M('pictures')->find(['id'=> $id]);
            if($fres){
                $file_url = $fres['litpic'];
                $now =date('Ymd_His', time());
                $download_name = $file_name.$now. '.' . $fres['filetype'];
                if (file_exists(APP_PATH.$file_url) && is_file(APP_PATH.$file_url)) {
                    $fileSize = filesize(APP_PATH.$file_url);
                            header('Content-Description: File Transfer');
                            header('Content-Type: application/octet-stream');
                            header('Content-Disposition: attachment; filename="' . basename($download_name) . '"');
                            header('Expires: 0');
                            header('Cache-Control: must-revalidate');
                            header('Pragma: public');
                            header('Content-Length: ' . $fileSize);
                    readfile(APP_PATH.$file_url);
                    exit;
                }else{
                    http_response_code(404); 
                    //echo "错误:文件不存在。";
                    exit; 
                }
                
            }else{
              http_response_code(404);  
              //echo "错误:文件不存在。";
              exit;    
            }
         
        }else{
          http_response_code(405);  
          exit;
        }
    } 

4.前端详情页模板使用
    {foreach $rjfile as $v}
        <li>
          {$v['id']}
          {$v['title']}
          {$v['filetype']}
          {$v['size']}
          {fun date('Y-m-d',$v['addtime'])}
         <a href="javascript:;" class="downf" fid="{$v['id']}" fname="{$v['title']}">下载</a>
        </li>
    {/foreach}
5.结合js实现文件下载
<script type="text/javascript">
 function download(id,filename){
  $('body').append(`<form method="post" target="_blank" action="/common/download.html" id="downloadForm"><input type="hidden" name="fid" value="${id}" required><input type="hidden"  name="file_name" value="${filename}" required></form>`);
  setTimeout(function(){
    $("#downloadForm").submit();
    setTimeout(function(){
        $("#downloadForm").remove()
        
    },1000)
  },500)
}
$(function(){
    $(".downf").each(function(){
        $(this).click(function(){
            var fid = $(this).attr("fid");
            var fname = $(this).attr("fname");
           download(fid,fname) 
        })
    })
    
})
</script>