HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

这个uniapp的api和组件太像小程序了有没有

uni_app

这个api和组件太像小程序了有没有

不过还是比较喜欢的,没有更多额外学习成本

这个api和组件太像小程序了有没有

不过还是比较喜欢的,没有更多额外学习成本

2020承接外包,长期有效,uniapp、web、php、微信

PHP h5+ uniapp Vue 外包

经济不景气,全栈程序员接外包补贴房贷。
可接uniapp、网站,微信小程序、logo海报、等平面设计(有团队),付费解决问题。
不管有没有需求欢迎qq微信骚扰。

qq:50401716
微信

5+案例(资讯,淘宝客,即时聊天):
https://m3w.cn/aihanfu
https://m3w.cn/dsg

一些案例图片:

网站及设计案例请加qq微信查看~

继续阅读 »

经济不景气,全栈程序员接外包补贴房贷。
可接uniapp、网站,微信小程序、logo海报、等平面设计(有团队),付费解决问题。
不管有没有需求欢迎qq微信骚扰。

qq:50401716
微信

5+案例(资讯,淘宝客,即时聊天):
https://m3w.cn/aihanfu
https://m3w.cn/dsg

一些案例图片:

网站及设计案例请加qq微信查看~

收起阅读 »

小程序开发费用,2018年的小程序开发费用

微信小程序 小程序

  现在常见的郑州小程序开发方式主要有以下三种,小程序开发费用通常是根据功能需求以及开发难度等因素决定,目前来说只有一个大致的价格区间,很多投资者在询问价格时,无法得到明确答复就是因为这些原因,而定制开发的小程序所需费用是三种开发方式中比较贵的。下面来详细的跟大家分析一下各种开发方式所对应的小程序开发区别吧。

  1、定制类小程序开发

  这类小程序所需的开发费用一般在一万以上,因为定制开发类的小程序可以满足企业自身的个性化需求的功能,从事这类定制类小程序开发公司通常会由产品经理、核心技术人员等团队成员和客户详细沟通需求,然后提供相应的报价和解决方案,定制类小程序在完成开发后,功能使用往往比较贴合客户需求。

  2、模板开发方式

  小程序开发公司一般要会根据不同的行业分类开发出一些固定的模板,一个模板同时可以卖给成千上万的客户,这种开发方式对于开发商来说利润很高,对用户而言所付出的成本也相对于低,但是这种开发方式弊端,就是无法修改模板,只是把小程序按年租售,同时也会存在部分功能无法实现又承载过多一些多余功能的情况,这类小程序的售后服务通常也不完善。

  3、开发各类常用模板的开发公司

  这类公司主要是开发一些常用的功能模板,与模板类不同的是,客户可以根据自己的需求来选择不同的功能进行组合,价格相对也会高一些,一般在几千到一万元以内,这类开发小程序虽然有一定的选择性,但功能并不能完全实现个性化定制。

  小程序开发需要多少费用?这是所有企业和个体商家关注的焦点,首先无论是哪一类型的小程序,开发费用都相对较低,但是不同类型的小程序根据用户的功能需求的不同,会导致开发费用有所差异,一般价格区间在几千到几万之间,小程序的开发费用是可以根据其开发方式推算出大概的预算方案,所以具体还是要跟开发公司协商才行。

