javascript - 使用PHP和JavaScript的幻灯片放映

标签 javascript php html arrays slideshow

我一直在尝试主要使用PHP和JavaScript创建幻灯片。但是,由于某些原因,当我单击>><<移至下一张或上一张幻灯片后,没有任何响应。

PHP脚本主要用于从文件夹中抓取图像并将其形成数组。然后,通过echo在此PHP中使用JavaScript,将PHP数组转换为JavaScript数组。

我使用this website作为教程。

谢谢你的帮助!

<?php
//PHP SCRIPT: getimages.php
//Header("content-type: text/javascript");

//This function gets the file names of all images in the current directory
//and ouputs them as a JavaScript array
function returnimages($dirname='C:\Apache\htdocs\Psych211LifespanDevchpt1') {
    echo "in return images";
    $files = array();
    $curimage = 0;

    if ($handles = opendir($dirname)) {
        echo "in handles";
        while (false !== ($file = readdir($handles))) {
            echo "in while";
            $path_info = $_FILES['file']['name'];
            $extensions = pathinfo($path_info, PATHINFO_EXTENSION);
            echo $extensions;
            if ($extensions=='png')
            //if(eregi($pattern, $file)) { //if this file is a valid image
                //Output it as a JavaScript array element
                //$files->append($file);
                $files[$curimage] = $file;
                array_push($files,$file);
                //echo $files[$curimage];
                // 'Slides['.$curimage.']="'.$file .'";';
                //echo $curimage;
                $curimage++;
            //}
        }
        echo $curimage;
        echo count($files);
        closedir($handle);
    }
    echo '<html>
    <head>
    <script type="text/javascript"> 
    var Slides = [];
    Slides = '.json_encode($files).'; document.write(Slides.length);
    function CacheImage(ImageSource) { // TURNS THE STRING INTO AN IMAGE OBJECT
        var ImageObject = new Image();
        ImageObject.src = ImageSource;
        return ImageObject;
    }

    function ShowSlide(Direction) {
       if (SlideReady) {
          NextSlide = CurrentSlide + Direction;
          // THIS WILL DISABLE THE BUTTONS (IE-ONLY)
          document.SlideShow.Previous.disabled = (NextSlide == 0);
          document.SlideShow.Next.disabled = (NextSlide == 
    (Slides.length-1));    
     if ((NextSlide >= 0) && (NextSlide < Slides.length)) {
                document.images["Screen"].src = Slides[NextSlide].src;
                CurrentSlide = NextSlide++;
                Message = "Picture " + (CurrentSlide+1) + "of " + 
    Slides.length;
                self.defaultStatus = Message;
                if (Direction == 1) CacheNextSlide();
          }
          return true;
       }
    }

    function Download() {
       if (Slides[NextSlide].complete) {
          SlideReady = true;
          self.defaultStatus = Message;
       }
       else setTimeout("Download()", 100); // CHECKS DOWNLOAD STATUS EVERY 100 MS
       return true;
    }

    function CacheNextSlide() {
       if ((NextSlide < Slides.length) && (typeof Slides[NextSlide] == 
    "string"))
    { // ONLY CACHES THE IMAGES ONCE
          SlideReady = false;
          self.defaultStatus = "Downloading next picture...";
          Slides[NextSlide] = CacheImage(Slides[NextSlide]);
          Download();
       }
       return true;
    }

    function StartSlideShow() {
       CurrentSlide = -1;
       Slides[0] = CacheImage(Slides[0]);
       var SlideReady = true;
       ShowSlide(1);
    }

    </script>
    </head>
    <body onLoad="StartSlideShow()"> 
<form name="SlideShow"> 
<table> 
<tr> 
<td colspan=2><img src="Psych211LifespanDevchpt1/slide-1.png" name="Screen" width=108 height=135></td>
 </tr>
 <tr> 
<td><input type="button" name="Previous" value=" << " onClick="ShowSlide(-1)"></td> 
<td align="right"><input type="button" name="Next" value=" >> " onClick="ShowSlide(1)"></td> 
</table> 
</form> 
</body> 
</html>';

//return($files);


    }

    //echo 'var Slides=new Array();'; //Define array in JavaScript
    returnimages() //Output the array elements containing the image file names
    ?>

