HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

热力图如何在前端实现

关于热力图的实现原理:
一般可大致归纳为以下几个步骤:
1.为每个数据点设置一个从中心向外灰度渐变的圆;
2.利用灰度可以叠加的原理,计算每个像素点数据交叉叠加得到的灰度值;
3.根据每个像素计算得到的灰度值,在一条彩色色带中进行颜色映射,最后对图像进行着色,得到热力图。
当热力图基于前端技术的具体实现时,又可分为以下四个步骤,接下来为大家详细解析:
1.准备热力图数据格式
由于热力图使用场景一般为地图,所以,数据源需要提供经纬度作为位置信息,以及count作为数据点的权重值。

2.在地图上填充数据
基于canvas绘制热力图时,热力图中每个数据点的半径大小会直接影响到热力图的展现效果,所以一般要结合使用地图的缩放级别以及数据精度来进行设置。

3.叠加显示,权重(密度)算法
上面的绘制结果中,因为没有使用到权重值,所以每个数据点圆的中心点灰度值都是1,不能直接用于颜色映射,需要根据离散点缓冲区的叠加来确定热力分布密度。每一个热点都有一个位置和权重,权重越大,则该点越显著,也就代表其渐变的一个衰变因素,此时,我们需要根据不同的count设置出不同的alpha值。本文主要根据count最小值对应alpha0,最大值对应1的映射计算方式,求得每个数据点,从而绘制出alpha:

4.颜色映射
根据画布上每个像素点累计得到的灰度值,可以从彩色映射色带中得到对应位置的颜色。
那么如何得到画布上每个像素点的信息呢?可以使用canvas提供的getImageData()方法,返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。需要注意的是,ImageData对象中的每个像素,都包含RGBA四项信息:

继续阅读 »

关于热力图的实现原理:
一般可大致归纳为以下几个步骤:
1.为每个数据点设置一个从中心向外灰度渐变的圆;
2.利用灰度可以叠加的原理,计算每个像素点数据交叉叠加得到的灰度值;
3.根据每个像素计算得到的灰度值,在一条彩色色带中进行颜色映射,最后对图像进行着色,得到热力图。
当热力图基于前端技术的具体实现时,又可分为以下四个步骤,接下来为大家详细解析:
1.准备热力图数据格式
由于热力图使用场景一般为地图,所以,数据源需要提供经纬度作为位置信息,以及count作为数据点的权重值。

2.在地图上填充数据
基于canvas绘制热力图时,热力图中每个数据点的半径大小会直接影响到热力图的展现效果,所以一般要结合使用地图的缩放级别以及数据精度来进行设置。

3.叠加显示,权重(密度)算法
上面的绘制结果中,因为没有使用到权重值,所以每个数据点圆的中心点灰度值都是1,不能直接用于颜色映射,需要根据离散点缓冲区的叠加来确定热力分布密度。每一个热点都有一个位置和权重,权重越大,则该点越显著,也就代表其渐变的一个衰变因素,此时,我们需要根据不同的count设置出不同的alpha值。本文主要根据count最小值对应alpha0,最大值对应1的映射计算方式,求得每个数据点,从而绘制出alpha:

4.颜色映射
根据画布上每个像素点累计得到的灰度值,可以从彩色映射色带中得到对应位置的颜色。
那么如何得到画布上每个像素点的信息呢?可以使用canvas提供的getImageData()方法,返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。需要注意的是,ImageData对象中的每个像素,都包含RGBA四项信息:

收起阅读 »

mui框架做的粉红风格服装包包商城网站模板

mui

mui框架做的粉红风格服装包包商城网站模板
这个风格时尚美观,比较适合卖女性商品
喜欢的朋友可以下载研究研究
下载地址:http://www.sucaihuo.com/templates/4490.html

继续阅读 »

mui框架做的粉红风格服装包包商城网站模板
这个风格时尚美观,比较适合卖女性商品
喜欢的朋友可以下载研究研究
下载地址:http://www.sucaihuo.com/templates/4490.html

收起阅读 »

关于JAVA开发HBuillder的微信支付(获取预支付订单后调起微信支付),经验分享

微信支付

本项目主要是集成微信支付,android APP请求java服务器获取预支付订单后调起微信支付。代码简单,亲测可用!
源码demo下载地址:
微信支付java服务端demo

主要是用于替换HBuillder H5+模板中的plus/payment.html文件中如下代码

