立即注册 登录
彼岸网 返回首页

天香公主的个人空间 http://www.bian-wang.com/discuz/?10005 [收藏] [复制] [分享] [RSS] txgz999@yahoo.com

日志

Discuz功能改进:给图片幻灯添加划动效果

热度 3已有 601 次阅读2017-7-16 12:09 AM |个人分类:Discuz

图片幻灯是Discuz里一个被广为使用的DIY模块模版,几乎在每个用Discuz软件建造的网站首页都能看到它。支持这个功能的函数还允许模版的显示样式有多个变体,它因此被称为百变幻灯片 (链接) ,比如我们可以通过添加风格类名为 slidebarup 和 slidebardown 的元素给图片幻灯加上显示前一个和后一个幻灯片的控制按钮,又如可以添加自己喜欢的控制按钮列来替代自动生成的数字控制按钮列。但是从功能上讲它也不无缺陷,如在电脑上我们可以将鼠标放在图片幻灯的数字控制按钮上来选择幻灯片的显示,但在iPad和手机上就没有这个便利了。和新浪体育首页(链接)上的类似功能比较会发现,新浪的图片幻灯(见下图)在iPad上可以通过手指划动来选择幻灯片,而Discuz的幻灯片手指划上去纹丝不动。本文讨论下如何让它也听从手指的指挥。


图片幻灯的功能是由文件static/js/common_extra.js里的slideshow函数来实现的。一种修改的思路是利用滚动条,参考了Chris Coyier的文章 Slider with Sliding Backgrounds (链接)。


Discuz的做法是通过改变各个幻灯片的隐藏属性来决定显示哪个或哪些幻灯片。这种做法无法支持划动。Chris Coyier介绍的办法是让所有图片都处在显示状态,只是用一个窗口将展示的部分局限于此,所以才可能用手指划动来选择幻灯片了。具体而言,图片幻灯是由下面多层结构组成的:
1)幻灯片:最里层是一张张幻灯片。它们具有float=left的特性。由于包含它们的容器足够宽,它们可以从左向右排成一行。
2)幻灯片容器:幻灯片的容器的宽度是所有幻灯片宽度的总和。
3)滚动容器:幻灯片容器的外面是个带滚动条的容器,它和幻灯可视区域一样宽,具有overflow-x=scroll的特性。因为它包含的幻灯片容器比它宽,所以它会带有横向的滚动条。它比幻灯可视区域略高,使得它的滚动条被隐藏于可视区域外。
4)显示窗口:最外层是一个显示窗口,它是幻灯的可视区域,具有overflow=hidden的特性,所以它包含的元素在它范围外的部分都被隐藏。
这里要注意的是我们遵循原来模版结构定义,不需要用户来添加额外的层次。所需的层次会在程序运行是按需自动加入。

还有几点值得一提:
1)在电脑上我们是通过处理mousedown,scroll,和mouseup事件在滚动停止后来选择显示的图片的,而在iPad上类似的事件则是touchstart, touchmove, 和 touchend。
2)具有overflow-x=scroll的特性的滚动容器使得在iPad上可以通过划动来调节显示它的内容。如果不添加滚动容器,而是让具有overflow=hidden的特性的显示窗口直接包含图片容器,那样的话在iPad上就无法划动。
3)划动结束时幻灯片容器位置的选择:由于滚动容器带着滚动条,所以它自动就支持在iPad里用手指划动来调节幻灯片容器的显示位置。但是一般情况下,划完后显示窗口显示的是不完整的幻灯片,如相邻的两张幻灯片各显示半张。这时就要选择是显示前一张还是后一张,用的逻辑是看划动方向。向左划动的话就显示前一张,向右划动的话就显示后一张。
4)在幻灯片容器里的幻灯片系列的两端添加了若干张复制的幻灯片,这样在用户结束划动决定滚动条位置时,可以适当选择来避免显示两端的幻灯片。这使得用户可以一直向一个方向划动,而幻灯片的显示则周而复始,不会因到达第一张幻灯片而无法向左划或到达最后一张而无法向右划。添加的复制幻灯片的数量取决于显示窗口同时显示的幻灯片数量。如果显示窗口只显示一张,那里我们只需在幻灯片系列前添加最后一张幻灯片的复制,并在幻灯片系列后添加第一张幻灯片的复制。上面的示意图显示的就是这种情形。如果显示窗口是同时显示两张幻灯片的话,我们就需要复制添加五张幻灯片。如下图所示。当用户划动结束后,我们要在显示窗口里左面一张在图中绿框里。比如如果划动结束显示的是图中第二个咖啡色框里的两张幻灯片,我们就要向左平移三格(注意这个例子里有三张原始的幻灯片)代之以显示图中第二个咖啡色框里的两张幻灯片。这个做法的目的是在用户不察觉的前提下保证在显示的两张幻灯片的两侧都至少还有两张幻灯片,这就使得用户下一次划动不会有超出幻灯片容器的边缘的需要。