本文由专业的郑州小程序开发(http://www.appsaa.com)燚轩科技整理发布,如需转载请注明出处。

继续阅读 »

  现在常见的郑州小程序开发方式主要有以下三种,小程序开发费用通常是根据功能需求以及开发难度等因素决定,目前来说只有一个大致的价格区间,很多投资者在询问价格时,无法得到明确答复就是因为这些原因,而定制开发的小程序所需费用是三种开发方式中比较贵的。下面来详细的跟大家分析一下各种开发方式所对应的小程序开发区别吧。

  1、定制类小程序开发

  这类小程序所需的开发费用一般在一万以上,因为定制开发类的小程序可以满足企业自身的个性化需求的功能,从事这类定制类小程序开发公司通常会由产品经理、核心技术人员等团队成员和客户详细沟通需求,然后提供相应的报价和解决方案,定制类小程序在完成开发后,功能使用往往比较贴合客户需求。

  2、模板开发方式

  小程序开发公司一般要会根据不同的行业分类开发出一些固定的模板,一个模板同时可以卖给成千上万的客户,这种开发方式对于开发商来说利润很高,对用户而言所付出的成本也相对于低,但是这种开发方式弊端,就是无法修改模板,只是把小程序按年租售,同时也会存在部分功能无法实现又承载过多一些多余功能的情况,这类小程序的售后服务通常也不完善。

  3、开发各类常用模板的开发公司

  这类公司主要是开发一些常用的功能模板,与模板类不同的是,客户可以根据自己的需求来选择不同的功能进行组合,价格相对也会高一些,一般在几千到一万元以内,这类开发小程序虽然有一定的选择性,但功能并不能完全实现个性化定制。

  小程序开发需要多少费用?这是所有企业和个体商家关注的焦点,首先无论是哪一类型的小程序,开发费用都相对较低,但是不同类型的小程序根据用户的功能需求的不同,会导致开发费用有所差异,一般价格区间在几千到几万之间,小程序的开发费用是可以根据其开发方式推算出大概的预算方案,所以具体还是要跟开发公司协商才行。

本文由专业的郑州小程序开发(http://www.appsaa.com)燚轩科技整理发布,如需转载请注明出处。

收起阅读 »

Anroid 6.0 动态权限申请代码分享

/*  
    正常权限,无需动态申请:  
        ACCESS_LOCATION_EXTRA_COMMANDS  
        ACCESS_NETWORK_STATE  
        ACCESS_NOTIFICATION_POLICY  
        ACCESS_WIFI_STATE  
        BLUETOOTH  
        BLUETOOTH_ADMIN  
        BROADCAST_STICKY  
        CHANGE_NETWORK_STATE  
        CHANGE_WIFI_MULTICAST_STATE  
        CHANGE_WIFI_STATE  
        DISABLE_KEYGUARD  
        EXPAND_STATUS_BAR  
        GET_PACKAGE_SIZE  
        INSTALL_SHORTCUT  
        INTERNET  
        KILL_BACKGROUND_PROCESSES  
        MODIFY_AUDIO_SETTINGS  
        NFC  
        READ_SYNC_SETTINGS  
        READ_SYNC_STATS  
        RECEIVE_BOOT_COMPLETED  
        REORDER_TASKS  
        REQUEST_INSTALL_PACKAGES  
        SET_ALARM  
        SET_TIME_ZONE  
        SET_WALLPAPER  
        SET_WALLPAPER_HINTS  
        TRANSMIT_IR  
        UNINSTALL_SHORTCUT  
        USE_FINGERPRINT  
        VIBRATE  
        WAKE_LOCK  
        WRITE_SYNC_SETTINGS  

    2)危险权限,需要动态申请:  
    group:android.permission-group.STORAGE  
         READ_EXTERNAL_STORAGE   
         WRITE_EXTERNAL_STORAGE  

    group:android.permission-group.CONTACTS   
         WRITE_CONTACTS   
         GET_ACCOUNTS   
         READ_CONTACTS  

    group:android.permission-group.PHONE  
         READ_CALL_LOG   
         READ_PHONE_STATE   
         CALL_PHONE   
         WRITE_CALL_LOG   
         USE_SIP   
         PROCESS_OUTGOING_CALLS   
        com.android.voicemail.permission.ADD_VOICEMAIL  

    group:android.permission-group.CALENDAR  
         READ_CALENDAR   
         WRITE_CALENDAR  

    group:android.permission-group.CAMERA  
         CAMERA  

    group:android.permissiongroup.SENSORS  
         BODY_SENSORS  

    group:android.permission-group.LOCATION  
         ACCESS_FINE_LOCATION   
         ACCESS_COARSE_LOCATION  

    group:android.permission-group.MICROPHONE  
         RECORD_AUDIO  

    group:android.permission-group.SMS  
         READ_SMS   
         RECEIVE_WAP_PUSH   
         RECEIVE_MMS   
         RECEIVE_SMS   
         SEND_SMS   
         READ_CELL_BROADCASTS  
*/  

/**  
 * Me:   
 *    cnscn <214363570@qq.com>  
 *  
 * 参考:  
 *    https://blog.csdn.net/lvyoujt/article/details/52826556  
 *    https://developer.android.com/reference/android/Manifest.permission  
 *    https://developer.android.com/reference/android/os/Build.VERSION  
 */  

function plusReady() {  
    var Build = plus.android.importClass("android.os.Build");  
    var Manifest = plus.android.importClass("android.Manifest");  
    var MainActivity = plus.android.runtimeMainActivity();  
    //var context=main.getApplicationContext(); //未用到,在此仅供参考  

    var ArrPermissions = [          
        Manifest.permission.READ_EXTERNAL_STORAGE,  
        Manifest.permission.WRITE_EXTERNAL_STORAGE,  
        Manifest.permission.CAMERA  
    ];  

    function PermissionCheck(permission) {  
        if (Build.VERSION.SDK_INT >= 23) {  
            if (MainActivity.checkSelfPermission(permission) == -1) {  
                return false;  
            }  
        }  
        return true;  
    }  

    function PermissionChecks(Arr) {  
        var HasPermission = true;  
        for (var index in Arr) {  
            var permission = Arr[index];  
            //如果此处没有权限,则是用户拒绝了  
            if (!PermissionCheck(permission)) {  
                HasPermission = false;  
                break;  
            }  
        }  
        return HasPermission;  
    }  

    function PermissionRequest(Arr) {  
        var REQUEST_CODE_CONTACT = 101;  
        if (Build.VERSION.SDK_INT >= 23) {  
            MainActivity.requestPermissions(Arr, REQUEST_CODE_CONTACT);  
        }  
    }  

    //如果没有权限,则申请  
    if (!PermissionChecks(ArrPermissions)) {  
            PermissionRequest(ArrPermissions);  
    } else { //如果拥有权限,那么干点啥吧^_^  
            //.......  
    }  
}  

if (window.plus) {  
        plusReady();  
} else {  
        document.addEventListener('plusready', plusReady, false);  
}

继续阅读 »
/*  
    正常权限,无需动态申请:  
        ACCESS_LOCATION_EXTRA_COMMANDS  
        ACCESS_NETWORK_STATE  
        ACCESS_NOTIFICATION_POLICY  
        ACCESS_WIFI_STATE  
        BLUETOOTH  
        BLUETOOTH_ADMIN  
        BROADCAST_STICKY  
        CHANGE_NETWORK_STATE  
        CHANGE_WIFI_MULTICAST_STATE  
        CHANGE_WIFI_STATE  
        DISABLE_KEYGUARD  
        EXPAND_STATUS_BAR  
        GET_PACKAGE_SIZE  
        INSTALL_SHORTCUT  
        INTERNET  
        KILL_BACKGROUND_PROCESSES  
        MODIFY_AUDIO_SETTINGS  
        NFC  
        READ_SYNC_SETTINGS  
        READ_SYNC_STATS  
        RECEIVE_BOOT_COMPLETED  
        REORDER_TASKS  
        REQUEST_INSTALL_PACKAGES  
        SET_ALARM  
        SET_TIME_ZONE  
        SET_WALLPAPER  
        SET_WALLPAPER_HINTS  
        TRANSMIT_IR  
        UNINSTALL_SHORTCUT  
        USE_FINGERPRINT  
        VIBRATE  
        WAKE_LOCK  
        WRITE_SYNC_SETTINGS  

    2)危险权限,需要动态申请:  
    group:android.permission-group.STORAGE  
         READ_EXTERNAL_STORAGE   
         WRITE_EXTERNAL_STORAGE  

    group:android.permission-group.CONTACTS   
         WRITE_CONTACTS   
         GET_ACCOUNTS   
         READ_CONTACTS  

    group:android.permission-group.PHONE  
         READ_CALL_LOG   
         READ_PHONE_STATE   
         CALL_PHONE   
         WRITE_CALL_LOG   
         USE_SIP   
         PROCESS_OUTGOING_CALLS   
        com.android.voicemail.permission.ADD_VOICEMAIL  

    group:android.permission-group.CALENDAR  
         READ_CALENDAR   
         WRITE_CALENDAR  

    group:android.permission-group.CAMERA  
         CAMERA  

    group:android.permissiongroup.SENSORS  
         BODY_SENSORS  

    group:android.permission-group.LOCATION  
         ACCESS_FINE_LOCATION   
         ACCESS_COARSE_LOCATION  

    group:android.permission-group.MICROPHONE  
         RECORD_AUDIO  

    group:android.permission-group.SMS  
         READ_SMS   
         RECEIVE_WAP_PUSH   
         RECEIVE_MMS   
         RECEIVE_SMS   
         SEND_SMS   
         READ_CELL_BROADCASTS  
*/  

/**  
 * Me:   
 *    cnscn <214363570@qq.com>  
 *  
 * 参考:  
 *    https://blog.csdn.net/lvyoujt/article/details/52826556  
 *    https://developer.android.com/reference/android/Manifest.permission  
 *    https://developer.android.com/reference/android/os/Build.VERSION  
 */  

function plusReady() {  
    var Build = plus.android.importClass("android.os.Build");  
    var Manifest = plus.android.importClass("android.Manifest");  
    var MainActivity = plus.android.runtimeMainActivity();  
    //var context=main.getApplicationContext(); //未用到,在此仅供参考  

    var ArrPermissions = [          
        Manifest.permission.READ_EXTERNAL_STORAGE,  
        Manifest.permission.WRITE_EXTERNAL_STORAGE,  
        Manifest.permission.CAMERA  
    ];  

    function PermissionCheck(permission) {  
        if (Build.VERSION.SDK_INT >= 23) {  
            if (MainActivity.checkSelfPermission(permission) == -1) {  
                return false;  
            }  
        }  
        return true;  
    }  

    function PermissionChecks(Arr) {  
        var HasPermission = true;  
        for (var index in Arr) {  
            var permission = Arr[index];  
            //如果此处没有权限,则是用户拒绝了  
            if (!PermissionCheck(permission)) {  
                HasPermission = false;  
                break;  
            }  
        }  
        return HasPermission;  
    }  

    function PermissionRequest(Arr) {  
        var REQUEST_CODE_CONTACT = 101;  
        if (Build.VERSION.SDK_INT >= 23) {  
            MainActivity.requestPermissions(Arr, REQUEST_CODE_CONTACT);  
        }  
    }  

    //如果没有权限,则申请  
    if (!PermissionChecks(ArrPermissions)) {  
            PermissionRequest(ArrPermissions);  
    } else { //如果拥有权限,那么干点啥吧^_^  
            //.......  
    }  
}  

if (window.plus) {  
        plusReady();  
} else {  
        document.addEventListener('plusready', plusReady, false);  
}

收起阅读 »

小程序开发之插件功能的有效实现方法

小程序

  我们在做小程序开发时,比如说在编辑器里里面编辑了一段内容,输出网页版只需要htmlspecialchars_decode()函数就可以搞定了,但是输出小程序就并不是那么简单了,必须要使用wxParse插件才能完成。下面跟大家分享一下导入插件的使用方法:

在wxml中引入,代码如下:

{{title}}

在wcss中引入,代码如下:

@import "/wxParse/wxParse.wxss";

.title{

/ border:solid #000 1rpx; /

width: 100% ;

text-align: center;

background-color: #fff;

font-size: 30rpx;

height:80rpx;

line-height: 80rpx;

}

.content{

/ border:solid #000 1rpx; /

width: 100% ;

margin-top:20rpx;

height: 100%;

background-color: #fff;

font-size: 25rpx;

padding:20rpx;

}

在js中引入,代码如下:

// pages/helpcontent/helpcontent.js

var WxParse = require('../../wxParse/wxParse.js');

Page({

/**

  • 页面的初始数据

*/

data: {

},

/**

  • 生命周期函数--监听页面加载

*/

onLoad: function (options) {

var that=this

wx.request({

url: 'https://www.appsaa.com', //仅为示例,并非真实的接口地址

header: {

'content-type': 'application/json'

},

success: function (res) {

console.log(res.data.title)

that.setData({

title: res.data.title,//第一个data为固定用法,第二个data是json中的data

infos: WxParse.wxParse('infos', 'html', res.data.infos, that, 5)

})

}

})

}

  那么到这里就结束了,大家现在可以尝试一下了,如果还是存在有不理解或者不清楚的地方,都是可以留言咨询我们的。

  本文由专业的郑州小程序开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。

继续阅读 »

  我们在做小程序开发时,比如说在编辑器里里面编辑了一段内容,输出网页版只需要htmlspecialchars_decode()函数就可以搞定了,但是输出小程序就并不是那么简单了,必须要使用wxParse插件才能完成。下面跟大家分享一下导入插件的使用方法:

在wxml中引入,代码如下:

{{title}}

在wcss中引入,代码如下:

@import "/wxParse/wxParse.wxss";

.title{

/ border:solid #000 1rpx; /

width: 100% ;

text-align: center;

background-color: #fff;

font-size: 30rpx;

height:80rpx;

line-height: 80rpx;

}

.content{

/ border:solid #000 1rpx; /

width: 100% ;

margin-top:20rpx;

height: 100%;

background-color: #fff;

font-size: 25rpx;

padding:20rpx;

}

在js中引入,代码如下:

// pages/helpcontent/helpcontent.js

var WxParse = require('../../wxParse/wxParse.js');

Page({

/**

  • 页面的初始数据

*/

data: {

},

/**

  • 生命周期函数--监听页面加载

*/

onLoad: function (options) {

var that=this

wx.request({

url: 'https://www.appsaa.com', //仅为示例,并非真实的接口地址

header: {

'content-type': 'application/json'

},

success: function (res) {

console.log(res.data.title)

that.setData({

title: res.data.title,//第一个data为固定用法,第二个data是json中的data

infos: WxParse.wxParse('infos', 'html', res.data.infos, that, 5)

})

}

})

}

  那么到这里就结束了,大家现在可以尝试一下了,如果还是存在有不理解或者不清楚的地方,都是可以留言咨询我们的。

  本文由专业的郑州小程序开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。

收起阅读 »

mui 如何禁用下拉刷新

下拉刷新

down: {
height: '50px',
range: '80px',
contentdown: "下拉可以刷新", //可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
contentover: "释放立即刷新", //可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
contentrefresh: "正在刷新...", //可选,正在刷新状态时,下拉刷新控件上显示的标题内容
//style: "circle",
color: '#f78000',
callback: downFn // 下拉执行函数
},
注释 //style: "circle",

这个方法安卓可以 ios还是有下拉的样式
可以全部注释,或者不加

继续阅读 »

down: {
height: '50px',
range: '80px',
contentdown: "下拉可以刷新", //可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
contentover: "释放立即刷新", //可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
contentrefresh: "正在刷新...", //可选,正在刷新状态时,下拉刷新控件上显示的标题内容
//style: "circle",
color: '#f78000',
callback: downFn // 下拉执行函数
},
注释 //style: "circle",

这个方法安卓可以 ios还是有下拉的样式
可以全部注释,或者不加

收起阅读 »

使用5+SDK实现IOS集成蓝牙与网口打印

打印 print iOS h5+

该工程是Hbuilder最新IOS 5+SDK的示例demo 集成了蓝牙打印机和网口打印机
使用该工程可以直接封装HTML代码

https://github.com/qjdice/Hbuider-ios-printer

该工程是Hbuilder最新IOS 5+SDK的示例demo 集成了蓝牙打印机和网口打印机
使用该工程可以直接封装HTML代码

https://github.com/qjdice/Hbuider-ios-printer

小程序开发如何实现视频或音频自定义可拖拽进度条

  程序原生组件的音频播放时并没有进度条的显示,而此次在我们所接的项目中,鉴于原生的视频进度条样式太丑,产品要求做一个可拖拽的进度条满足需求。视频和音频提供的api大致是相似的,可以根据以下代码修改为与音频相关的进度条。
wxml的结构如下:

<video id="myVideo" src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" enable-danmu danmu-btn controls="{{false}}" autoplay='{{true}}' bindtimeupdate="videoUpdate" objectFit="fill"></video>
<view class='process-container'>
<image src='{{playStates ? "../../assets/image/pause_icon.png" : "../../assets/image/play_icon.png"}}' class='video-controls-icon' bindtap='videoOpreation'></image>
<view class='slider-container'>
<slider bindchange="sliderChange" bindchanging="sliderChanging" step="1" value="{{sliderValue}}" backgroundColor="#A8A8A8" activeColor="#FFEE83" block-color="#FFEE83" />
</view>
</view>

data中初始化了sliderValue, updateState, playStates几个变量。

data: {

sliderValue: 0, //控制进度条slider的值,

updateState: false, //防止视频播放过程中导致的拖拽失效

playStates: true //控制播放 & 暂停按钮的显示

},

onReady: function () {

this.videoContext = wx.createVideoContext('myVideo');

this.setData({

updateState: true

})

},

videoUpdate在播放进度变化时触发,触发频率 250ms 一次。event.detail = {currentTime, duration},currentTime表示当前时间,duration表示总时长,都以秒为单位

videoUpdate(e) {

if (this.data.updateState) { //判断拖拽完成后才触发更新,避免拖拽失效

let sliderValue = e.detail.currentTime / e.detail.duration * 100;

this.setData({

sliderValue,

duration: e.detail.duration

})

}

},

进度条可拖拽并指定视频跳转到相应的位置

sliderChanging(e) {

this.setData({

updateState: false //拖拽过程中,不允许更新进度条

})

},

sliderChange(e) {

if (this.data.duration) {

this.videoContext.seek(e.detail.value / 100 * this.data.duration); //完成拖动后,计算对应时间并跳转到指定位置

this.setData({

sliderValue: e.detail.value,

updateState: true //完成拖动后允许更新滚动条

})

}

},

暂停/播放视频

videoOpreation() {

this.data.playStates ? this.videoContext.pause() : this.videoContext.play();

this.setData({

playStates: !this.data.playStates

})

}
  总结:slider的最大值为100, step的值最小为1,这会导致视频或音频播放时间过长的时候,slider滑块移动速度很慢,拖拽移动的时间间隔较大,用户体验差。如果还是有不理解的地方,可以留言咨询。

  本文由专业的郑州小程序开发公司燚轩科技整理发布,如需转载请注明出处。

继续阅读 »

  程序原生组件的音频播放时并没有进度条的显示,而此次在我们所接的项目中,鉴于原生的视频进度条样式太丑,产品要求做一个可拖拽的进度条满足需求。视频和音频提供的api大致是相似的,可以根据以下代码修改为与音频相关的进度条。
wxml的结构如下:

<video id="myVideo" src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" enable-danmu danmu-btn controls="{{false}}" autoplay='{{true}}' bindtimeupdate="videoUpdate" objectFit="fill"></video>
<view class='process-container'>
<image src='{{playStates ? "../../assets/image/pause_icon.png" : "../../assets/image/play_icon.png"}}' class='video-controls-icon' bindtap='videoOpreation'></image>
<view class='slider-container'>
<slider bindchange="sliderChange" bindchanging="sliderChanging" step="1" value="{{sliderValue}}" backgroundColor="#A8A8A8" activeColor="#FFEE83" block-color="#FFEE83" />
</view>
</view>

data中初始化了sliderValue, updateState, playStates几个变量。

data: {

sliderValue: 0, //控制进度条slider的值,

updateState: false, //防止视频播放过程中导致的拖拽失效

playStates: true //控制播放 & 暂停按钮的显示

},

onReady: function () {

this.videoContext = wx.createVideoContext('myVideo');

this.setData({

updateState: true

})

},

videoUpdate在播放进度变化时触发,触发频率 250ms 一次。event.detail = {currentTime, duration},currentTime表示当前时间,duration表示总时长,都以秒为单位

videoUpdate(e) {

if (this.data.updateState) { //判断拖拽完成后才触发更新,避免拖拽失效

let sliderValue = e.detail.currentTime / e.detail.duration * 100;

this.setData({

sliderValue,

duration: e.detail.duration

})

}

},

进度条可拖拽并指定视频跳转到相应的位置

sliderChanging(e) {

this.setData({

updateState: false //拖拽过程中,不允许更新进度条

})

},

sliderChange(e) {

if (this.data.duration) {

this.videoContext.seek(e.detail.value / 100 * this.data.duration); //完成拖动后,计算对应时间并跳转到指定位置

this.setData({

sliderValue: e.detail.value,

updateState: true //完成拖动后允许更新滚动条

})

}

},

暂停/播放视频

videoOpreation() {

this.data.playStates ? this.videoContext.pause() : this.videoContext.play();

this.setData({

playStates: !this.data.playStates

})

}
  总结:slider的最大值为100, step的值最小为1,这会导致视频或音频播放时间过长的时候,slider滑块移动速度很慢,拖拽移动的时间间隔较大,用户体验差。如果还是有不理解的地方,可以留言咨询。

  本文由专业的郑州小程序开发公司燚轩科技整理发布,如需转载请注明出处。

收起阅读 »

doodoo.js配置教程 

node nodejs

Doodoo.js -- 中文最佳实践Node.js Web快速开发框架。支持Koa.js, Express.js中间件,支持模块化,插件,钩子机制,可以直接在项目里使用 ES6/7(Generator Function, Class, Async & Await)等特性 https://www.doodooke.com

配置
doodoo配置.env 文件位于项目根目录下,作为全局默认环境配置文件。

# 应用配置  
APP_ROOT=app  
APP_PORT=3000  
APP_HOST=127.0.0.1  

# MYSQL数据库链接  
MYSQL=false  
MYSQL_HOST=127.0.0.1  
MYSQL_USER=root  
MYSQL_PASSWORD=root  
MYSQL_DATABASE=doodoo  
MYSQL_PORT=3306  
MYSQL_CHARSET=utf8mb4  

# MONGODB数据库链接  
MONGOOSE=false  
MONGOOSE_URI=mongodb://127.0.0.1:27017/doodoo  

# REDIS链接  
REDIS=false  
REDIS_HOST=127.0.0.1  
REDIS_PORT=6379  
REDIS_PREFIX=doodoo:  

# 静态资源服务  
STATIC_DIR=www  
STATIC_MAXAGE=30 * 24 * 60 * 60  
STATIC_DYNAMIC=true

支持根据不同环境加载不同的配置文件(自定义文件配置将覆盖全局默认环境配置)

# 创建docker.env文件  
touch docker.env  

# 自定义docker环境启动  
NODE_ENV=docker node app.js
继续阅读 »

Doodoo.js -- 中文最佳实践Node.js Web快速开发框架。支持Koa.js, Express.js中间件,支持模块化,插件,钩子机制,可以直接在项目里使用 ES6/7(Generator Function, Class, Async & Await)等特性 https://www.doodooke.com

配置
doodoo配置.env 文件位于项目根目录下,作为全局默认环境配置文件。

# 应用配置  
APP_ROOT=app  
APP_PORT=3000  
APP_HOST=127.0.0.1  

# MYSQL数据库链接  
MYSQL=false  
MYSQL_HOST=127.0.0.1  
MYSQL_USER=root  
MYSQL_PASSWORD=root  
MYSQL_DATABASE=doodoo  
MYSQL_PORT=3306  
MYSQL_CHARSET=utf8mb4  

# MONGODB数据库链接  
MONGOOSE=false  
MONGOOSE_URI=mongodb://127.0.0.1:27017/doodoo  

# REDIS链接  
REDIS=false  
REDIS_HOST=127.0.0.1  
REDIS_PORT=6379  
REDIS_PREFIX=doodoo:  

# 静态资源服务  
STATIC_DIR=www  
STATIC_MAXAGE=30 * 24 * 60 * 60  
STATIC_DYNAMIC=true

支持根据不同环境加载不同的配置文件(自定义文件配置将覆盖全局默认环境配置)

# 创建docker.env文件  
touch docker.env  

# 自定义docker环境启动  
NODE_ENV=docker node app.js
收起阅读 »

doodoo.js快速入门教程 

node.js

快速入门
我们通过3步演示如何快速创建一个doodoo项目

第一步

# 创建doodoo-demo目录  
mkdir doodoo-demo && cd doodoo-demo  

# 初始化npm  
npm init -y  

# 安装doodoo.js  
yarn add doodooke/doodoo.js  

# 创建app.js  
touch app.js

接下来我们将以下代码copy到app.js

const Doodoo = require("doodoo.js");  

const app = new Doodoo();  
app.start();

第二步

# 创建app/hello/controller目录  
mkdir -p app/hello/controller && cd app/hello/controller  

# 创建test.js文件  
touch test.js

接下来我们将以下代码copy到test.js

module.exports = class extends doodoo.Controller {  
    async _initialize() {  
        // 控制器初始化  
        console.log("_initialize");  
    }  

    async _before() {  
        // 控制器前置  
        console.log("_before");  
    }  

    async _before_index() {  
        // 方法前置  
        console.log("_before_index");  
    }  

    async index() {  
        console.log("index");  
        this.success("Hello Doodoo.js");  
    }  

    async _after_index() {  
        // 方法后置  
        console.log("_after_index");  
    }  

    async _after() {  
        // 控制器后置  
        console.log("_after");  
    }  
};

第三步

进入doodoo-demo根目录

cd ../../../

启动项目

node app.js

通过命令行可以看到如下信息表示启动成功

[doodoo] Version: 1.0.3
[doodoo] Website: 127.0.0.1
[doodoo] Nodejs Version: v10.10.0
[doodoo] Nodejs Platform: darwin x64
[doodoo] Server Enviroment: development
[doodoo] Server Startup Time: 36ms
[doodoo] Server Current Time: 2018-10-09 20:26:40
[doodoo] Server Running At: http://127.0.0.1:3000

通过浏览器访问以下链接可以看到如下提示

http://127.0.0.1:3000/hello/test/index

{
errmsg: "ok",
errcode: 0,
data: "Hello Doodoo.js"
}

源码
按照传统,所有课程源代码基于 MIT 开源,托管于 GitHub :https://github.com/doodooke/doodoo-demo

继续阅读 »

快速入门
我们通过3步演示如何快速创建一个doodoo项目

第一步

# 创建doodoo-demo目录  
mkdir doodoo-demo && cd doodoo-demo  

# 初始化npm  
npm init -y  

# 安装doodoo.js  
yarn add doodooke/doodoo.js  

# 创建app.js  
touch app.js

接下来我们将以下代码copy到app.js

const Doodoo = require("doodoo.js");  

const app = new Doodoo();  
app.start();

第二步

# 创建app/hello/controller目录  
mkdir -p app/hello/controller && cd app/hello/controller  

# 创建test.js文件  
touch test.js

接下来我们将以下代码copy到test.js

module.exports = class extends doodoo.Controller {  
    async _initialize() {  
        // 控制器初始化  
        console.log("_initialize");  
    }  

    async _before() {  
        // 控制器前置  
        console.log("_before");  
    }  

    async _before_index() {  
        // 方法前置  
        console.log("_before_index");  
    }  

    async index() {  
        console.log("index");  
        this.success("Hello Doodoo.js");  
    }  

    async _after_index() {  
        // 方法后置  
        console.log("_after_index");  
    }  

    async _after() {  
        // 控制器后置  
        console.log("_after");  
    }  
};

第三步

进入doodoo-demo根目录

cd ../../../

启动项目

node app.js

通过命令行可以看到如下信息表示启动成功

[doodoo] Version: 1.0.3
[doodoo] Website: 127.0.0.1
[doodoo] Nodejs Version: v10.10.0
[doodoo] Nodejs Platform: darwin x64
[doodoo] Server Enviroment: development
[doodoo] Server Startup Time: 36ms
[doodoo] Server Current Time: 2018-10-09 20:26:40
[doodoo] Server Running At: http://127.0.0.1:3000

通过浏览器访问以下链接可以看到如下提示

http://127.0.0.1:3000/hello/test/index

{
errmsg: "ok",
errcode: 0,
data: "Hello Doodoo.js"
}

源码
按照传统,所有课程源代码基于 MIT 开源,托管于 GitHub :https://github.com/doodooke/doodoo-demo

收起阅读 »

在web-view加载的本地及远程HTML中调用uni的API及网页和vue页面通讯

Webview uniapp

uni-app的web-view组件,支持加载远程网页,在app环境下,还支持加载本地HTML页面。

在web-view加载页面中,会涉及wx、plus、uni等对象的使用。

  • 在小程序下使用wx的api,需要引入微信提供的https://res.wx.qq.com/open/js/jweixin-1.4.0.js。
  • 在app下默认有plus对象,不需要引入js文件。
  • 不管是在小程序下还是在app下,使用uni的api,需要引入https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js

本文会详述在webview里的uni对象的使用方式,以及和vue页面的通讯方式。

HBuilderX 1.0.0 版本开始,uni-app 支持在 web-view 中调用 uni 的 API。

引用依赖的文件

在 web-view 加载的 HTML 中调用 uni 的 API,需要在 HTML 中引用必要的 JS-SDK。

<!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 -->  
<script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>  
<!-- uni 的 SDK,必须引用。 -->  
<script type="text/javascript" src="//js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js"></script>

Tips

  • 这些 JS 文件是在 web-view 加载的那个 HTML 文件中引用的,而不是 uni-app 项目中的文件。
  • 如果不考虑微信小程序,则无需引入微信的 JS-SDK。
  • 两个文件同时引入时,注意引入的顺序,微信的需要在前。

调用的时机

在引用依赖的文件后,需要在 HTML 中监听 UniAppJSBridgeReady 事件触发后,才能安全调用 uni 的 API。

document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.getEnv(function(res) {  
        console.log('当前环境:' + JSON.stringify(res));  
    });  
});

页面跳转

支持调用所有的 uni 路由方法,可以实现从 HTML 重新跳转回应用内的页面。

在 UniAppJSBridgeReady 后,调用路由方法跳转到应用内的页面。

document.addEventListener('UniAppJSBridgeReady', function() {  
    document.querySelector('.btn-list').addEventListener('click', function(evt) {  
        var target = evt.target;  
        if (target.tagName === 'BUTTON') {  
            var action = target.getAttribute('data-action');  
            if(action === 'navigateTo') {  
                uni.navigateTo({  
                    url: '/pages/component/button/button'  
                });  
            }  
        }  
    });  
});

发送消息

可以通过 uni.postMessage 在 HTML 中向应用发送消息。要实现此功能,需要完成以下两步工作。

监听 web-view 的 message 事件

监听 web-view 组件的 message 事件,然后在事件回调的 event.detail.data 中接收传递过来的消息。

<template>  
    <view>  
        <web-view src="http://192.168.1.1:3000/test.html" @message="handleMessage"></web-view>  
    </view>  
</template>  

<script>  
    export default {  
        methods: {  
            handleMessage(evt) {  
                console.log('接收到的消息:' + JSON.stringify(evt.detail.data));  
            }  
        }  
    }  
</script>

从 HTML 向应用发送消息

uni.postMessage 中的参数格式,必须是 data: {}。也就是说,传递的消息信息必须在 data 这个对象中。

document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.postMessage({  
        data: {  
            action: 'postMessage'  
        }  
    });  
});

每次执行 postMessage 后,传递的消息会以数组的形式存放。因此,在 web-view 的 message 事件回调中,接收到的 event.detail.data 的值是一个数组。

获取当前环境信息

HTML 在不同的环境下,可能需要执行不同的操作或传递不同的消息。可以通过 uni.getEnv() 方法,来获取当前的环境信息。

document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.getEnv(function(res) {  
        if (res.plus) {  
            console.log('当前环境为【5+App】');  
        } else if (res.miniprogram) {  
            console.log('当前环境为【微信小程序】');  
        }  
    });  
});