var PAYSERVER='http://demo.dcloud.net.cn/payment/?payid=';

继续阅读 »

本项目主要是集成微信支付,android APP请求java服务器获取预支付订单后调起微信支付。代码简单,亲测可用!
源码demo下载地址:
微信支付java服务端demo

主要是用于替换HBuillder H5+模板中的plus/payment.html文件中如下代码

var PAYSERVER='http://demo.dcloud.net.cn/payment/?payid=';

收起阅读 »

uni-app 升级检测,客户端实现更新下载App自动安装

升级 升级更新

稍后整理描述后更新!

稍后整理描述后更新!

解决mui下拉刷新使用mui(querySelector).pullRefresh().setStopped(false);禁止和恢复的问题

共用模板,下拉刷新 下拉刷新

把你们的mui.min.js的源码部分修改如下

修改前


disablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.bottomPocket.className = "mui-pull-bottom-pocket "   e, window.removeEventListener("dragup", this)  
                        },  
                        enablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.bottomPocket.classList.remove(e), this.pullCaption.className = g   " "   h, this.pullCaption.innerHTML = this.options.up.contentdown, b.addEventListener("plusscrollbottom", this), window.addEventListener("dragup", this)  
                        }  

修改后


disablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.topPocket.className = "mui-pull-bottom-pocket "   e, window.removeEventListener("dragup", this)  
                        },  
                        enablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.topPocket.classList.remove(e), this.topCaption.className = g   " "   h, this.topCaption.innerHTML = this.options.up.contentdown, b.addEventListener("plusscrollbottom", this), window.addEventListener("dragup", this)  
                        }  

第一次发帖,有点激动。

继续阅读 »

把你们的mui.min.js的源码部分修改如下

修改前


disablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.bottomPocket.className = "mui-pull-bottom-pocket "   e, window.removeEventListener("dragup", this)  
                        },  
                        enablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.bottomPocket.classList.remove(e), this.pullCaption.className = g   " "   h, this.pullCaption.innerHTML = this.options.up.contentdown, b.addEventListener("plusscrollbottom", this), window.addEventListener("dragup", this)  
                        }  

修改后


disablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.topPocket.className = "mui-pull-bottom-pocket "   e, window.removeEventListener("dragup", this)  
                        },  
                        enablePullupToRefresh: function() {  
                            this._initPullupRefresh(), this.topPocket.classList.remove(e), this.topCaption.className = g   " "   h, this.topCaption.innerHTML = this.options.up.contentdown, b.addEventListener("plusscrollbottom", this), window.addEventListener("dragup", this)  
                        }  

第一次发帖,有点激动。

收起阅读 »

关于IOS缓存本地图片读取显示空白的问题解决办法

uniapp

说一下我的应用场景:
网络加载图片太多,所以考虑使用本地缓存。图片下载到本地后使用本地路径。
用到的接口:

// 检查本地是否已经存储  
plus.io.resolveLocalFileSystemURL  

// 下载文件  
plus.downloader.createDownload  

// 下载失败删除文件  
plus.io.resolveLocalFileSystemURL

存储地址使用:_downloads/xxx.jpg

得到的结果如楼主一样,安卓可以读取本地文件,iOS返回空白。

在群里问了半天,最后群主说建议使用uni的API
尝试方法:

// 下载文件  
uni.downloadFile(OBJECT)  

// 保存文件  
uni.saveFile(OBJECT)

通过这种方法,确实可以显示图片,但是有一个问题,就是无法自定义文件名,
下载的临时路径,文件名是使用时间戳命名的,存储到本地后也只能是这个文件名,如果我们要监测缓存,就需要去维护一个网络图片与本地图片的map关系,而且缓存删除更新,都需要更新这个map文件,相对复杂。

思考:为什么uni.saveFile返回的路径可以显示,是不是ios的相对路径不一样?

通过打印,发现uni.saveFile存储到路径在_doc/目录下,尝试把存储路径从_downloads改为_doc后,发现,问题解决了!
原来如此。

相关文档 相对路径URL

继续阅读 »

说一下我的应用场景:
网络加载图片太多,所以考虑使用本地缓存。图片下载到本地后使用本地路径。
用到的接口:

// 检查本地是否已经存储  
plus.io.resolveLocalFileSystemURL  

// 下载文件  
plus.downloader.createDownload  

// 下载失败删除文件  
plus.io.resolveLocalFileSystemURL

存储地址使用:_downloads/xxx.jpg

