头图

朋友圈承载着大量人们生活、工作的碎片化记忆,是大家表达自我、开展社交的重要场景。那么,在YonBuilder移动端低代码开发平台(APICloud)能够实现哪些朋友圈功能、以及该如何实现呢?本文将为各位开发者带来朋友圈主要功能开发教程。首先展示效果:

807fcb97dfe2036683f7fa76ae5744ff.png

项目结构图以及用到的模块

708883bda4534615365900e1817aca30.png

主要功能

1、下拉刷新、上拉加载(mescroll.js)

​2、点赞评论

​3、导航背景透明渐变效果

​4、图像预览(UIPhotoViewer)

​5、图像压缩

​6、定位附近地点(aMap)

​7、图像批量上传

功能点详解

​1、下拉刷新和上拉加载

下拉刷新和上拉加载用的是 mescroll.js(自带图像懒加载,官方网站有详细使用说明文档) 实现的思路是自定义下拉样式,当下拉的时候图像不停旋转同时向下移动,几秒后向上移动消失在顶部。下拉刷新效果需要自定义,更改下拉刷新的布局容器样式 warpClass: 'refresh' 。<div class="refresh"></div> //下拉刷新容器 css 样式如下:

.refresh {
    position: fixed;
    top: 0;
    width: 100%
}
​<div class="laoding"><img src="../res/icon.png" class="img"></div>旋转动画效果 css 样式如下:

.laoding {
    position: fixed;
    top: -1.5rem;
    left: 2rem;
    width: 1.5rem;
    height: 1.5rem;
    z-index: 1;
}

.to_bottom {
    -webkit-animation: to_bottom 2s;
    animation: to_bottom 2s;
}

.laoding .img {
    width: 1.3rem;
    height: 1.3rem;
    animation: rotating 0.2s linear infinite;
    -webkit-animation: rotating 0.2s infinite;
}
@keyframes to_bottom {
    0% { top: -4rem; }
    4% { top: 3rem; }
    8% { top: 4rem; }
    10% { top: 5rem; }
    50% { top: 5rem; }
    75% { top: 5rem; }
    100% { top: -1.5rem; }
}

@keyframes rotating {
    to {
        transform: rotate(1turn);
    }
}

2、点赞评论

​这个功能主要是样式的设计难度很小但是需要注意当屏幕滚动时需要隐藏评论框以及相关按钮。

f745c19b6e9c215ad468e49df4e6ecc4.png

3、导航背景透明渐变效果

​实现的思路是结合mescroll.js滚动监听滚动区域距离顶部的高度、该表导航栏背景和文字以及状态栏的文字颜色。具体代码如下:


<header>
    <div class="status-bar"></div>
    <div class="nav">
        <div class="back"><i class="iconfont icon">&#xe70c;</i></div>
        <div class="nav-title"></div>
        <div class="camera" onclick="add()"><i class="iconfont icon">&#xe6aa;</i></div>
    </div>
</header>

if (h < 60) {
    StatusBar('light', 'rgba(255, 255, 255, 0)');
    hui('header').css({ 'background': "rgba(255,255,255,0.0" + h + ")" })
    hui('header').css({ 'box-shadow': "1px 3px 4px rgba(0, 0, 0, 0)" })
    hui(".icon").css({ "color": "#ffffff" });
    hui(".nav-title").html('');
} else if (h >= 60 && h <= 100) {
    StatusBar('dark', 'rgba(255,255,255,0)');
    hui('header').css({ 'background': "rgba(255,255,255,0.0" + h + ")" })
    hui('header').css({ 'box-shadow': "1px 3px 4px rgba(0, 0, 0, 0)" })
    hui(".icon").css({ "color": "#000" });
    hui(".nav-title").html('朋友圈');
} else if (h >= 100) {
    StatusBar('dark', 'rgba(255,255,255,0)');
    hui('header').css({ 'background': "#ffffff" })
    hui('header').css({ 'box-shadow': "1px 3px 4px rgba(0, 0, 0, 0.05)" })
    hui(".icon").css({ "color": "#000" });
    hui(".nav-title").html('朋友圈');
}

4、图像预览(UIPhotoViewer)

​photoswipe.js 效果更好但是不支持图像长按功能。UIPhotoViewer实现起来比较简单,但是要模仿微信那种效果需要创建一个网页viewer-dot.Html来实现滚动效果。
4f4b643a80ab3bf40b843a1d07dd01f6.png