本地 HTML

自 HBuilderX v1.1.0 起,在 5+App 平台下 web-view 支持加载应用内的 HTML 资源。
本地的 HTML 资源,必须存放在规定的目录下,即 uni-app 项目->hybrid->html 目录。

├─common      
├─components        
├─hybrid  
│  └─html  
│          test.html        
├─pages              
├─static  
│  App.vue  
│  main.js  
│  manifest.json  
│  pages.json

与 html 文件相关的 css、js 等本地资源,同样放在这个 hybrid->html 目录下。
这个hybrid目录不会被编译器编译,所以这里的不能放vue文件,而其他目录也不能放本地HTML文件。
未来hybrid目录还会支持其他语言在uni-app的中的混合使用。

注意:在本地 HTML 中引入网络资源时,必须补全协议。比如:https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js

运行体验

示例中 web-view 加载的是一个本机的测试地址,这个测试 HTML 见附件。

  • 加载网络地址的话,需要在本机启动一个服务将此 HTML 放进去,然后修改 hello uni-app 中的 web-view 例子的 src 地址为可访问的局域网地址。

  • 如果是加载本地 HTML 的话,就直接新建目录将此 HTML 放进去,然后修改 web-view 的 src 为 /hybrid/html/test.html 即可。

  • 参考文档:web-view