得到的结果如楼主一样,安卓可以读取本地文件,iOS返回空白。

在群里问了半天,最后群主说建议使用uni的API
尝试方法:

// 下载文件  
uni.downloadFile(OBJECT)  

// 保存文件  
uni.saveFile(OBJECT)

通过这种方法,确实可以显示图片,但是有一个问题,就是无法自定义文件名,
下载的临时路径,文件名是使用时间戳命名的,存储到本地后也只能是这个文件名,如果我们要监测缓存,就需要去维护一个网络图片与本地图片的map关系,而且缓存删除更新,都需要更新这个map文件,相对复杂。

思考:为什么uni.saveFile返回的路径可以显示,是不是ios的相对路径不一样?

通过打印,发现uni.saveFile存储到路径在_doc/目录下,尝试把存储路径从_downloads改为_doc后,发现,问题解决了!
原来如此。

相关文档 相对路径URL

收起阅读 »

Koa nuxt最佳实践前篇

微信小程序 小程序 nodejs node.js

从demo快速上手

首先我们下载demo

git clone https://github.com/doodooke/doodoo-nuxt-demo.git

进入目录安装依赖和启动

yarn install && npm run dev

访问浏览器http://127.0.0.1:3000

继续阅读 »

从demo快速上手

首先我们下载demo

git clone https://github.com/doodooke/doodoo-nuxt-demo.git

进入目录安装依赖和启动

yarn install && npm run dev

访问浏览器http://127.0.0.1:3000

收起阅读 »

tap点击一次出现2次效果的原因

点击事件 重复点击 连续点击

这个原因有几种,网上看了一下基本上都是说应用了2次js文件
但是我都代码应用了一次 还是出现了这个情况
仔细检查了一下发现了这个问题

mui('.mui-content').on('tap', '.ArticleJump', function() {

});

如果代码存在2个mui-conten类 mui-conten包裹了mui-conten 就会出现2次或者多少次点击效果

继续阅读 »

这个原因有几种,网上看了一下基本上都是说应用了2次js文件
但是我都代码应用了一次 还是出现了这个情况
仔细检查了一下发现了这个问题

mui('.mui-content').on('tap', '.ArticleJump', function() {

});

如果代码存在2个mui-conten类 mui-conten包裹了mui-conten 就会出现2次或者多少次点击效果

收起阅读 »

多多客小程序开源版一步安装教程

node.js 微信小程序 小程序

一步安装教程

打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

执行命令

wget https://gitee.com/doodooke/doodoo/raw/master/shell/oneStepInstall.sh && chmod 755 ./oneStepInstall.sh && ./oneStepInstall.sh

1、检测环境

2、自动下载

3、安装依赖

4、系统配置

5、自动启动

继续阅读 »

一步安装教程

打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

执行命令

wget https://gitee.com/doodooke/doodoo/raw/master/shell/oneStepInstall.sh && chmod 755 ./oneStepInstall.sh && ./oneStepInstall.sh

1、检测环境

2、自动下载

3、安装依赖

4、系统配置

5、自动启动

收起阅读 »

多多客小程序开源版8步快速安装教程(图文版)

nodejs node node.js 微信小程序 小程序

1、首先我们打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

2、进入下载的代码目录,打开命令行

3、执行命令安装依赖yarn

4、创建数据库,配置数据库连接

5、执行命令启动项目npm run dev

6、打开浏览器访问http://127.0.0.1:3000,点击开源版下载

7、下载提示完成,执行命令npm run dev重启,打开浏览器访问http://127.0.0.1:3000

8、安装完成,配置.env和.env.web既可以配置完成,系统启动。

继续阅读 »

1、首先我们打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

2、进入下载的代码目录,打开命令行

3、执行命令安装依赖yarn

4、创建数据库,配置数据库连接

5、执行命令启动项目npm run dev

6、打开浏览器访问http://127.0.0.1:3000,点击开源版下载

7、下载提示完成,执行命令npm run dev重启,打开浏览器访问http://127.0.0.1:3000

8、安装完成,配置.env和.env.web既可以配置完成,系统启动。

收起阅读 »

ios离线打包 集成 视频压缩功能

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

第一步
1.在HBuilder-Hello目录下新建compressVideo文件夹,在改文件夹下新建文件SendVideoView.h和SendVideoView.m

2.SendVideoView.h代码

#include "PGPlugin.h"  
#include "PGMethod.h"  

