简体   繁体   English

使用PHP和JavaScript的幻灯片放映

[英]Slideshow using PHP and JavaScript

I have been trying to create a slideshow using PHP and JavaScript mainly. 我一直在尝试主要使用PHP和JavaScript创建幻灯片。 However, for some reason there is no response after I click >> or << to move to the next or previous slide. 但是,由于某些原因,当我单击>><<移动到下一张或上一张幻灯片后,没有任何响应。

The PHP script is mainly used to grab images from a folder and form them into an array. PHP脚本主要用于从文件夹中抓取图像并将其形成数组。 Then I use JavaScript within this PHP via echo to transform the PHP-array into a JavaScript-array. 然后,我通过echo在此PHP中使用JavaScript,将PHP数组转换为JavaScript数组。

I used this website as a tutorial. 我使用此网站作为教程。

Thanks for your help! 谢谢你的帮助!

<?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
    ?>

Most of your functions use an implicit global variable name SlideReady . 您的大多数函数都使用隐式全局变量名SlideReady In StartSlideShow you use var SlideReady = true; StartSlideShow您可以使用var SlideReady = true; to try and set it. 尝试设置它。 Because you prefaced it with var you are setting a local variable that is also named SlideReady , not the global variable that other functions have access to, so the global SlideReady remains undefined . 因为您以var开头,所以您正在设置一个也称为SlideReady的局部变量,而不是其他函数可以访问的全局变量,因此全局SlideReady仍未undefined

So when StartSlideShow calls ShowSlide , the line 因此,当StartSlideShow调用ShowSlide

