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

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

日志

从代码修改到插件开发:头像编辑

热度 8已有 2736 次阅读2016-4-16 08:37 PM |个人分类:Discuz

从修改系统代码到开发插件:头像开发


不久前应网友aikato的要求把头像编辑功能由flash改成了html5 (链接)。当时没对这事有多大兴趣因为这不是个网民每次上网都要用到的功能,也许一个网民在一个网站就用一次。没想到贴出来后好几位网友表示不喜欢flash而偏好html5。网友carry0987向我介绍了他人写的头像插件和其它网站上对这个功能的修改,所以我也来尝试下将我的修改代码改成插件形式。

编码和解码

回想起来当时没有写成插件一是因为没有需要,二是由于当头像在flash编辑后上传到服务器后,服务器端的程序对上传上来的图片数据做了个解码,这说明flash程序里对图像数据做了某种编码。而html5则用了另一种称为base64的编码,所以在服务器端需要对数据做base64的解码。当时觉得如果不直接修改Discuz代码来支持这种解码而写插件的话,就要拷贝很多Discuz代码到插件里就有些无聊了。这次重新考虑了下,发现我们可以在客户端将html5生成的用base64编码的图片数据先解码,再按服务器端的flash解码方式在客户端先做对应的编码,这样上传的图片数据就和原来完全相同,因而就不用修改服务器端的代码了。

Discuz的解码程序在文件 uc_server/control/user.php 里: function flashdata_decode($s) { $r = ''; $l = strlen($s); for($i=0; $i<$l; $i=$i+2) { $k1 = ord($s[$i]) - 48; $k1 -= $k1 > 9 ? 7 : 0; $k2 = ord($s[$i+1]) - 48; $k2 -= $k2 > 9 ? 7 : 0; $r .= chr($k1 << 4 | $k2); } return $r; } 这个编码基于常用的16进制数表示:0到9的数字不变,而10到15分别用字母A到F来表示。用这种0到15这16个数字和0到9加上A到F共16个字符间的一一对换,每个8位数据都可以用两个0到9加上A到F的字符组合表示,而解码就是两个0到9加上A到F的字符组合转换成一个8位数据。

举例而言:200 = 12 * 16 + 8 => (12, 8) => (C, 8) => C8。理解了这一点,我们就不难在网页代码里重现原来flash里的编码程序(因为是javascript代码,用到的函数和原来的php代码有所不同,本质是一样的): function flashdata_encode(s) { var r = ''; var l = s.length; for (var i = 0; i < l; i++) { var k = s[i].charCodeAt(0); var k1 = k >> 4; var k2 = k - (k1 << 4); k1 += 48; if (k1 > 57) k1 += 7; k2 += 48; if (k2 > 57) k2 += 7; r += String.fromCharCode(k1, k2); } return r; }
一些改进:

1)头像图片的三种来源:原来的代码修改旨在替换原有的头像编辑功能,所以只支持上传用户自己机器上的图片做为头像。但为什么不能象日志里添加图片那里那样,也支持用相册图片和网络图片做为头像呢?所以在这个插件里我支持了上传图片,相册图片和网络图片三种图片来源:
界面的代码参照了文件 template/default/home/editor_image_menu.htm,而处理提交选择后的图片的代码参照了文件 uc_server/control/user.php。幸好裁剪图片的代码不管图片来自何方,所以并不需要为支持相册图片和网络图片而添加很多代码。