@interface SendVideoView : PGPlugin  
    - (void)compression:(PGMethod*)commands;  
    - (CGFloat)fileSize:(NSURL*)path;  
    -(NSString *)getNowTimeTimestamp;  
@end  

3.SendVideoView.m代码

#import "SendVideoView.h"  
#import <AssetsLibrary/AssetsLibrary.h>  
#import <AVFoundation/AVFoundation.h>  

@implementation SendVideoView  
-(NSString *)getNowTimeTimestamp{  

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

    [formatter setDateStyle:NSDateFormatterMediumStyle];  

    [formatter setTimeStyle:NSDateFormatterShortStyle];  

    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

    //设置时区,这个对于时间的处理有时很重要  

    NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

    [formatter setTimeZone:timeZone];  

    NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

    NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

    return timeSp;  

}  
//计算压缩大小  
- (CGFloat)fileSize:(NSURL*)path  
{  
    return [[NSData dataWithContentsOfURL:path] length]/1024.00 /1024.00;  
}  
//压缩  
- (void)compression:(PGMethod*)commands  
{  
    NSString* parameter0 = [commands.arguments objectAtIndex:0];  
    NSLog(@"parameter=%@",parameter0);  
    NSString* callFunc = [commands.arguments objectAtIndex:1];  
    NSURL * url = [NSURL URLWithString:parameter0];  
     NSLog(@"第一个参数=%@",parameter0);  
      NSLog(@"压缩前大小 %f MB",[self fileSize:url]);  
    //    创建AVAsset对象  
    AVAsset* asset = [AVAsset assetWithURL:url];  
    /*   创建AVAssetExportSession对象  
     压缩的质量  
     AVAssetExportPresetLowQuality   最low的画质最好不要选择实在是看不清楚  
     AVAssetExportPresetMediumQuality  使用到压缩的话都说用这个  
     AVAssetExportPresetHighestQuality  最清晰的画质  

     */  
    AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];  
    //优化网络  
    session.shouldOptimizeForNetworkUse = YES;  
    //转换后的格式  

    //拼接输出文件路径 为了防止同名 可以根据日期拼接名字 或者对名字进行MD5加密  

    NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];  
    //判断文件是否存在,如果已经存在删除  
    [[NSFileManager defaultManager]removeItemAtPath:path error:nil];  
    //设置输出路径  
    session.outputURL = [NSURL fileURLWithPath:path];  

    //设置输出类型  这里可以更改输出的类型 具体可以看文档描述  
    session.outputFileType = AVFileTypeMPEG4;  

    [session exportAsynchronouslyWithCompletionHandler:^{  
        NSLog(@"%@",[NSThread currentThread]);  

        //压缩完成  

        if (session.status==AVAssetExportSessionStatusCompleted) {  
            //在主线程中刷新UI界面,弹出控制器通知用户压缩完成  
            dispatch_async(dispatch_get_main_queue(), ^{  
                NSString* pResultString = [@"file://" stringByAppendingPathComponent:path];  
                NSLog(@"path=%@",path);  
                PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsString:pResultString];  
                [self toCallback:callFunc withReslut:[result toJSONString]];  
                NSFileManager* fileManager=[NSFileManager defaultManager];  
                // 删除沙盒中的视频  
                BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:[parameter0 substringFromIndex:7]];  
                if(blHave){  
                    BOOL blDele= [fileManager removeItemAtPath:[parameter0 substringFromIndex:7] error:nil];  
                }  
                // 以下调试时开起  
//                NSLog(@"导出完成");  
//                NSLog(@"压缩完毕,压缩后大小 %f MB",[self fileSize:session.outputURL]);  
            });  

        }  

    }];     

}  

@end

第二步
1.打开PandoraApi.bundle下的feature.plist文件

  1. feature.plist文件里加入
    <key>compressVideo</key>
    <dict>
    <key>class</key>
    <string>SendVideoView</string>
    <key>global</key>
    <true/>
    <key>autostart</key>
    <string>YES</string>
    </dict>

第三步
在html 页面 用JS通过 Native.js,调用原生类
var _BARCODE = 'compressVideo'
var B = window.plus.bridge
var compressVideo = {

compression: function (path, successCallback) {  
  var success = typeof successCallback !== 'function' ? null : function (args) {  
      successCallback(args)  
    },  
    callbackID = B.callbackId(success, null)  
  return B.exec(_BARCODE, 'compression', [path, callbackID])  
}  

}

