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

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

日志

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

热度 9已有 11453 次阅读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);

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以上的所有版本了。
11/27/2017更新:当选择本地图片时,没有必要把图片先上传到服务器上,可以直接显示在图片元素里。这是File API提供的功能,参见这里的讨论。注意网络图片仍有先拷贝到服务器的必要,不然在裁剪图片时会出现跨域安全错误。
11/28/2017更新:防止与其它版本的jQuery发生冲突。
11/29/2017更新:将属性里设置的load事件处理改为在代码里设置,以避免在使用Cloudflare的网站里被其更改而不工作。

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

发表评论 评论 (149 个评论)

回复 天香公主 2016-4-17 05:54 PM
aikato: 搞定的了呢,取消了邀請碼的了 :)
我试了下你的网站,能用上传图片当头像,但相册图片和网络图片都不工作。我做了些修改,请你再试试
http://www.bian-wang.com/upload/txgz_avatar_160417a.zip
回复 aikato 2016-4-17 02:36 AM
天香公主: 谢谢,找到问题了 (我原来假定头像编辑页上有两个表单,第一个是搜索表单,第二个才是头像表单,而你把搜索框去掉了,现在我把这假设去掉了)

请更新一下 http ...
原來是這樣子哦 哈哈
回复 aikato 2016-4-17 02:35 AM
天香公主: 谢谢,我注册过了,你可以把邀请码加上去了。
搞定的了呢,取消了邀請碼的了 :)
回复 天香公主 2016-4-17 12:54 AM
aikato: 關掉了邀請碼了喔
谢谢,我注册过了,你可以把邀请码加上去了。
回复 天香公主 2016-4-17 12:53 AM
aikato: 沒有修改了喔
之前一直都只是在改主題而已,沒有修改過同類文件喔
谢谢,找到问题了 (我原来假定头像编辑页上有两个表单,第一个是搜索表单,第二个才是头像表单,而你把搜索框去掉了,现在我把这假设去掉了)

请更新一下 http://www.bian-wang.com/upload/txgz_avatar_160417.zip
回复 aikato 2016-4-17 12:13 AM
天香公主: 你的网站没法注册因为要邀请码。不过我想起可能的原因了,你的网站是不是已经照我原来说的办法改过spacece_avatar.htm和user.php了?能不能将这两个文件用Discuz ...
關掉了邀請碼了喔
回复 aikato 2016-4-17 12:13 AM
天香公主: 你的网站没法注册因为要邀请码。不过我想起可能的原因了,你的网站是不是已经照我原来说的办法改过spacece_avatar.htm和user.php了?能不能将这两个文件用Discuz ...
沒有修改了喔
之前一直都只是在改主題而已,沒有修改過同類文件喔
回复 天香公主 2016-4-16 10:24 PM
aikato: 安裝完測試上傳頭像時,跳轉後只出現 -3,然後就出錯了喔
http://f3story.com/home.php?mod=spacecp&ac=avatar
可以開個帳號看看呢 ...
你的网站没法注册因为要邀请码。不过我想起可能的原因了,你的网站是不是已经照我原来说的办法改过spacece_avatar.htm和user.php了?能不能将这两个文件用Discuz提供的文件再复原回来?因为我的插件需要spacecp_avatar.htm里有原来Discuz文件里有的flash embed元素
回复 aikato 2016-4-16 09:50 PM
安裝完測試上傳頭像時,跳轉後只出現 -3,然後就出錯了喔
http://f3story.com/home.php?mod=spacecp&ac=avatar
可以開個帳號看看呢
12345678

facelist doodle 涂鸦板

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

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2024-3-28 03:09 PM , Processed in 0.025850 second(s), 10 queries. ,ApcOn

返回顶部