我一直在尝试主要使用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) {
因为全局
SlideReady
是undefined
,这是一个falsy值。在false
语句内将伪造的值强制为if
,因此if
块内的代码永远不会运行,并且幻灯片也不会更改。使用诸如jsHint或更严格的jsLint之类的linter可以帮助您避免此类错误。在strict mode中运行所有代码也会使这种错误更加明显。此代码中还有许多其他隐式全局变量(
NextSlide
,CurrentSlide
,Message
)。隐式全局变量可能导致此类错误,甚至可能导致更隐蔽的错误。其他有待改进的地方
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
访问它。实际上,您甚至不需要使用表单和按钮,可以很容易地将div
或span
元素设置为看起来像按钮的样式。使用
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">«</span>
<span class="button" id="next-slide">»</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创建事件处理程序
prevSlide
和nextSlide
。线
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 one,part 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/