window.plus.compressVideo = compressVideo

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)
安卓版的视频压缩,改天有空了再写出来

继续阅读 »

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

第一步
1.在HBuilder-Hello目录下新建compressVideo文件夹,在改文件夹下新建文件SendVideoView.h和SendVideoView.m

2.SendVideoView.h代码

#include "PGPlugin.h"  
#include "PGMethod.h"  

@interface SendVideoView : PGPlugin  
    - (void)compression:(PGMethod*)commands;  
    - (CGFloat)fileSize:(NSURL*)path;  
    -(NSString *)getNowTimeTimestamp;  
@end  

3.SendVideoView.m代码

#import "SendVideoView.h"  
#import <AssetsLibrary/AssetsLibrary.h>  
#import <AVFoundation/AVFoundation.h>  

@implementation SendVideoView  
-(NSString *)getNowTimeTimestamp{  

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

    [formatter setDateStyle:NSDateFormatterMediumStyle];  

    [formatter setTimeStyle:NSDateFormatterShortStyle];  

    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

    //设置时区,这个对于时间的处理有时很重要  

    NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

    [formatter setTimeZone:timeZone];  

    NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

    NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

    return timeSp;  

}  
//计算压缩大小  
- (CGFloat)fileSize:(NSURL*)path  
{  
    return [[NSData dataWithContentsOfURL:path] length]/1024.00 /1024.00;  
}  
//压缩  
- (void)compression:(PGMethod*)commands  
{  
    NSString* parameter0 = [commands.arguments objectAtIndex:0];  
    NSLog(@"parameter=%@",parameter0);  
    NSString* callFunc = [commands.arguments objectAtIndex:1];  
    NSURL * url = [NSURL URLWithString:parameter0];  
     NSLog(@"第一个参数=%@",parameter0);  
      NSLog(@"压缩前大小 %f MB",[self fileSize:url]);  
    //    创建AVAsset对象  
    AVAsset* asset = [AVAsset assetWithURL:url];  
    /*   创建AVAssetExportSession对象  
     压缩的质量  
     AVAssetExportPresetLowQuality   最low的画质最好不要选择实在是看不清楚  
     AVAssetExportPresetMediumQuality  使用到压缩的话都说用这个  
     AVAssetExportPresetHighestQuality  最清晰的画质  

     */  
    AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];  
    //优化网络  
    session.shouldOptimizeForNetworkUse = YES;  
    //转换后的格式  

    //拼接输出文件路径 为了防止同名 可以根据日期拼接名字 或者对名字进行MD5加密  

    NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];  
    //判断文件是否存在,如果已经存在删除  
    [[NSFileManager defaultManager]removeItemAtPath:path error:nil];  
    //设置输出路径  
    session.outputURL = [NSURL fileURLWithPath:path];  

    //设置输出类型  这里可以更改输出的类型 具体可以看文档描述  
    session.outputFileType = AVFileTypeMPEG4;  

    [session exportAsynchronouslyWithCompletionHandler:^{  
        NSLog(@"%@",[NSThread currentThread]);  

        //压缩完成  

        if (session.status==AVAssetExportSessionStatusCompleted) {  
            //在主线程中刷新UI界面,弹出控制器通知用户压缩完成  
            dispatch_async(dispatch_get_main_queue(), ^{  
                NSString* pResultString = [@"file://" stringByAppendingPathComponent:path];  
                NSLog(@"path=%@",path);  
                PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsString:pResultString];  
                [self toCallback:callFunc withReslut:[result toJSONString]];  
                NSFileManager* fileManager=[NSFileManager defaultManager];  
                // 删除沙盒中的视频  
                BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:[parameter0 substringFromIndex:7]];  
                if(blHave){  
                    BOOL blDele= [fileManager removeItemAtPath:[parameter0 substringFromIndex:7] error:nil];  
                }  
                // 以下调试时开起  
//                NSLog(@"导出完成");  
//                NSLog(@"压缩完毕,压缩后大小 %f MB",[self fileSize:session.outputURL]);  
            });  

        }  

    }];     

}  

@end

第二步
1.打开PandoraApi.bundle下的feature.plist文件

  1. feature.plist文件里加入
    <key>compressVideo</key>
    <dict>
    <key>class</key>
    <string>SendVideoView</string>
    <key>global</key>
    <true/>
    <key>autostart</key>
    <string>YES</string>
    </dict>