还有一种修改的办法是利用CSS风格里的平移变换,参考Kevin Foley的文章 The JavaScript Behind Touch-Friendly Sliders (链接)。用这种办法的话就不需要添加滚动容器了。只要将幻灯片容器适当的平移,就能使得显示窗口里的内容不断变动。和第一种办法不同的是,在第一种办法里,滚动容器里的内容随手指划动而移位是滚动条的作用,不需要写代码来实现。而在第二种办法里,我们需要处理touchmove事件,在其中平移幻灯片容器。那么能不能不用平移变换,而直接设置和不断变化幻灯片容器位置呢?理论上可行,但效果很差,见 Paul Irish 的讨论 Why Moving Elements With Translate() Is Better Than Pos:abs Top/left (链接)。另外虽然我们在使用平移变换时做的只是简单的横向移动,但用的是三维平移函数而不是二维平移函数,其原因是只有前者才会启动硬件加速,让划动的效果更好。参见 Guil Hernandez 的讨论 (链接)。

下面是个示范幻灯。在电脑上看和彼岸网首页右下方的日志图片幻灯几无差别,但在iPad上就会发现它可以用手指划动:

Discuz 提供的图片幻灯基于滚动条的图片幻灯利用平移变换的图片幻灯
  • 他用8列火车从纳粹手下救出了669个孩子, 几
  • 风筝情
  • 写给女人的诗__ 《天下女人》 作者: 银莲
  • 在此刻~~~春晚歌曲分享
  • 朋友圈里最温暖的照片! (音乐自动)
  • 南山南
  • 在云海中看日出————飞机上看到的一幕
  • Love Never Dies 《真爱不死》
  • 灵魂伴侣, 如果相遇, 请好好珍惜
  • 我愿在这样的小镇, 遇见最美的时光
  • 红粉秋千 ~~~ 作者: 法道济


<div class="module cl slidebox"> <ul class="slideshow"> [loop] <li style="width: {picwidth}px; height: {picheight}px;"><a href="{url}"{target}><img src="{pic}" width="{picwidth}" height="{picheight}" /></a><span class="title">{title}</span></li> [/loop] </ul> </div> <script type="text/javascript"> runslideshow(); </script>
  • 他用8列火车从纳粹手下救出了669个孩子, 几
  • 风筝情
  • 写给女人的诗__ 《天下女人》 作者: 银莲
  • 在此刻~~~春晚歌曲分享
  • 朋友圈里最温暖的照片! (音乐自动)
  • 南山南
  • 在云海中看日出————飞机上看到的一幕
  • Love Never Dies 《真爱不死》
  • 灵魂伴侣, 如果相遇, 请好好珍惜
  • 我愿在这样的小镇, 遇见最美的时光
  • 红粉秋千 ~~~ 作者: 法道济


<div class="module cl slidebox" slidenum="3" slidestep="1"> <div class="slidebarup" style="float: left; width: 20px; height: 80px;"><input type="button" style="background: url(static/image/common/arw_l.gif) no-repeat; margin-top: 30px;" ></input></div> <div style="float: left; width: 240px; height: 80px; "> <ul class="slideshow"> [loop] <li style="width: {picwidth}px; height: {picheight}px; float: left;"><a href="{url}"{target}><img src="{pic}" width="{picwidth}" height="{picheight}" /></a><span class="title">{title}</span></li> [/loop] </ul> </div> <div class="slidebardown" style="float: left; width: 20px; height: 80px;"><input type="button" style="background: url(static/image/common/arw_r.gif) no-repeat; margin-top: 30px;" ></input></div> </div> <script type="text/javascript"> runslideshow(); </script>


文件下载: http://www.bian-wang.com/discuz/data/userupload/10005/slideshow.zip

附录:(原有的)幻灯模版定义的一些规则:
  1. 模版里必须包含一个slidebox作为幻灯容器,即它包含其它与幻灯有关的元素。
  2. slidebox里一般会定义一个slideshow的元素作为所有幻灯片的容器。它的每个子元素代表了一张幻灯片。如果slideshow不存在的话,那么slidebox的每个子元素被视为一张幻灯片。
  3. 可以给slidebox添加slidenum和slidestep的属性。在没有这两个设置时,每次显示一张幻灯片。定期会自动用下一张幻灯片更换。直到显示最后一张后,再重新开始显示第一张。如果设置了这两个值。则slidenum代表同时显示的幻灯片数量,slidestep代表每次更换幻灯片的数量。在开始时显示的是前slidenum张幻灯片,但不会定期自动更换。这两个属性不能只设其一,那样的话幻灯片不显示。
  4. 可以给slidebox添加timestep的属性。如果幻灯片在定期自动更换的话,它是以毫秒为单位的更换频率。缺省值是2500,即每过2.5秒更换一次。
  5. 当鼠标进入显示的幻灯片内部后,定期更换停止。等鼠标离开后,定期更新接着进行,即便之前不定期自动更换。这意味着设有slidenum和slidestep的幻灯只要鼠标进入并离开图片区域后就会开始定期自动更换。
  6. 还可以给slidebox添加一个mevent的属性,它的值可以为click和mouseover。它决定了用控制按钮更换幻灯片所依据的事件。
  7. 当slidebox没有slidenum和slidestep属性时,可以在模版定义里在slidebox内添加一个slidebar,其中每个元素只要不是slidebarup和slidebardown的话,就起到了一个数字控制按钮的作用。如果没有定义一个slidebar的话,会自动添加一个slidebar,其中包括了和幻灯片数量相同的数字控制按钮。数字控制按钮当有mevent定义的事件(缺省时是mouseover事件)发生时更换幻灯片。新幻灯片的选择由该控制按钮在slidebar里的位置决定。
  8. 可以在slidebox内添加一个slidebarup做为前一个/上一个的控制按钮。当有mevent定义的事件(缺省时是click事件)发生时,会更换成下一张幻灯片,或是更换slidestep张幻灯片如果slidestep设置的话。类似的还可以定义一个slidebardown做为后一个/下一个的控制按钮。这两个按钮可以定义在slidebar内或外面,互不影响。
  9. 可以在slidebox里定义一个或多个slideother。每个slideother里应有和幻灯片数量相同的子元素,按位置与幻灯片一一对应。在对应的幻灯片显示时它们同时显示。

发表评论 评论 (25 个评论)

回复 牛肉炖土豆 2017-9-17 01:02 AM
天香公主: 是说第二种办法,这可以理解,因为transition是个比较新的风格设置,旧的浏览器不支持,详见 https://stackoverflow.com/questions/5103283/does-internet-explo ...
好的,知道了,IE6在国外应该基本没人用了,~
回复 天香公主 2017-9-16 10:34 PM
牛肉炖土豆: slideshow_transform_withshifteffect.txt
我发现了一个小BUG,就是在IE6下,图片横向撑开
是说第二种办法,这可以理解,因为transition是个比较新的风格设置,旧的浏览器不支持,详见 https://stackoverflow.com/questions/5103283/does-internet-explorer-support-css-transitions

我没ie6没法试,估计略作修改的话,可以让它在ie6里不撑开,但肯定不能在那里实现这功能。
回复 牛肉炖土豆 2017-9-14 01:22 AM
slideshow_transform_withshifteffect.txt
我发现了一个小BUG,就是在IE6下,图片横向撑开
回复 loveyou520tw 2017-8-30 01:56 AM
老師您好~我想問一下關於overflow: hidden; width: 750px; height: 150px;該如何修正?height?因為我是運用於Discuz分類訊息。結果分類訊息中的部分訊息都被遮住了
除非將這段<div style=&quot;overflow: hidden; width: 750px; height: 150px;&quot;> 修改成height: 200px才可以出現分類訊息訊息。