最佳答案

您的大多数函数都使用implicit global变量名SlideReady。在
StartSlideShow您使用var SlideReady = true;尝试进行设置。因为
您以var开头,您正在设置一个局部变量,该局部变量也被命名为
SlideReady,而不是其他函数可以访问的全局变量,因此
全局SlideReady保持为undefined

因此,当StartSlideShow调用ShowSlide时,

if (SlideReady) {


被解释为

if (false) {


因为全局SlideReadyundefined,这是一个falsy值。在false语句内将伪造的值强制为if,因此if块内的代码永远不会运行,并且幻灯片也不会更改。

使用诸如jsHint或更严格的jsLint之类的linter可以帮助您避免此类错误。在strict mode中运行所有代码也会使这种错误更加明显。此代码中还有许多其他隐式全局变量(NextSlideCurrentSlideMessage)。隐式全局变量可能导致此类错误,甚至可能导致更隐蔽的错误。

其他有待改进的地方

window.self不常用。特别是,此代码将其用作裸self而不以window开头的方式可能会引起头痛。许多人需要使用use a variable named self to store a reference to this从另一个函数内部访问外部函数的this对象的情况下closure。使用self引用window.self可能会给任何阅读使用它的代码的人造成混乱。 (对我来说确实如此,自从我看到对window.self的引用以来已经很久了,我忘记了它的存在!)

window.defaultStatus已经过时了很长一段时间,大多数浏览器甚至没有状态栏。没有人会看到在那里张贴的消息。

此代码有很多大写的变量名。它是有效的代码,可以运行,但是在JavaScript中,它已成为仅将constructor functions大写的约定。简而言之,构造函数是需要使用new关键字调用的函数。如果将来有人(包括您在内)使用该代码,则大写的函数名将提醒您需要在其之前使用new关键字。 Linters还使用此约定为您自动发现丢失的new

通过document.formname.elementName访问表单元素和通过document.images访问图像是非常过时的技术。如果表单元素的名称与表单的属性相同,则使用document.formName.elementName也可以cause problems。而是给每个按钮一个id并通过document.getElementById访问它。实际上,您甚至不需要使用表单和按钮,可以很容易地将divspan元素设置为看起来像按钮的样式。

使用onclick是附加事件的过时方法,尤其是将其嵌入HTML的onclick中。使用obtrusive代替addEventListener较少。

For a number of reasons许多编写现代JavaScript的人都喜欢使用function expressions而不是function declaration来定义function。函数声明可能会引起一些令人困惑的错误,而存储在变量中的函数表达式的行为则更具可预测性。

全局变量是有害的,通常会导致各种奇怪的错误,但是代码的不同部分通常需要访问公共变量。通过将代码包装在Immediately-Invoked Function Expression (IIFE)中(有时也称为自调用函数),可以在不创建全局变量的情况下允许这样做。

(function () {
  'use strict';
  var shared = true,
    foo = function () {
      // has access to shared
    },
    bar = function () {
      // also has access to shared
    };
// you can access shared here
}());
// you can't access shared here because it is not a global


我个人认为没有必要或不值得预装图像。大多数人将拥有相当快的连接,并且如果对图像进行了正确的编码,则它们将逐步加载,并且在某些状态下可见,比使用在未完全加载图像之前不会显示图像的代码更快。在用户请求之前加载下一张图像也会浪费他们的带宽,这对于他们在移动设备上可能是很重要的。

如果您认为预加载图像很重要,而不是使用一个过于复杂的系统,直到完全下载下一张图片,否则它不会显示,因此我将在一开始就将它们全部预加载:

Slides.forEach(function (url) {
  (new Image()).src = url;
});


这将下载每个图像并将其存储在浏览器缓存中,而不是像您发布的代码那样将其保存在内存中。

代码现代化

该教程中的JavaScript代码的更新版本可能看起来像这样:

<img id="slide"></td>
<div class="slide-controls">
  <span class="button" id="prev-slide">&laquo;</span>
  <span class="button" id="next-slide">&raquo;</span>
</div>

<script>
  (function () {
    'use strict';
    var slides = [
        'http://www.placecage.com/300/200',
        'http://www.placecage.com/g/300/200',
        'http://www.placecage.com/c/300/200',
        'http://www.placecage.com/gif/300/200'
      ],
      currentSlide = 0,
      doc = document,
      elSlide = doc.getElementById('slide'),
      elPrev = doc.getElementById('prev-slide'),
      elNext = doc.getElementById('next-slide'),

      showSlide = function (index) {
        if (index > -1 && index < slides.length) {
          currentSlide = index;
          elPrev.classList.remove('disabled');
          elNext.classList.remove('disabled');
          if (index === 0) {
            elPrev.classList.add('disabled');
          } else if (index === slides.length - 1) {
            elNext.classList.add('disabled');
          }
          elSlide.src = slides[index];
          elSlide.title = 'Picture ' + (index + 1) + 'of ' + slides.length;
        }
      },
      changeSlide = function (step) {
          var index = currentSlide + step;
          showSlide(index);
      },
      prevSlide = changeSlide.bind(null, -1),
      nextSlide = changeSlide.bind(null, 1);

    elPrev.addEventListener('click', prevSlide, false);
    elNext.addEventListener('click', nextSlide, false);

    showSlide(0);
  }());
</script>


jsFiddle

无需使用docuemnt load event (aka onLoad),这些元素在JavaScript代码上方的标记中定义,并且在JavaScript代码运行时可用。

我将状态消息放在图像的defaultStatus属性中,而不是使用title,如果用户将鼠标悬停在图像上,它将在大多数浏览器中显示为工具提示。如果您希望在没有鼠标悬停的情况下可见消息,也可以将消息输出到另一个<div>

我使用Function.prototype.bind创建事件处理程序prevSlidenextSlide

线

  prevSlide = changeSlide.bind(null, -1),
  nextSlide = changeSlide.bind(null, 1);


实际上等于

  prevSlide = function () {
    changeSlide(-1);
  },
  nextSlide = function () {
    changeSlide(1);
  };


由于我将changeSlide逻辑与图像的实际显示分开,并且showSlide采用索引而不是前进或后退的数量,因此使函数跳转到第一张或最后一张幻灯片也很容易:

  var firstSlide = showSlide.bind(null, 0),
    lastSlide = showSlide.bind(null, slides.length - 1);


jsFiddle

其他资源

以下是与我使用的技术有关的一些资源。


Crockford on JavaScript - Section 8: Programming Style & Your Brain特别适用于我所讨论的某些内容,the whole series值得一看。另外,阅读他的书“ JavaScript:好的部分”可以帮助解释造成这种现象的原因。
JavaScript样式part onepart two的元素
A good description of function declaration vs function expressions
Namespaces, Closures, Self-Invoking Functions, and much, much more...
JavaScript and HTML Script Tags
Named function expressions demystified

关于javascript - 使用PHP和JavaScript的幻灯片放映,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29909392/

相关文章:

javascript - Vue.js 推送和后退按钮

javascript - 与多个状态变量 react 的通用函数

javascript - 如何在继续之前等待 element.all().each() 解决

php - 通过 'for' 循环插入 MySQL 表,并在字符串之间使用变量

javascript - 在 D3.JS 中创建元素 block 的最佳方法是什么

javascript - 创建 d3.js 计时器的问题

javascript - 如何使提交按钮既使用 PHP -> MySQL 发送表单又执行 javascript?

php - 如何限制显示评论的数量

javascript - 纯Javascript super 简单的幻灯片图像数量计数器?

javascript - 阻止元素在达到另一个元素的固定宽度时扩展其宽度