web-view组件在app中的窗体关系和plus.webview操作方式

uni-app的vue页面本身是一个webview,vue页面里的web-view组件,其实是一个子webview。
但一个vue页面不能放多个web-view组件,这个组件默认是全屏的(不会覆盖原生头和原生导航)。
使用plus代码获得当前webview的对象后(参考此文https://ask.dcloud.net.cn/article/35036),再获取子webview,其实也可以得到web-view组件所对应的plus的webview对象,进而再使用plus.webview的丰富api。
获取子webview时注意时机,获取方法执行太早可能获取不到。

继续阅读 »

uni-app的web-view组件,支持加载远程网页,在app环境下,还支持加载本地HTML页面。

在web-view加载页面中,会涉及wx、plus、uni等对象的使用。

  • 在小程序下使用wx的api,需要引入微信提供的https://res.wx.qq.com/open/js/jweixin-1.4.0.js。
  • 在app下默认有plus对象,不需要引入js文件。
  • 不管是在小程序下还是在app下,使用uni的api,需要引入https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js

本文会详述在webview里的uni对象的使用方式,以及和vue页面的通讯方式。

HBuilderX 1.0.0 版本开始,uni-app 支持在 web-view 中调用 uni 的 API。

引用依赖的文件

在 web-view 加载的 HTML 中调用 uni 的 API,需要在 HTML 中引用必要的 JS-SDK。

<!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 -->  
<script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>  
<!-- uni 的 SDK,必须引用。 -->  
<script type="text/javascript" src="//js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js"></script>

Tips

  • 这些 JS 文件是在 web-view 加载的那个 HTML 文件中引用的,而不是 uni-app 项目中的文件。
  • 如果不考虑微信小程序,则无需引入微信的 JS-SDK。
  • 两个文件同时引入时,注意引入的顺序,微信的需要在前。

调用的时机

在引用依赖的文件后,需要在 HTML 中监听 UniAppJSBridgeReady 事件触发后,才能安全调用 uni 的 API。

document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.getEnv(function(res) {  
        console.log('当前环境:' + JSON.stringify(res));  
    });  
});