2)以flash 为后备(fallback):以html5替代flash固然好,但万一有用户用的是旧的浏览器不支持html5怎么办呢?为此我加了一段判断用户的浏览器是否支持html5的画布功能。如果支持就用我们的html5功能,不然还是显示原来的flash功能: if (isCanvasSupported()) { replaceAvatarSection(document.getElementById('avatardesigner')); ... } //http://stackoverflow.com/questions/2745432/best-way-to-detect-that-html5-canvas-is-not-supported function isCanvasSupported() { var elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); }
3)在javascript文件里使用语言包里的汉字:在插件中的javascript文件里要使用汉字比如提示框里要显示汉字怎么办?有此问题是在javascript文件里不象在php文件和html文件能调用语言包里定义的汉字。Discuz代码自身的做法是在有些javascript文件里直接把汉字写在里面,因此对于这些文件,Discuz的每个语言版本就提供了不同版本的文件(而不是象其它文件那样通用)。而且这种做法也不适合要支持多种语言版本的插件因为把插件放到Discuz应用中心时没法提供多个语言版本的同一javascript文件。看到Discuz网站上一个讨论(链接)给出了个很好的解决方法:在html文件里调用语言包里的汉字来定义javascript变量值,而在javascript文件里调用这些变量:
在模板文件 avatar.htm 里: <script type="text/javascript"> var upload_succeed = '{lang txgz_avatar:upload_succeed}'; var three_avatars = '{lang txgz_avatar:three_avatars}'; var upload_error = '{lang upload_error}'; </script> <script type="text/javascript" src="source/plugin/txgz_avatar/js/avatar.js?{VERHASH}"></script> 在 javascript 文件 avatar.js 里: ctx.fillText(upload_succeed, dwidth - 140, 180);

插件下载: http://www.bian-wang.com/discuz/data/userupload/10005/txgz_avatar.zip (04/26/2017更新)

10/17/2016补充:写了一个不基于HTML5且支持动画图片的新版本 http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1533
04/26/2017补充:网友e0759提醒本插件在Discuz2.5里不工作。检查发现由模版文件avatar.htm产生的脚本文件有语法错误。看来是因为Discuz2.5的block标签内不能插入eval标签 (链接),解决办法是将原来开始的两句 <!--{block avatardesigner}--> <!--{eval $albums = getalbums($_G['uid']); }--> 改成 {eval $albums = getalbums($_G['uid']); } <!--{block avatardesigner}--> 这样就适用于2.5以上的所有版本了。

发表评论 评论 (140 个评论)

回复 天香公主 2017-3-16 09:26 PM
carry0987: 天香,關於之前的帖子封面,我發現有個弊端,就是如果我單純放個音樂帖,又不想要為了讓dz抓取而上傳圖片到帖子裡面,會造成無解的狀況...(意思是,假設我的帖 ...
论坛里的东西我不敢贸然改动,因为我用过Discuz里的论坛,缺乏直观的认识,而且感觉比日志和记录的功能要复杂些,怕改坏了反为不美。
回复 carry0987 2017-3-13 05:39 AM
天香,關於之前的帖子封面,我發現有個弊端,就是如果我單純放個音樂帖,又不想要為了讓dz抓取而上傳圖片到帖子裡面,會造成無解的狀況...(意思是,假設我的帖子裡面沒有任何圖片,就沒辦法產生封面,不知道有什麼方法可以自己上傳封面,又不用出現在帖子裡面?)
回复 carry0987 2017-3-12 12:51 AM
天香公主: 你可以试试在
1)在source/language/lang_notification.php里加上
    'comment_mention' => '{actor} 在主题 <a href=&quot;forum.php?mod=viewthread&tid={ti ...
好的,我去試試
回复 天香公主 2017-3-12 12:38 AM
carry0987: 對了,天香,Dz的點評能夠使用@嗎?
你可以试试在
1)在source/language/lang_notification.php里加上
    'comment_mention' => '{actor} 在主题 <a href="forum.php?mod=viewthread&tid={tid}" target="_blank">{subject}</a> 中发表的帖子点评中提到了您 &nbsp; <a href="forum.php?mod=redirect&goto=findpost&pid={pid}&ptid={tid}" target="_blank" class="lit">查看 &rsaquo;</a>',

2)在source/include/post/post_newreply.php的下面这句
update_threadpartake($post['tid']);
前面加上
    if (preg_match_all("/(&nbsp;|\s|^)@(\S+)(&nbsp;|\s|$)/", $comment, $matches)) {
        $result = array_unique($matches[2]);
        foreach($result as $ausername) {
            if(($auid = C::t('common_member')->fetch_uid_by_username($ausername))) {
                if ((!empty($_G['uid'])) && ($auid != $_G['uid']) && ($auid != $post['authorid'])) {
                    notification_add($auid, 'comment', 'comment_mention', array(
                        'tid' => $_G['tid'],
                        'pid' => $_GET['pid'],
                        'subject' => $thread['subject'],
                        'from_id' => $_G['tid'],
                        'from_idtype' => 'pcomment',
                        'commentmsg' => cutstr(str_replace(array('', '', '[/color]'), '', preg_replace("/\[color=([#\w]+?)\]/i", "", $comment)), 200)
                    ));
                }
            }
        }
    }