第三步
在html 页面 用JS通过 Native.js,调用原生类
var _BARCODE = 'compressVideo'
var B = window.plus.bridge
var compressVideo = {

compression: function (path, successCallback) {  
  var success = typeof successCallback !== 'function' ? null : function (args) {  
      successCallback(args)  
    },  
    callbackID = B.callbackId(success, null)  
  return B.exec(_BARCODE, 'compression', [path, callbackID])  
}  

}

window.plus.compressVideo = compressVideo

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)
安卓版的视频压缩,改天有空了再写出来

收起阅读 »

IOS离线打包集成 阿里云 短视频sdk

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

1.基础版: 只有录制和裁剪功能,

  1. 标准版:可以修改UI
  2. 专业版: 很复杂的功能

可以参考,阿里云SDK说明

阿里云短视频基础版

如何没有离线打包过的,可以参考,官方最新的AS 打包教程:
ios离线打包教程

第一步
先下载ios短视频基础版SDK,详见sdk下载页面
1.开发者打开工程,选中目标target,依次选择”General”->”Embededed Binaries”,点击”+”号,点击“Add Other…”,导入QUCore-ThirdParty.framework和AliyunVideoSDK.framework。
2.同时,还需依赖libz.tbd、libc++.tbd、libiconv.tbd、libresolv.tbd、ImageIO.framework、CoreMedia.framework、CoreVideo.framework、SystemConfiguration.framework、Photos.framework、OpenAL.framework、VideoToolbox.framework请一并加上。截图如下

3.配置 Build Setting -- Build Options -- Enable Bitcode 选项为NO

4.配置 Build Setting -- Linking -- Other Linker Flags 添加 -ObjC选项

第二步
1.在HBuilder-Hello下新建文件夹recoredVideo 并在该文件夹下新建RecordVideo.h和RecordVideo.m文件

2.RecordVideo.h代码

include "PGPlugin.h"

include "PGMethod.h"

import <AliyunVideoSDK/AliyunVideoBase.h>

@interface RecordVideo : PGPlugin

  • (void)record:(PGMethod*)commands;
  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath;
    -(NSString
    )getNowTimeTimestamp;
    @end

3.RecordVideo.m代码

import "RecordVideo.h"

import <AliyunVideoSDK/AliyunVideoSDK.h>

import <AliyunVideoSDK/AliyunVideoRecordParam.h>

import <AliyunVideoSDK/AliyunVideoUIConfig.h>

import <AliyunVideoSDK/AliyunVideoBase.h>

import <AliyunVideoSDK/AliyunVideoCropParam.h>

import <AssetsLibrary/AssetsLibrary.h>

@interface RecordVideo()
@property (nonatomic,strong) NSString *callFunc;
@end

@implementation RecordVideo

  • (void)record:(PGMethod)commands
    {
    AliyunVideoUIConfig
    config = [[AliyunVideoUIConfig alloc] init];
    config.hiddenFlashButton = NO;
    config.imageBundleName = @"QPSDK";
    config.hiddenImportButton = YES;
    [[AliyunVideoBase shared] registerWithAliyunIConfig:config];

    NSString parameter0 = [commands.arguments objectAtIndex:0];
    self.callFunc = [commands.arguments objectAtIndex:1];
    NSData
    data= [parameter0 dataUsingEncoding:NSUTF8StringEncoding];
    NSError error = nil;
    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    NSDictionary
    dict = (NSDictionary )jsonObject;
    AliyunVideoRecordParam
    quVideo = [[AliyunVideoRecordParam alloc] init];
    quVideo.maxDuration = [[dict objectForKey:@"setMaxDuration"] doubleValue];
    quVideo.minDuration = [[dict objectForKey:@"setMinDuration"] doubleValue];
    quVideo.videoQuality = AliyunVideoQualityHight;
    quVideo.torchMode = AliyunCameraTorchModeOff;
    quVideo.size = AliyunVideoVideoSize540P;
    quVideo.gop = [[dict objectForKey:@"setGop"] intValue];
    quVideo.beautifyStatus = [[dict objectForKey:@"setBeautyStatus"] boolValue];
    quVideo.beautifyValue = [[dict objectForKey:@"setBeautyLevel"] intValue];
    quVideo.position = AliyunCameraPositionBack;
    NSString path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];
    quVideo.outputPath = path;
    UIViewController
    recordViewController = [[AliyunVideoBase shared] createRecordViewControllerWithRecordParam:quVideo];
    [AliyunVideoBase shared].delegate = (id)self;
    [self.rootViewController.navigationController pushViewController:recordViewController animated:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }

  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath {
    NSLog(@"录制完成 %@", videoPath);
    ALAssetsLibrary
    library = [[ALAssetsLibrary alloc] init];
    [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:videoPath]
    completionBlock:^(NSURL assetURL, NSError error) {
    NSString path = [@"file://" stringByAppendingPathComponent:videoPath];
    NSDictionary
    dict = [NSDictionary dictionaryWithObjectsAndKeys:@"000000",@"code",path,@"path",nil];
    PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsDictionary:dict];
    [self toCallback:self.callFunc withReslut:[result toJSONString]];
    dispatch_async(dispatch_get_main_queue(), ^{
    [recordVC.navigationController popViewControllerAnimated:YES];
    });
    }];
    }