页面跳转

支持调用所有的 uni 路由方法,可以实现从 HTML 重新跳转回应用内的页面。

在 UniAppJSBridgeReady 后,调用路由方法跳转到应用内的页面。

document.addEventListener('UniAppJSBridgeReady', function() {  
    document.querySelector('.btn-list').addEventListener('click', function(evt) {  
        var target = evt.target;  
        if (target.tagName === 'BUTTON') {  
            var action = target.getAttribute('data-action');  
            if(action === 'navigateTo') {  
                uni.navigateTo({  
                    url: '/pages/component/button/button'  
                });  
            }  
        }  
    });  
});

发送消息

可以通过 uni.postMessage 在 HTML 中向应用发送消息。要实现此功能,需要完成以下两步工作。

监听 web-view 的 message 事件

监听 web-view 组件的 message 事件,然后在事件回调的 event.detail.data 中接收传递过来的消息。

<template>  
    <view>  
        <web-view src="http://192.168.1.1:3000/test.html" @message="handleMessage"></web-view>  
    </view>  
</template>  

<script>  
    export default {  
        methods: {  
            handleMessage(evt) {  
                console.log('接收到的消息:' + JSON.stringify(evt.detail.data));  
            }  
        }  
    }  
</script>

从 HTML 向应用发送消息

uni.postMessage 中的参数格式,必须是 data: {}。也就是说,传递的消息信息必须在 data 这个对象中。

document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.postMessage({  
        data: {  
            action: 'postMessage'  
        }  
    });  
});

每次执行 postMessage 后,传递的消息会以数组的形式存放。因此,在 web-view 的 message 事件回调中,接收到的 event.detail.data 的值是一个数组。

获取当前环境信息

HTML 在不同的环境下,可能需要执行不同的操作或传递不同的消息。可以通过 uni.getEnv() 方法,来获取当前的环境信息。

document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.getEnv(function(res) {  
        if (res.plus) {  
            console.log('当前环境为【5+App】');  
        } else if (res.miniprogram) {  
            console.log('当前环境为【微信小程序】');  
        }  
    });  
});

本地 HTML

自 HBuilderX v1.1.0 起,在 5+App 平台下 web-view 支持加载应用内的 HTML 资源。
本地的 HTML 资源,必须存放在规定的目录下,即 uni-app 项目->hybrid->html 目录。

├─common      
├─components        
├─hybrid  
│  └─html  
│          test.html        
├─pages              
├─static  
│  App.vue  
│  main.js  
│  manifest.json  
│  pages.json

与 html 文件相关的 css、js 等本地资源,同样放在这个 hybrid->html 目录下。
这个hybrid目录不会被编译器编译,所以这里的不能放vue文件,而其他目录也不能放本地HTML文件。
未来hybrid目录还会支持其他语言在uni-app的中的混合使用。

注意:在本地 HTML 中引入网络资源时,必须补全协议。比如:https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js

运行体验

示例中 web-view 加载的是一个本机的测试地址,这个测试 HTML 见附件。

  • 加载网络地址的话,需要在本机启动一个服务将此 HTML 放进去,然后修改 hello uni-app 中的 web-view 例子的 src 地址为可访问的局域网地址。

  • 如果是加载本地 HTML 的话,就直接新建目录将此 HTML 放进去,然后修改 web-view 的 src 为 /hybrid/html/test.html 即可。

  • 参考文档:web-view

web-view组件在app中的窗体关系和plus.webview操作方式

uni-app的vue页面本身是一个webview,vue页面里的web-view组件,其实是一个子webview。
但一个vue页面不能放多个web-view组件,这个组件默认是全屏的(不会覆盖原生头和原生导航)。
使用plus代码获得当前webview的对象后(参考此文https://ask.dcloud.net.cn/article/35036),再获取子webview,其实也可以得到web-view组件所对应的plus的webview对象,进而再使用plus.webview的丰富api。
获取子webview时注意时机,获取方法执行太早可能获取不到。

收起阅读 »