背景:早早之前在实验室做了一个微信端的图片加工项目。功能就是把用户的图片加工成名家画作的艺术风格。当初做出了最最最最基本的功能,界面也很戳,然后就扔着实习去了。这阵子趁着国庆,重新整了一下上线,趁着手热记录一下~
架构
=>实验室服务器+阿里云+坚果云
用户上传图片后,通过公众号接口拉取图片到阿里云服务器,坚果云将图片同步到实验室服务器,实验室服务器将新增图片队列一一加工输出。
=>数据库mysql
谁,传了哪张图片,选了哪种风格,是默认风格还是自定义风格,输出成哪张图片,这些固然需要一个唯一标签做索引。openid是个不错的选择,但是它无法区分同个用户的不同图片。于是我们使用了时间戳。数据库保存用户openid、图片media_id风格id、时间戳等。输出图片的命名采用“12位时间戳+media_id”。
=>access_token与js_api_ticket
整个微信api的调用过程中,access_token与js_api_ticket的使用极其频繁。在多数教程中都推荐保存在缓存memcached中。其实保存于数据库更为直观,将所有的token逻辑写在token.php中分离开来,需要的时候require_once "token.php";即可,同时后期一些需要明文token【在线配置自定义按钮】直接在数据库找到。
=>推送
服务器跑php循环脚本,每次触发python脚本扫描输出文件夹,检测到新增图片则做相应推送,并将图片切移到其他文件夹,这样每次只需考虑新增图片,避免每次比较新旧文件差异得出新增图片而需要的大量性能消耗。
=>页面设计
除了“我的图集”与“小智图集”,整个流程的跳转都通过js控制隐藏出现的单页面,不存在url的跳转。这样在牺牲一些首页加载时间来保证整个过程的操作是流畅的。
“我的图集”与“小智图集”页面初次只加载9张已下的图片,通过“加载更多”按钮控制加载。
微信接口
=>网页授权
很明显我们的页面需要用户的openid,一开始的方法是让用户在公众号回复特定文字返回以get方式携带用户openid的目标链接。
www.domain.com/target.php?uder_id=012346789
然而让用户回复文字再点击这个操作的体验是很不愉快。通过网页授权接口,将下图配置好的链接设置为按钮链接即可。在目标页面使用$_GET["code"]获取code,用token+code通过curl获得openid。
坑与填坑
=>网页授权的刷新问题
在iOS中,由于滑动返回页面无法像一开始点击菜单一样get参数“code”,于是需要用session
session_start();
require_once "jssdk.php";
$jssdk = new JSSDK("000", "000");
$signPackage = $jssdk->GetSignPackage();
//判断是否已经保存openid字节。
if (!isset($_SESSION['openid'])) {
$user_code = $_GET["code"];
$appid="000";
$secret="000";
$user_code_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$user_code}&grant_type=authorization_code";
$josn_user_code_result=json_decode(httpGet($user_code_url));
$specile_access_token=$josn_user_code_result->access_token;
$specile_openid=$josn_user_code_result->openid;
$_SESSION['openid'] = $specile_openid;
} else {
$specile_openid = $_SESSION['openid'];
}
//curl
function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
=>click与touchstart
移动页面中,click存在300毫秒延迟的问题,而touchstart似乎能敏捷反应。于是一般使用touchstart事件。
但是,如点击图片放大效果中,每次滑动页面都会误触touchstart而自动弹出大图。所以这种场景还是使用click事件。
然而切勿同一页面click与touchstart混用。一次点触事件的触发顺序为:touchstart => mouseover => mousemove => mousedown => mouseup => click => touchend;响应了touchstart事件后会触发其他地方的click事件。
=>“加载更多”的时机
在“我的图集”中,由于瀑布流的样式,加载完图片后需要调整图片的位置。然而,每次点击新增图片的同时调整布局,由于图片尚未加载完成导致无法获取图片的尺寸,新加载的图片无法正常瀑布流显示。需要监听图片加载完成。
document.getElementById("pic_container").innerHTML += creatDOM(str_pic);
var get_img = pic_liu.getChildElement(document.getElementById("pic_container"),"pic_box");
var last_img = get_img[get_img.length - 1].children[0].children[0];
last_img.onload = function() {
pic_liu.imgLocation("pic_container","pic_box");
};//监听最后一张图片加载完成
然而,最后一张图片加载完成≠所以图片加载完成。而检查每张图片加载完成有些繁琐,于是使用了不怎么靠谱的setTimeout
setTimeout(function() {
pic_liu.imgLocation("pic_container","pic_box");
}, 1000);