-(void)videoBaseRecordVideoExit {
NSLog(@"退出录制");
[self.rootViewController.navigationController popViewControllerAnimated:YES];
}

-(NSString *)getNowTimeTimestamp{

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

[formatter setDateStyle:NSDateFormatterMediumStyle];  

[formatter setTimeStyle:NSDateFormatterShortStyle];  

[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

//设置时区,这个对于时间的处理有时很重要  

NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

[formatter setTimeZone:timeZone];  

NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

return timeSp;  

}
@end

第三步
1.打开PandoraApi.bundle下的feature.plist文件

2.feature.plist文件里加入
<key>RecordVideo</key>
<dict>
<key>class</key>
<string>RecordVideo</string>
<key>global</key>
<true/>
<key>autostart</key>
<string>YES</string>
</dict>

然后在html 页面 用JS通过 Native.js,调用原生类
var RecordVideoIos = function (options) {
this.options = this.extend(
{
setResolutionMode: '540p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 80, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'NO', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}, options)
this.init()
}

RecordVideoIos.prototype = {
init: function () {
this.event()
},
event: function () {
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k]
}
return obj
},
open: function (fn) {
let B = window.plus.bridge
let success = typeof fn !== 'function' ? null : function (args) {
fn(args)
}
let callbackID = B.callbackId(success, null)
return B.exec('RecordVideo', 'record', [JSON.stringify(this.options), callbackID])
}
}

const option = {
setResolutionMode: '720p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 60, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'OFF', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}

var recordVideoIos = new RecordVideoIos(option)
if (plus.os.name != 'Android') {
window.plus.recordVideo = recordVideoIos
}

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)

继续阅读 »

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

1.基础版: 只有录制和裁剪功能,

  1. 标准版:可以修改UI
  2. 专业版: 很复杂的功能

可以参考,阿里云SDK说明

阿里云短视频基础版

如何没有离线打包过的,可以参考,官方最新的AS 打包教程:
ios离线打包教程

第一步
先下载ios短视频基础版SDK,详见sdk下载页面
1.开发者打开工程,选中目标target,依次选择”General”->”Embededed Binaries”,点击”+”号,点击“Add Other…”,导入QUCore-ThirdParty.framework和AliyunVideoSDK.framework。
2.同时,还需依赖libz.tbd、libc++.tbd、libiconv.tbd、libresolv.tbd、ImageIO.framework、CoreMedia.framework、CoreVideo.framework、SystemConfiguration.framework、Photos.framework、OpenAL.framework、VideoToolbox.framework请一并加上。截图如下

3.配置 Build Setting -- Build Options -- Enable Bitcode 选项为NO

4.配置 Build Setting -- Linking -- Other Linker Flags 添加 -ObjC选项

第二步
1.在HBuilder-Hello下新建文件夹recoredVideo 并在该文件夹下新建RecordVideo.h和RecordVideo.m文件

2.RecordVideo.h代码

include "PGPlugin.h"

include "PGMethod.h"

import <AliyunVideoSDK/AliyunVideoBase.h>

@interface RecordVideo : PGPlugin

  • (void)record:(PGMethod*)commands;
  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath;
    -(NSString
    )getNowTimeTimestamp;
    @end

3.RecordVideo.m代码

import "RecordVideo.h"

import <AliyunVideoSDK/AliyunVideoSDK.h>

import <AliyunVideoSDK/AliyunVideoRecordParam.h>

import <AliyunVideoSDK/AliyunVideoUIConfig.h>

import <AliyunVideoSDK/AliyunVideoBase.h>

import <AliyunVideoSDK/AliyunVideoCropParam.h>

import <AssetsLibrary/AssetsLibrary.h>

@interface RecordVideo()
@property (nonatomic,strong) NSString *callFunc;
@end

@implementation RecordVideo

  • (void)record:(PGMethod)commands
    {
    AliyunVideoUIConfig
    config = [[AliyunVideoUIConfig alloc] init];
    config.hiddenFlashButton = NO;
    config.imageBundleName = @"QPSDK";
    config.hiddenImportButton = YES;
    [[AliyunVideoBase shared] registerWithAliyunIConfig:config];

    NSString parameter0 = [commands.arguments objectAtIndex:0];
    self.callFunc = [commands.arguments objectAtIndex:1];
    NSData
    data= [parameter0 dataUsingEncoding:NSUTF8StringEncoding];
    NSError error = nil;
    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    NSDictionary
    dict = (NSDictionary )jsonObject;
    AliyunVideoRecordParam
    quVideo = [[AliyunVideoRecordParam alloc] init];
    quVideo.maxDuration = [[dict objectForKey:@"setMaxDuration"] doubleValue];
    quVideo.minDuration = [[dict objectForKey:@"setMinDuration"] doubleValue];
    quVideo.videoQuality = AliyunVideoQualityHight;
    quVideo.torchMode = AliyunCameraTorchModeOff;
    quVideo.size = AliyunVideoVideoSize540P;
    quVideo.gop = [[dict objectForKey:@"setGop"] intValue];
    quVideo.beautifyStatus = [[dict objectForKey:@"setBeautyStatus"] boolValue];
    quVideo.beautifyValue = [[dict objectForKey:@"setBeautyLevel"] intValue];
    quVideo.position = AliyunCameraPositionBack;
    NSString path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];
    quVideo.outputPath = path;
    UIViewController
    recordViewController = [[AliyunVideoBase shared] createRecordViewControllerWithRecordParam:quVideo];
    [AliyunVideoBase shared].delegate = (id)self;
    [self.rootViewController.navigationController pushViewController:recordViewController animated:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }

  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath {
    NSLog(@"录制完成 %@", videoPath);
    ALAssetsLibrary
    library = [[ALAssetsLibrary alloc] init];
    [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:videoPath]
    completionBlock:^(NSURL assetURL, NSError error) {
    NSString path = [@"file://" stringByAppendingPathComponent:videoPath];
    NSDictionary
    dict = [NSDictionary dictionaryWithObjectsAndKeys:@"000000",@"code",path,@"path",nil];
    PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsDictionary:dict];
    [self toCallback:self.callFunc withReslut:[result toJSONString]];
    dispatch_async(dispatch_get_main_queue(), ^{
    [recordVC.navigationController popViewControllerAnimated:YES];
    });
    }];
    }