当图像预览发生左右滚动时发送一个广播事件,告诉viewer-dot.Html当图像预览模块关闭时也关闭viewer-dot.Html页面。

apiready = function () {
    api.addEventListener({
        name: 'change_dot'
    }, function (ret, err) {
        init(ret.value.index,ret.value.nub)
    })
    init(api.pageParam.index,api.pageParam.nub)
};
function init(on_index,dot_number) {
    var html = '';
    for (var i = 0; i < dot_number; i++) {
        if (i == on_index) {
            html += '<div class="dot active"></div>';
        } else {
            html += '<div class="dot"></div>';
        }
    }
    hui('.list').html(html);
}

5、图像压缩

​图像压缩可以用compactPicture,压缩后图像清晰、体积小。封装了一个 js 函数实现图像压缩 compress_img()。

function compress_img(path, obj, callback) {
    var img = new Image();
    img.src = path;
    img.onload = function () {
        var that = this;
        var w = that.width, h = that.height, scale = w / h;
        w = obj.width || w;
        h = obj.height || (w / scale);
        var quality = 0.7
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(that, 0, 0, w, h);
        if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
            quality = obj.quality;
        }
        var base64 = canvas.toDataURL('image/jpeg', quality);
        callback(base64);
    }
}

图像压缩前需要指定图像宽度,如果设为固定值,所有图像压缩后宽度一样,这肯定不行。所以需要根据图片的宽度、高度灵活设置压缩后的宽度。imageFilter模块可以获取图像宽高。

        var imageFilter = api.require('imageFilter');
        imageFilter.getAttr({
            path: pic
        }, function (ret, err) {
            if (ret.status) {
                if (ret.width > ret.height) {
                    if (ret.width > 1000) { imgw = 1200}
                    else if (ret.width < 1000 && ret.width > 700) { imgw = 800}
                    else if (ret.width < 700 && ret.width > 500) { imgw = 600}
                    else {imgw = 400}
                }
                else {
                    if (ret.height > 3000) {imgw = 990}
                    else if (ret.height < 3000 && ret.height > 1600) {imgw = 900}
                    else if (ret.height < 1600 && ret.height > 1000) {imgw = 800}
                    else if (ret.height < 1000 && ret.height > 600) {imgw = 550}
                    else if (ret.height < 600 && ret.height > 400) {imgw = 350}
                    else {imgw = 200}
                }

但是压缩后返回的是base64,批量上传二进制流不方便,所以利用trans 块将base64转成jpg,然后再批量上传。

compress_img(pic, {
    width: imgw
}, function (base) {
    var imgName = randomString(8) + '.jpg';
    var imgPath = "fs://picture/moments/"
    var base64Str = base.replace('data:image/jpeg;base64,', '');
    var trans = api.require('trans');
    trans.saveImage({
        base64Str: base64Str,
        imgPath: imgPath,
        imgName: imgName
    }, function (ret, err) {
        if (ret.status) {
            var path = api.fsDir + "/picture/moments/" + imgName;
            vm.pics.push(path);
        }
    });
});

6、定位附近地点(aMap)

​使用该模块需要获取定位权限,同时还要执行updateMapViewPrivacy、updateSearchPrivacy,否则地图和搜索接口都无效。

function open_map() {
        var ret = api.hasPermission({
            list: ['location']
        });
        if (ret[0].granted) {
            api.openWin({
                name: 'map-view',
                url: 'map-view.html',
            });
        } else {
            api.requestPermission({
                list: ['location'],
            }, function (res) {
                if (res.list[0].granted) {
                    api.openWin({
                        name: 'map-view',
                        url: 'map-view.html',
                    });
                } else {
                    api.toast({
                        msg: '无手机定位权限'
                    })
                }
            });
        } 
    }

利用 searchNearby 接口显示附近地点,详细可以参考:https://developer.yonyou.com/...
03c3f1b4e6671621b825a3b3520653f4.png

7、图像批量上传

​实现思路:图像压缩后将图像地址保存在pics数组里面,再用ajax以表单方式提交文件。

api.ajax({
    url: 'https://www.yy-im.cn/api/moments/add',
    method: 'post',
    data: {
        files: { "pic[]": vm.pics }
    }
}, function (ret, err) {

});

b8902e2c9a38a1f08c6318fb73bb8003.jpg


YonBuilder
17 声望9 粉丝

用友YonBuilder移动低代码开发平台,快速构建高性能多端应用