if (SlideReady) {

is interpreted as 被解释为

if (false) {

because the global SlideReady is undefined , which is a falsy value. 因为全局SlideReadyundefined ,所以它是一个伪造的值。 A falsy value is coerced to false inside the if statement, so the code inside of the if block never runs and the slide never changes. 伪造的值在if语句内被强制为false ,因此if块内的代码永远不会运行,并且幻灯片也不会更改。

Using a linter like jsHint or the even stricter jsLint will help you avoid these kinds of errors. 使用像jsHint或更严格的jsLint这样的linter可以帮助您避免此类错误。 Running all your code in strict mode would also have made this kind of error more apparent. 严格模式运行所有代码还会使这种错误更加明显。 There are a number of other implicit globals in this code ( NextSlide , CurrentSlide , Message ). 此代码中还有许多其他隐式全局变量( NextSlideCurrentSlideMessage )。 Implicit globals can cause errors like this or even more insidious ones. 隐式全局变量可能导致此类错误,甚至可能导致更隐蔽的错误。

Other things that could be improved 其他有待改进的地方

window.self isn't commonly used. window.self不常用。 In particular the way this code uses it as a bare self without prefacing it with window could cause headaches. 特别是,此代码将其用作裸露的self而未在window前缀的方式可能会引起麻烦。 Many people use a variable named self to store a reference to this in situations where they need to access a this object of an outer function from inside another function using closure . 许多人在需要使用闭包从另一个函数内部访问外部函数的this对象的情况下, 使用名为self的变量来存储this的引用 Using self to refer to window.self will likely cause confusion for anyone reading code that uses it. 使用self来引用window.self可能会使任何阅读使用window.self代码的人感到困惑。 (It did for me, it has been so long since I have seen a reference to window.self I forgot it existed!) (对我来说确实如此,自从我看到对window.self的引用以来已经很久了,我自己忘记了它的存在!)

window.defaultStatus has been obsolete for a long time, most browsers don't even have a status bar anymore; window.defaultStatus已经过时了很长时间,大多数浏览器甚至都没有状态栏。 no one will see the messages that are being posted there. 没有人会看到在那里张贴的消息。

This code has a lot of variable names that are capitalized. 该代码有很多大写的变量名。 It is valid code and will run, but in JavaScript it has become a convention that only constructor functions be capitalized. 它是有效的代码,可以运行,但是在JavaScript中,它已成为仅将构造函数大写的约定。 In simplest of terms, a constructor function is a function that needs to be called with the new keyword. 用最简单的术语来说,构造函数是需要使用new关键字调用的函数。 If someone in the future (including you) works on the code, the function name being capitalized is a reminder that you need to use the new keyword before it. 如果将来有人(包括您在内)使用该代码,则大写的函数名称将提醒您需要在其之前使用new关键字。 Linters also use this convention to automatically spot missing new s for you. Linters还使用此约定为您自动发现丢失的new

Accessing form elements via document.formname.elementName and images via document.images are very outdated techniques. 通过document.formname.elementName访问表单元素和通过document.images访问图像是非常过时的技术。 Using document.formName.elementName can also cause problems if a form element has the same name as a property of the form. 如果表单元素的名称与表单的属性相同,则使用document.formName.elementName也会引起问题 Instead giving each button an id and accessing it via document.getElementById . 而是给每个按钮一个id并通过document.getElementById对其进行访问。 In fact, you don't even need to use a form and buttons, it is easy to style a div or a span element to look like a button. 实际上,您甚至不需要使用表单和按钮,可以很容易地将divspan元素设置为看起来像按钮的样式。

Using onclick is a dated way of attaching events, especially embedding it in the onclick in your HTML. 使用onclick是附加事件的过时方法,尤其是将其嵌入HTML的onclick中。 It is less obtrusive to use addEventListener instead. 改为使用addEventListener不太麻烦

For a number of reasons many people writing modern JavaScript prefer to use function expressions to define function s instead of function declaration . 由于多种原因,许多编写现代JavaScript的人都喜欢使用函数表达式来定义function而不是函数声明 Function declarations can cause some puzzling bugs, whereas a function expression stored in a variable behaves more predictably. 函数声明可能会引起一些令人费解的错误,而存储在变量中的函数表达式的行为则更具可预测性。

Global variables are bad and can often lead to all sorts of weird bugs, but often different parts of your code need access to common variables. 全局变量很糟糕,通常会导致各种奇怪的错误,但是代码的不同部分常常需要访问公共变量。 You can allow this without creating globals by wrapping your code in an Immediately-Invoked Function Expression (IIFE) (sometimes also called a self-invoking function). 您可以通过将代码包装在立即调用的函数表达式(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

I personally don't feel it is necessary or worth it to preload the images. 我个人认为没有必要或不值得预加载图像。 Most people will have a reasonably fast connection and if the images are encoded properly they will load in progressively and will be viewable in some state much quicker than with this code that won't display the image until it is fully loaded. 大多数人将拥有相当快的连接,并且如果对图像进行了正确的编码,则它们将逐步加载,并且在某些状态下可见,比使用在未完全加载图像之前不会显示图像的代码更快。 Loading the next image before the user requests it also wastes their bandwidth which could be important if they are on mobile. 在用户请求之前加载下一张图像也会浪费其带宽,这对于移动设备而言可能非常重要。

If you think that preloading the images is important, instead of using an overly complex system that won't display the next picture until it is fully downloaded, I would just preload them all at the beginning: 如果您认为预加载图像很重要,而不是使用一个过于复杂的系统,直到完全下载下一张图片,该系统才会显示下一张图片,所以我将在一开始就将它们全部预加载:

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

This will download each image and store it in the browsers cache instead of keeping it in memory in an array like the code you posted does. 这将下载每个图像并将其存储在浏览器缓存中,而不是像您发布的代码那样将其保存在数组中的内存中。

Modernizing the code 代码现代化

A more modern version of the JavaScript code from that tutorial might look more like this: 该教程中的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 的jsfiddle

There is no need to use the docuemnt load event (aka onLoad ) , the elements are defined in the markup above the JavaScript code and will be available when the JavaScript code runs. 无需使用docuemnt load事件(又名onLoad ,这些元素在JavaScript代码上方的标记中定义,并且在JavaScript代码运行时将可用。

Instead of using defaultStatus , I am putting the status message in the title attribute on the image, it should show up as a tool-tip in most browsers if the user mouses-over the image. 我没有使用defaultStatus ,而是将状态消息放在图像的title属性中,如果用户将鼠标悬停在图像上,它应该在大多数浏览器中显示为工具提示。 You could also output the message to another <div> if you want it to be visible without a mouse-over. 如果希望在不将鼠标悬停的情况下可见,也可以将消息输出到另一个<div>

I used Function.prototype.bind to create the event hanlders prevSlide and nextSlide . 我用Function.prototype.bind创建了事件处理程序prevSlidenextSlide

The lines 线

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

are effectively equal to 实际上等于

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

Since I separated the changeSlide logic from the actual display of the image and showSlide takes an index instead of how many forward or back to go, it would be easy to make a function that jumps to the first or the last slide too: 由于我将changeSlide逻辑与图像的实际显示分开,并且showSlide采用索引而不是前进或后退的数量,因此使函数也可以跳转到第一张或最后一张幻灯片很容易:

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

jsFiddle 的jsfiddle

Other resources 其他资源

Here are a few resources related to the techniques I used. 以下是与我使用的技术有关的一些资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM