Discuz提供的微博功能相对简陋,在微博上除了能写文字外,也就是能用bb代码来加超链接了,连图片也没法贴。我以前讨论过如何扩展微博功能来让用户使用bb代码在上面贴图(链接)。这是个很自然的想法,因为一是超链接在微博里就是用bb代码加的,二是日志后的评论里可以用bb代码来贴图。所以这样的做法是对Discuz内置功能的一个自然延伸。在储存格式上有两种可能,一是储存用户填写的bb代码,然后在显示前转换为html代码。二是在储存前将bb代码转换成html代码,在数据库里存html代码,这样就能直接显示了。两种方法都是可行的而且各有利弊。存bb代码便于用户编辑修改(不过现在微博还没有修改功能),而且bb代码相当简约。上面提到的两个内置的贴超链接和贴图功能存的都是html代码,但内置的日志里贴的视频的功能则采取了存bb代码的做法,也许是因为把它转换成html里的object代码会在储存时多占很大空间。
近来我看到汉山网让用户直接贴图片的地址,然后系统将它转换成图片显示,称之为一键完成又称一键通和一键贴(
链接)。我觉得那样的做法比用bb代码好。一是对用户更方便,不需要记bb代码了。二是储存内容干净,没有bb代码。三是用户修改起来也方便,因为按原样储存没对用户输入做任何转换。当然这种做法也有一定缺陷:
1)它对图片的识别是依据地址结尾处图片文件名的后缀(如.png),所以它没法识别用短地址代表的图片,比如它可以识别
https://www.google.com/images/srpr/logo11w.png
但却没法识别与此等价的短地址
http://tinyurl.com/lubjeod
而用bb代码就没有这局限。
2) 它没法让用户选择图片显示尺寸,而bb代码则不难扩充来支持这个自由度。
3) 用户没有只贴图片地址不要贴图的自由。
但感觉这些都不是大问题。关于1)短地址用的人不多,而且能在浏览器里轻易就能转换成普通地址。关于2),因为各人的微博都显示在一起,所以以网站统一显示尺寸为好。关于3),可以去掉地址最前端的protocol来避免转换。
1。一键贴图
下面我们来考虑下如何实现对这种贴图办法的支持。
新的代码加在了 /source/include/space/space_doing.php 里,在从数据库里取出了微博内容后将图片地址转换成了html里的图片元素,举例而言,将图片地址
https://www.google.com/images/srpr/logo11w.png
转换成了类似于下面的html图片元素
下面两段代码里的最后两句是新加的。第一段是处理微博主贴的内容,第二段是处理微博回复的内容:
$query = C::t('home_doing')->fetch_all_search($start, $perpage, 1, $uids, '', $searchkey, '', '' ,'', 1, $doid, $f_index);
foreach($query as $value) {
if($value['status'] == 0 || $value['uid'] == $_G['uid'] || $_G['adminid'] == 1) {
require_once libfile('function/url2html');
$value['message'] =url2html($value['message']);
foreach(C::t('home_docomment')->fetch_all_by_doid($doids) as $value) {
require_once libfile('function/url2html');
$value['message'] = url2html($value['message']);
具体的转换代码定义在一个新加的文件 /source/function/function_url2html.php 里:
function url2html ($message) {
$message = preg_replace("/(https?:\/\/\S+?.(?:jpe?g|png|gif))/ie", "url2html_img('\\1')", $message);
return $message;
}
function url2html_img($url) {
return "
";
}
上面修改的文件 /source/include/space/space_doing.php 是在显示整个微博页时用的,还有一个文件/source/include/spacecp/spacecp_doing.php 则处理了加了一个回复后对新回复所属的微博主贴包括其下所有回复的显示更新的情形,因此也需要做类似修改:
foreach(C::t('home_docomment')->fetch_all_by_doid($doid) as $value) {
require_once libfile('function/url2html');
$value['message'] = url2html($value['message']);
这种做法的特点是在储存微博时不做任何相关处理,而从数据库提取微博后,则用正则表达式来找出该微博里的所有图片,然后将这些图片地址都替换成能直接显示成图片的html图片元素。
2。一键视频
汉山上的一键贴不光支持贴图,还支持贴音频和多个视频网站的视频。接下来我们讨论一下如何支持贴YouTube视频。常见的YouTube视频地址有多种形式,举例而言:
https://www.youtube.com/embed/MD5bFCDfySc (视频地址)
https://www.youtube.com/v/MD5bFCDfySc (视频地址)
https://www.youtube.com/watch?v=MD5bFCDfySc (视频网页地址)
https://m.youtube.com/watch?v=MD5bFCDfySc (视频网页地址)
https://youtu.be/MD5bFCDfySc (视频网页地址)
有些对应于视频本身,还有些则对应于视频所在的网页。 我们要支持所有这些形式的地址。将前面介绍过的函数 url2html 增补如下:
function url2html ($message) {
$message = preg_replace("/(https?:\/\/\S+?.(?:jpe?g|png|gif))/ie", "url2html_img('\\1')", $message);
$message = preg_replace("/https?:\/\/(?:www.)?youtube.com\/embed\/([a-zA-Z0-9\_\-]+)/ie", "url2html_youtube('\\1')", $message);
$message = preg_replace("/https?:\/\/(?:www.)?youtube.com\/v\/([a-zA-Z0-9\_\-]+)/ie", "url2html_youtube('\\1')", $message);
$message = preg_replace("/https?:\/\/(?:[a-zA-Z0-9\-]+\.)?youtube.com\/watch\?v=([a-zA-Z0-9\_\-]+)/ie", "url2html_youtube('\\1')", $message);
$message = preg_replace("/https?:\/\/youtu.be\/([a-zA-Z0-9\_\-]+)/ie", "url2html_youtube('\\1')", $message);
return $message;
}
function url2html_youtube($vid) {
return "";
}
这种做法将每个微博里的Youtube地址都显示成了一个iframe,网民可以点击后在那里观看。缺点一是如果将视频按Youtube推荐的尺寸560*315来显示的话,它在微博里占地过大,影响阅读其它内容。而如果缩小过多的话,看起来不方便,会不得不再点击全屏播放。 二是这样做微博页上网页越多,网页的负担越大,显示和反应的速度越慢。 每个iframe里的内容都要向YouTube网站发数个请求来获取,即使是不看视频的网友也会受其影响。
3。按需嵌入
Amit Agarwal (
链接)介绍了 Google+ 网站
(
链接)是如何来避免网页速度变慢的。
它们在网页上显示视频的并不是iframe,而只是视频的一张缩影图片。只当用户点击图片后,那张图片才被一个当时生成的iframe所取代。
他还介绍了具体的实现方法。下面的处理借鉴了他的方法。我们将上面提到的 url2html_youtube 函数修改如下:
function url2html_youtube($vid) {
return '';
}
在用户点击了显示的YouTube视频图片后,loadYouTubeVideo函数将它用一个 iframe 来替换,它定义在 /template/default/common/footer.htm 里:
function loadYouTubeVideo(pd, vid) {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "//www.youtube.com/embed/" + vid + "?autoplay=1&border=0&wmode=opaque&enablejsapi=1&controls=1&showinfo=1");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("id", "youtube-iframe");
pd.parentNode.replaceChild(iframe, pd);
} 相关风格的定义如下:
div.youtube-player { display: inline-block; width: 400px; height: 300px; position: relative; vertical-align: top; background-color: Black; margin-bottom: 20px; }
img.youtube-thumb { width: 400px; height: 300px; position: absolute; }
div.play-button { height: 128px; width: 128px; position:absolute; margin-left: 136px; margin-top: 86px; background: url({IMGDIR}/player_play.png) no-repeat; }
#youtube-iframe { width: 100%; height: 100%; position: absolute; }
这种办法对网页的速度会有改善,但还是没解决视频占地和周边微博内容尺寸不匹配的问题。
4。弹窗播放
现在我们来介绍第三种办法。保留第二种办法里显示视频图片的优点,但将它缩小到能和微博里其它内容高度匹配,当用户点击它时将视频在一个新窗口里按YouTube推荐的560*315的尺寸播放。这个窗口可以用我们前文介绍过的Discuz软件提供的弹窗功能(
链接)来实现。
我们先要对前面提到过的函数 url2html_youtube 做个小的改动:
function url2html_youtube($vid) {
return '';
}
重点要改的是函数 loadYouTubeVideo 里的内容:
function loadYouTubeVideo(vid) {
var html = "";
showWindow('youtube', html, 'html', 0);
}
再要修改下前面提到过的有关风格(还缩小一个图):
div.youtube-player { display: inline-block; width: 200px; height: 150px; position: relative; vertical-align: top;margin-bottom: 20px; }
img.youtube-thumb { width: 200px; height: 150px; position: absolute; }
div.play-button { position:absolute; width: 48px; height: 48px; margin-left: 152px; margin-top: 103px; background: url({IMGDIR}/player_play.png) no-repeat; }
本文主要讨论了如何在微博里添加对图片和油管视频的一键贴的支持。这样的做法不难类似的推广到其它形式的视频音频和其它格式的文件如PDF,以及论坛博文文章及其评论里。