目录
该符号
将读取器返回到目录的顶部。
1. 简介
我最近决定为一个组织修改即将举行的活动轮播。轮播显示在两个位置:
- 作为在电视显示器上显示的一系列幻灯片,在组织的休息室,由树莓派4每张幻灯片显示10秒钟。显示完所有幻灯片后,幻灯片放映将重复播放。
- 作为组织网站上的轮播。网站轮播是休息室幻灯片的副本,其控件允许暂停幻灯片放映、更改幻灯片显示时间和反转显示方向。
实现网站轮播的决定是因为某些幻灯片具有相当大的内容,在分配的10秒内不容易阅读。由于幻灯片已经放置在网站上以下载到Raspberry Pi 4,因此决定构建一个轮播以在网站上显示幻灯片是一项容易完成的任务——至少我是这么认为的。
实现轮播的方法似乎与使用轮播的网站一样多。本文介绍了另一个可能对某些读者有用的方法。它还描述了在实现过程中发生的一些设计决策和一些回溯。
2. 要求
对网站轮播的要求是:
- 能够显示至少30张幻灯片(此实现最多显示32张幻灯片)。
- 从网站上的目录中获取幻灯片。
- 允许用户控制滑动移动的方向(即向右或向左)。
- 允许用户暂停并重新启动显示器移动。
- 允许用户显示特定幻灯片。
- 允许用户修改每张幻灯片的显示时间。
3. 设计
旋转木马的原始设计使用了< input type="range"...> HTML元素。但是,出现了几个问题:
- 将刻度线与范围滑块的位置对齐的尝试充其量是“接近”而不是“精确”。无法预测范围滑块从一个步骤移动到下一个步骤时停止的位置。
- 浏览器实现者在如何解释W3c草稿方面存在显着差异<input type=“range”...>[^] HTML元素。这意味着需要大量的CSS[^]才能使元素在浏览器中看起来一致。
这些问题导致了第二个设计,其中<input type=“range”...> HTML元素被一组可选的刻度线所取代,如下面的设计图所示。
除了carousel_container <div>之外,有三个主要的<div>。
- left_slide_right <div>显示左移动控件、幻灯片和右侧移动控件。每个组件都包含在自己的<div>中。箭头指向单击时滑动移动的方向。
- pause_continue_dots <div>包含暂停/继续控件和表示将显示的幻灯片数量的小圆圈(在本例中为20张幻灯片)。暂停/继续控件和未填充/填充圆圈组件都包含在自己的<div>中。实心圆圈表示当前正在显示的幻灯片。通过单击未填充的点,将显示该点所代表的幻灯片。在此图中,幻灯片移动暂停,继续箭头显示在点的左侧。单击继续箭头时,移动将再次开始,继续箭头将替换为暂停指示器(如图所示,carousel_container <div>左侧)。
- ticks_and_delay <div>包含用户可以更改分配给幻灯片显示的时间量的方法。它包含可选择的刻度线,允许用户单击刻度线以设置所需的延迟。
4. 实现
本文中描述的实现使用HTML、CSS、vanilla JavaScript和SVG。未使用第三方软件。
4.1.HTML
left_slide_right <div>,pause_continue_dots <div>和ticks_and_delay <div>定义弹性框。我可以向我的读者保证,朴素的<div>(不使用flex)或<table>不是解决方案(他们被尝试过!)
4.2.CSS
弹性框在CSS中定义。
.carousel_container,
.left_slide_right_container {
display:flex;
justify-content:center;
align-items:flex-start;
}
.left_slide_right {
height:300px;
display:flex;
justify-content:center;
align-items:center;
}
.pause_continue_dots_container,
.time_ticks_div,
.ticks {
display:flex;
justify-content:center;
align-items:center;
}
#pause_continue_button,
#dots {
display:flex;
justify-content:center;
}
前面的CSS在carousel.html文档的样式元素中显示为内部CSS。内部CSS中提供的CSS特定于此轮播实现。
虽然轮播的部分CSS出现在内部CSS中,但也使用了内联CSS。这种形式的CSS通常设置宽度和高度的值,因为这种样式仅适用于特定的HTML元素。
在carousel.js 中找到的JavaScript中生成了额外的CSS。
有趣的是,点只能通过CSS定义。特定点是填充还是未填充由JavaScript函数set_active_dot决定。
这些点与其左邻点相隔2个像素;控件与点<div>隔5个像素。这些值是通过实验来选择的,以找到可接受的平衡。
4.3. Javascript
到目前为止,最复杂的代码段是项目的Javascript模块,包含在carousel.js中,其“命名空间”是“Carousel”。
JavaScript的执行由JSON对象控制。
<script>
var CAROUSEL_COMPONENTS =
{
"slides_directory":"./Slides30",
"timer_default_value":2,
"timer_minimum":1,
"timer_maximum":20,
"timer_step":1,
"chosen":"Red",
"hover":"DodgerBlue",
"normal":"LightSkyBlue",
"debug_json":false
}; // CAROUSEL_COMPONENTS
</script>
此JSON对象应在carousel.html的<head>中定义。
要显示的幻灯片应位于CAROUSEL_COMPONENTS.slides_directory中命名的单个目录中。幻灯片本身使用表单命名
Slide1.png,Slide2.png, ....
目录中的幻灯片列表使用XMLHttpRequest恢复。返回的列表包含的信息不仅仅是幻灯片的名称。XMLHttp.responseText中的每一行都以'\n'结尾,因此可以通过按该字符拆分XMLHttp.responseText来创建文件列表。要提取实际的幻灯片列表,必须考虑执行环境。这是通过以下方法完成的。
// The strings returned in the
// XMLHttp.responseText differ
// between the localhost
// environment (used in test
// and debug) and the
// production environment
var LOCAL_DOMAINS = [ "localhost", "127.0.0.1" ];
var IS_LOCALHOST =
LOCAL_DOMAINS.includes ( window.location.hostname );
JavaScript函数extract_slides_from_file_list负责生成幻灯片列表。
此实现中可以显示的幻灯片数量有限制(受幻灯片图像下方可以容纳的填充/空点数的限制)。
// maximum number of slides:
// width of carousel 400 px
// width of a dot 10 px
// dot right margin 2 px
// total dot width 12 px
// width of control 10 px
// control right margin 5 px
// total control width 15 px
// ( 400 - 15 ) / 12 = 32.08
// ≈ 32
// MORE THAN 32 SLIDES WILL BE
// TRUNCATED TO 32 WITHOUT
// WARNING UNLESS THE DISPLAY
// IS ON LOCALHOST WHEN A
// WARNING WILL BE GIVEN
var MAXIMUM_SLIDES_ALLOWED = 32;
此实现中可以显示的刻度线数量也有限制(受刻度线数量和carousel_container中可以容纳的图例的限制)。
// maximum number of ticks
// width of carousel
// container 450 px
// width of tick mark 5 px
// tick right margin 5 px
// total tick width 10 px
// width of "delay" 50 px
// width of "seconds" 50 px
// total legend width 100 px
// ( 450 - 100 ) / 10 = 35
// MORE THAN 35 TICKS WILL BE
// TRUNCATED TO 35 WITHOUT
// WARNING UNLESS THE DISPLAY
// IS ON LOCALHOST WHEN A
// WARNING WILL BE GIVEN
var MAXIMUM_TICK_MARKS_ALLOWED = 35;
由于JavaScript和HTML之间的交互非常重要,因此需要实例化大量文档ID。
// document ids
var carousel = document.getElementById ( "carousel" );
var dots = document.getElementById ( "dots" );
var left_side_BUT = document.getElementById ( "left_side_BUT" );
var pause_continue_button = document.getElementById (
"pause_continue_button" );
var right_side_BUT = document.getElementById ( "right_side_BUT" );
var right_text = document.getElementById ( "right_text" );
var temporary_dot = document.getElementById ( "temporary_dot" );
var ticks = document.getElementById ( "ticks" );
Javascript为所有轮播事件提供事件处理程序,包括:
dot_clicked
move_left
move_right
pause_continue_clicked
tick_clicked
tick_mouseout
tick_mouseover
有五个状态变量:
// state variables
var current_active_dot = 0;
var current_seconds = 0;
var current_tick_mark_border_color;
var moving_leftward = true;
var paused = false;
这些变量可以保存/恢复关键执行状态,也可以控制GUI显示其内容的方式。
4.4. 可缩放矢量图形(SVG)
例如,暂停和继续图像是在JavaScript函数assign_pause_or_continue_image中使用SVG生成的。
// ******************************** assign_pause_or_continue_image
// local entry point
function assign_pause_or_continue_image ( )
{
pause_continue.innerHTML = "";
if ( paused )
{
pause_continue.innerHTML =
"<svg class='continue_icon'" +
" width='10' " +
" height='10'" +
" viewBox='0 0 10 10'" +
" overflow='visible'>" +
" <path d='M 0 0 L 10 5 L 0 10 L 0 0' " +
" fill='" + COMPONENTS.normal + "'" +
" stroke='" + COMPONENTS.normal + "'/>" +
"</svg>";
}
else
{
pause_continue.innerHTML =
"<svg class='pause_icon' " +
" width='10'" +
" height='10'" +
" viewBox='0 0 10 10'>" +
" <path d='M 0 0 h 4 v 10 h -4 v -10 m 6 0 h 4 v 10 h -4 v -10'" +
" fill='" + COMPONENTS.normal + "'" +
" stroke='" + COMPONENTS.normal + "'/>" +
"</svg>";
}
} // assign_pause_or_continue_image
此代码使用暂停的状态变量来确定要绘制的图形。图形轮廓是使用路径创建的。在continue_icon中,“M”将笔移动到绝对位置,“L”绘制一条从当前位置到绝对位置的线。然后关闭该路径。在pause_icon中,“m”将笔从其当前位置移动到相对位置,“h”绘制一条水平线,“v”绘制指定长度的垂直线。因为它们是动态的,所以这两个数字是用JavaScript绘制的。向左和向右移动的箭头是使用HTML中嵌入的SVG绘制的。
<div class="left_slide_right"
style="width:25px;" >
<button id="left_side_BUT"
style="background:transparent;">
<svg version="1.1"
width="20"
height="23"
xmlns="http://www.w3.org/2000/svg">
<polygon id="left_pointing_arrow"
points="0,11 20,0 20,23"
fill="CornflowerBlue"
stroke="CornflowerBlue"/>
</svg>
</button>
</div>
⋮
<!-- right_side -->
<div class="left_slide_right"
style="width:25px;
margin-left:1px;" >
<button id="right_side_BUT"
style="background:transparent;
float:left;
vertical-align:middle;">
<svg version="1.1"
width="20"
height="23"
xmlns="http://www.w3.org/2000/svg">
<polygon id="right_pointing_arrow"
points="0,0 20,11 0,23"
fill="CornflowerBlue"
stroke="CornflowerBlue"/>
</svg>
</button>
</div>
图形轮廓是使用定义为一系列点的多边形创建的。SVG多边形将自行闭合。
5. 下载
carousel.zip文件在以下目录中包含以下文件(目录以粗体显示))
Carousel_Project
carousel.html Project HTML
carousel.js Project JavaScript
favicon.ico Project Icon
Slides30 Slide directory derived from Slides30.ppt
Slide1.png
⋮
Slide30.png
Carousel_Sources
BW_Slides30.ppt
Initial_Design.ppt
Miscellaneous.ppt
Slides20.ppt
Slides30.ppt
Slides40.ppt
Carousel_Paper
Carousel.html This article
carousel.png
Carousel.TOC.html This article with a TOC
Chrome.png
Edge.png
Firefox.png
Firefox_Developer.png
four_svgs.PNG
Internet_Explorer.png
Opera.png
overview.png
pause_continue_dots.png
range_vs_div.png
ReturnToTOC.png
Safari.png
对于打算下载ZIP文件的读者,我建议如下:
- 创建目录轮播。
- 将ZIP文件下载到轮播中。
- 将ZIP文件的内容解压缩到目录轮播中。请注意,某些ZIP文件提取程序希望将内容提取到轮播下新创建的目录中。
- 使用您喜欢的浏览器,打开Carousel_Project/carousel.html。
如有任何建议、意见或批评,请告知我。它们都同样受到欢迎。
6. 参考资料
7. 结论
本文介绍了不需要第三方软件的轻量级动态轮播的实现。
8. 开发环境
旋转木马项目是在以下环境中开发的:
微软Windows 7专业版SP 1 |
Microsoft Visual Studio 2008 Professional SP1 |
微软Windows C# 2008 |
Microsoft .Net Framework 版本 3.5 SP1 |
9. 支持的浏览器
下面描述了支持此轮播实现的浏览器。
| | | | | | |
Chrome | Edge | Firefox | Firefox | Internet | Opera | Safari |
Internet Explorer和Safari都没有针对Windows 7的修订版。
https://www.codeproject.com/Articles/5336578/Lightweight-Carousel-Using-only-HTML-CSS-JavaScrip