--- 更新 ----
看出所以然了,看來是因為對應圖片大小的關係。
回复 天香公主 2017-8-1 11:36 PM
牛肉炖土豆: 我觉得无论是效果,还是兼容性徕看,基于滚动条的图片幻灯比较适合用在项目中,它即支持PC,又支持手指滑动,而且目前还没发现BUG,几近完美了, ...
嗯。我前面说的用平移变换法时偶尔网页会移动的问题解决了,在touchmove事件处理里加了句 preventDefault。现在我是观察不出两种办法的效果的差别了,虽然据说平移变化效果应该好一些因为开启了硬件加速。
回复 牛肉炖土豆 2017-8-1 08:56 PM
天香公主: 谢谢。我在文中示范和下载文件里加了另一种做法,是利用风格里的平移变化。用手指划动的效果没明显区别。但用新办法划动时好像页面有时有点移动。 ...
我觉得无论是效果,还是兼容性徕看,基于滚动条的图片幻灯比较适合用在项目中,它即支持PC,又支持手指滑动,而且目前还没发现BUG,几近完美了,
回复 天香公主 2017-7-31 12:57 AM
牛肉炖土豆: 横排,我把我的CSS发给你消息了
谢谢。我在文中示范和下载文件里加了另一种做法,是利用风格里的平移变化。用手指划动的效果没明显区别。但用新办法划动时好像页面有时有点移动。
回复 牛肉炖土豆 2017-7-27 09:53 PM
天香公主: 请教一下,你用这个模板造出来的幻灯里三个图片是横排的还是竖排的,如果是横排的,给li加了什么风格?

我又看了看原来的幻灯(slidenum=&quot;3&quot;且slides ...
横排,我把我的CSS发给你消息了
回复 天香公主 2017-7-26 07:37 AM
原来的幻灯图案变化周期:
1)5张图,slidenum=2,slidestep=1
12 23 34 45 15, 而自然的规则我觉得应是 12 23 34 45 51
2)5张图,slidenum=5,slidestep=1
123 234 345 145 125,而自然的规律我觉得应是 123 234 345 451 512
总的来讲,显示的数字组合和我料想的相同,但组合里的位置永远是从小到大。其根源在于Discuz用的办法无法变动图案的前后位置,如无法将2显示在1之前
回复 天香公主 2017-7-25 11:39 PM
牛肉炖土豆: <div class=&quot;module cl slidebox&quot; slidenum=&quot;3&quot; slidestep=&quot;1&quot;>
<ul class=&quot;slideshow&quot;>
[loop]
<li style=&quot;widt ...
请教一下,你用这个模板造出来的幻灯里三个图片是横排的还是竖排的,如果是横排的,给li加了什么风格?

我又看了看原来的幻灯(slidenum="3"且slidestep="1"),觉得图案的变动有问题,还是我没看出规律?
回复 牛肉炖土豆 2017-7-23 04:04 AM
天香公主: 我更新了下载文件,现在应该支持有slidenum和slidestep的情形了,我在文末也加了个示范。

同意你说的应该让这样的幻灯一开始就动起来为好,这样做的好处之一是 ...
完美!这种幻灯片实用性非常强,超喜欢。点赞!
回复 天香公主 2017-7-22 10:34 PM
牛肉炖土豆: 我又测试一下改动后的,

1.一定要点击动作或滑动动作,它才能自动移动,如果不用点击自动移动,就完美了!
2.点击左右按钮,首次点击一次移动三张图片,第2次开 ...
我更新了下载文件,现在应该支持有slidenum和slidestep的情形了,我在文末也加了个示范。

同意你说的应该让这样的幻灯一开始就动起来为好,这样做的好处之一是可以选择不加上下按钮。不过为了和原来的行为匹配,我没这么做。如果你要改成这样的话,把代码最后部分有一句
    if (!this.slidenum || !this.slidestep) this.goon();
改成
    this.goon();
即可。
回复 天香公主 2017-7-22 10:17 AM
牛肉炖土豆: 我又测试了一下,没改动前也要点击才能自动移动。。。奇怪了
我新装了一个Discuz来观察原来的幻灯行为。的确,有slidenum和slidestep的幻灯虽然开始时不动,但一旦让鼠标进入幻灯片再离开后就动起来了。还有这两个设置如果有就得同时存在,只设一个的话幻灯不显示。我把观察到的行为补充在文后了。请看看是否与你的观察相符。

另外确认了我新加的支持更换效应的代码造成了有slidestep的幻灯片更换发生问题,还有点击上下控制按钮就让幻灯开始自动动起来了也是不对的,我稍后会更正。
回复 天香公主 2017-7-21 06:47 AM
牛肉炖土豆: 我又测试了一下,没改动前也要点击才能自动移动。。。奇怪了
谢谢,我等晚上试了再说。我对原来幻灯片各种设置的效果不熟,也许无意中破坏了原有的代码。总的来讲,在添加了触摸划动和图片切换效果后,应保持原有功能不变。
回复 牛肉炖土豆 2017-7-20 10:38 PM
我又测试一下改动后的,

1.一定要点击动作或滑动动作,它才能自动移动,如果不用点击自动移动,就完美了!
2.点击左右按钮,首次点击一次移动三张图片,第2次开始一个一个移动
回复 牛肉炖土豆 2017-7-20 10:08 PM
天香公主: 我不是要你改,我要测试有问题的那个模块模版。所以你的模块模版里只有slidenum没有slidestep? 能把模块模版的内容给我试试吗? ...
我又测试了一下,没改动前也要点击才能自动移动。。。奇怪了
回复 牛肉炖土豆 2017-7-20 10:05 PM
天香公主: 我不是要你改,我要测试有问题的那个模块模版。所以你的模块模版里只有slidenum没有slidestep? 能把模块模版的内容给我试试吗? ...
对了,要加上这个左右点击的按钮

        <div class="btn_arr">
          <div class="leftbtn slidebarup">
            <a href="javascript:void(0);" class="btn_prev" mevent="click">
              <span class="sp"></span></a>
          </div>
          <div class="slidebardown">
            <a href="javascript:void(0);" class="btn_next" mevent="click">
              <span class="sp"></span></a>
          </div>
        </div>
回复 牛肉炖土豆 2017-7-20 10:03 PM
天香公主: 我不是要你改,我要测试有问题的那个模块模版。所以你的模块模版里只有slidenum没有slidestep? 能把模块模版的内容给我试试吗? ...
<div class="module cl slidebox" slidenum="3" slidestep="1">
<ul class="slideshow">
[loop]
<li style="width: {auto;}px; height: {picheight}px;"><a href="{url}"{target}><img src="{pic}" width="{picwidth}" height="{picheight}" /></a><span class="title">{title}</span></li>
[/loop]
</ul>
</div>
<script type="text/javascript">
runslideshow();
</script>
回复 天香公主 2017-7-20 10:00 PM
牛肉炖土豆: 1.我的幻灯片里没了slidenum,slidestep我没有试过,稍后试一下
2.没有改动前,不用点击,自动移动的,单是效果比较奇怪,就是slidenum时移动几个之后,然后一闪 ...
我不是要你改,我要测试有问题的那个模块模版。所以你的模块模版里只有slidenum没有slidestep? 能把模块模版的内容给我试试吗?
回复 牛肉炖土豆 2017-7-20 09:55 PM
天香公主: 改正了一个小错误,请再试试。如果仍有你说的问题,请问
1)你的幻灯里是光设有slidenum,还是还设了slidestep?
2)在没用我的改动之前,你的幻灯是每过2秒半会 ...
1.我的幻灯片里没了slidenum,slidestep我没有试过,稍后试一下
2.没有改动前,要点击,自动移动,单是效果比较奇怪,就是slidenum时移动几个之后,然后一闪一闪的原地更换,然后又移动,如此反复


3.这次改动之后,
移动端:要手动滑动之后才开始自动移动
PC端:不自动移动,要鼠标点击一个,才变成自动
12下一页

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2017-9-25 07:42 AM , Processed in 0.076809 second(s), 21 queries.

返回顶部