回复 天香公主 2017-3-12 12:22 AM
carry0987: 原來如此...我懂了,iframe之所以會出現警告是因為真的有載入http的連結,而超連結沒有載入的動作,因此才不會出現安全警告 ...
同意
回复 carry0987 2017-3-11 09:27 AM
對了,天香,Dz的點評能夠使用@嗎?
回复 carry0987 2017-3-11 09:23 AM
天香公主: 一般而言,我觉得在https网页里用iframe load http网页会引发安全警告,而包含个指向http 网页的超链不会有警告是正确的。
具体到FB,我不熟悉它,没法回答你的 ...
原來如此...我懂了,iframe之所以會出現警告是因為真的有載入http的連結,而超連結沒有載入的動作,因此才不會出現安全警告
回复 天香公主 2017-3-11 07:15 AM
carry0987: 不,我的意思是,為何在Facebook上發表任何http連結,都不會造成Facebook的小綠鎖消失?是因為Facebook把所有的連結都使用超連結,而非iframe的形式嗎? ...
一般而言,我觉得在https网页里用iframe load http网页会引发安全警告,而包含个指向http 网页的超链不会有警告是正确的。
具体到FB,我不熟悉它,没法回答你的问题,除非你给我个你觉得有疑惑的FB网页,我可以去查下它是用何种方式包含那个http网页的。不过一般在浏览器里看看就应该能分辨出是超链还是iframe了吧?
回复 carry0987 2017-3-11 03:33 AM
天香公主: 你说的对,我早上是在公司里试的,那个机器旧了些。现在在家里机器上看到了警告 (FF) Firefox has blocked parts of this page that are not secure, (GC) This  ...
不,我的意思是,為何在Facebook上發表任何http連結,都不會造成Facebook的小綠鎖消失?是因為Facebook把所有的連結都使用超連結,而非iframe的形式嗎?
回复 天香公主 2017-3-10 07:03 PM
carry0987: 找到問題了,天香你的chrome不是最新版的.....新版的chrome對於ssl的審查制度有改變
你说的对,我早上是在公司里试的,那个机器旧了些。现在在家里机器上看到了警告 (FF) Firefox has blocked parts of this page that are not secure, (GC) This page is trying to load scripts from unauthenticated sources 原因是你要在iframe里load http://school.nehs.tc.edu.tw/schtimetable/td06.aspx,感觉这个警告是对的。你说把它放在FB里没出现警告。能给我个FB网页,让我看看那里是怎么放的?
回复 carry0987 2017-3-10 09:58 AM
找到問題了,天香你的chrome不是最新版的.....新版的chrome對於ssl的審查制度有改變
回复 天香公主 2017-3-10 09:22 AM
carry0987: 抱歉弄錯,是這個,你再進去一次,我是用iframe包起來的
https://www.fucknehs.com/forum.php?mod=viewthread&tid=2&page=1&extra=#pid3 ...
新的这个链接也没问题,见我的截屏:
http://www.bian-wang.com/discuz/data/attachment/album/201703/10/092004ayzdyhf6s6cxkffy.png
http://www.bian-wang.com/discuz/data/attachment/album/201703/10/092012b3ymmfmdmltoexdm.png
回复 carry0987 2017-3-10 09:07 AM
天香公主: 你说的那个 http 链接是什么,让我试试?你的那个网页在我的FF和GC里都有小绿锁
抱歉弄錯,是這個,你再進去一次,我是用iframe包起來的
https://www.fucknehs.com/forum.php?mod=viewthread&tid=2&page=1&extra=#pid3
回复 天香公主 2017-3-10 08:00 AM
東里山人: 是这样的,头像问题分两种,第一种是未开启移动端跳到M前缀的情况下,两个DZ共同一个UC(两个域名是不在同一主域内的),这时在电脑端用DZ默认的FLASH上传头像功 ...
哦,现在清楚你说的问题了,等我过几天搭个类似的环境试了再复。我之前没注意到你的第一部分
回复 天香公主 2017-3-10 07:56 AM
carry0987: 天香,Facebook 是怎麼讓https與http共存的?例如我把一個http的連結貼到facebook上,但是facebook的小綠鎖(代表有使用SSL)依然存在,但是我把http連結貼到我的 ...
你说的那个 http 链接是什么,让我试试?你的那个网页在我的FF和GC里都有小绿锁
回复 東里山人 2017-3-10 06:03 AM
天香公主: 哦,所以是我的插件特有的问题 。感觉可以解决,无非是程序在config_ucenter.php里找到ucenter地址后可能要按需做个M和WWW间的变换。我需要你详细说说"把 ...
是这样的,头像问题分两种,第一种是未开启移动端跳到M前缀的情况下,两个DZ共同一个UC(两个域名是不在同一主域内的),这时在电脑端用DZ默认的FLASH上传头像功能是正常的,但是用你的头像插件是无效的,不能上传。