-(void)videoBaseRecordVideoExit {
NSLog(@"退出录制");
[self.rootViewController.navigationController popViewControllerAnimated:YES];
}

-(NSString *)getNowTimeTimestamp{

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

[formatter setDateStyle:NSDateFormatterMediumStyle];  

[formatter setTimeStyle:NSDateFormatterShortStyle];  

[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

//设置时区,这个对于时间的处理有时很重要  

NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

[formatter setTimeZone:timeZone];  

NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

return timeSp;  

}
@end

第三步
1.打开PandoraApi.bundle下的feature.plist文件

2.feature.plist文件里加入
<key>RecordVideo</key>
<dict>
<key>class</key>
<string>RecordVideo</string>
<key>global</key>
<true/>
<key>autostart</key>
<string>YES</string>
</dict>

然后在html 页面 用JS通过 Native.js,调用原生类
var RecordVideoIos = function (options) {
this.options = this.extend(
{
setResolutionMode: '540p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 80, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'NO', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}, options)
this.init()
}

RecordVideoIos.prototype = {
init: function () {
this.event()
},
event: function () {
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k]
}
return obj
},
open: function (fn) {
let B = window.plus.bridge
let success = typeof fn !== 'function' ? null : function (args) {
fn(args)
}
let callbackID = B.callbackId(success, null)
return B.exec('RecordVideo', 'record', [JSON.stringify(this.options), callbackID])
}
}

const option = {
setResolutionMode: '720p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 60, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'OFF', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}

var recordVideoIos = new RecordVideoIos(option)
if (plus.os.name != 'Android') {
window.plus.recordVideo = recordVideoIos
}

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)

收起阅读 »