第二种,每个DZ各自使用自带的UC。我的跳转很简单。DZ本身是能设置多域名的,但我都没有设置,全留空了。我是用Apache跳转的,我在设置是这样:

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} &quot;((iPhone)|(Android)|(iPod)|(ios)|(Windows CE)|(Windows Phone)|(webOS)|(Wget)|(Java)|(curl)|(Opera))&quot; [NC]
RewriteRule ^/(.*)$ http://m.huamuchengxi.com/$1 [L,R=301]

假如探测到非移动端:

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} &quot;!((iPhone)|(Android)|(iPod)|(ios)|(Windows CE)|(Windows Phone)|(webOS)|(Wget)|(Java)|(curl)|(Opera))&quot; [NC]
RewriteRule ^/(.*)$ http://www.huamuchengxi.com/$1 [L,R=301]

上面就是双域名。不过我觉得这样双域名似乎各种问题,所以我打算试试改成WWW域名,然后后面加“mobile=no”或“mobile=2”,这种还没具体测试,要等有空才行。
回复 carry0987 2017-3-9 11:42 PM
天香公主: 哦,所以是我的插件特有的问题 。感觉可以解决,无非是程序在config_ucenter.php里找到ucenter地址后可能要按需做个M和WWW间的变换。我需要你详细说说"把 ...
天香,Facebook 是怎麼讓https與http共存的?例如我把一個http的連結貼到facebook上,但是facebook的小綠鎖(代表有使用SSL)依然存在,但是我把http連結貼到我的論壇的帖子後,小綠鎖卻消失了,並且顯示有不安全的內容...
https://www.fucknehs.com/thread-2-1-1.html
回复 天香公主 2017-3-9 01:55 PM
東里山人: 之前两个DZ共用一个UC的时候,DZ自带的上传头像功能在电脑上没问题,现在域名跳转的条件下没测试。而且在手机也打不开FLASH啊   ...
哦,所以是我的插件特有的问题 。感觉可以解决,无非是程序在config_ucenter.php里找到ucenter地址后可能要按需做个M和WWW间的变换。我需要你详细说说"把第二个DZ弄成双域名(PC端WWW和移动端M),然后用Apache跳转,如果探测到移动端时WWW自动跳到M前缀,如果非移动端则M跳到WWW前缀"的具体实现步骤,让我能效仿在自己机器上试一下。
回复 東里山人 2017-3-9 12:52 PM
天香公主: 问好。看来问题出在跳转上,能不跳就别跳了吧     我猜在这种情况下,即便是用Discuz自带的Flash头像编辑功能也会有图片上传失败的问题吧? ...
之前两个DZ共用一个UC的时候,DZ自带的上传头像功能在电脑上没问题,现在域名跳转的条件下没测试。而且在手机也打不开FLASH啊
回复 天香公主 2017-3-8 10:45 PM
東里山人: 谢谢楼主的回复,很久没来,今天才回复楼主,很不好意思。

上次我没表达清楚,我两个DZ都是包含UC的,不过我想让两个网站的用户数据互通,所以将第二个DZ的UC地 ...
问好。看来问题出在跳转上,能不跳就别跳了吧   我猜在这种情况下,即便是用Discuz自带的Flash头像编辑功能也会有图片上传失败的问题吧?

facelist doodle 涂鸦板

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

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2017-6-25 11:34 PM , Processed in 0.062891 second(s), 19 queries.

返回顶部