HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

用mui要在CSS里面加 *{touch-action: none;}

更新MUI

用mui要在CSS里面加 *{touch-action: none;} 否则tap事件,开发工具会提示
Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080

继续阅读 »

用mui要在CSS里面加 *{touch-action: none;} 否则tap事件,开发工具会提示
Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080

收起阅读 »

MUI使用个推推送流程分析

推送

原文链接(看的格式可能舒服点)

需求:app通知栏收到推送,点击通知栏推送可以进入到不同的详情页


1、监听方法分析

  • receive方法:
    当APP在前台的时候,可以监听接收透传消息,APP不在前台的时候无法监听
    plus.push.addEventListener("receive", function (msg) {  
    }
    • click方法:
      1、iOS APP处于后台,透传消息会变成通知提醒,此时点击通知触发
      2、点击本地设置的推送到通知栏的通知
plus.push.addEventListener("click", function (msg) {  
}

2、技术分析

通知栏通知:

  • iOS
    在个推中,iOS 只有透传,没有通知。当APP不在前台时,透传只在通知栏提醒,点击走click方法处理业务;
  • Android
    APP透传消息都不会出现在通知栏,有两种处理方式:
    1、个推发送通知(但是点击通知只能打开APP、打开链接、下载应用)
    2、收到透传消息后,本地生成通知到通知栏(仅限于APP处于前台,receive方法中处理)

透传消息:

  • APP处于前台才可接收到,APP处于后台无法接收。且接收透传消息时,不可以直接做跳转页面等业务处理,业务处理跳转等需在点击通知栏后进行相应处理。

3、工欲善其事必先利其器,先看官方常见问题:

image.png

4、逻辑处理:

iOS

  • APP处于前台:

    服务器端推送透传消息后,直接在receive方法监听到:
    iOS APP处于前台.png

但是这不是我们要的。我们需要的是用户收到消息后在通知栏出现,而不是直接在receive方法中做业务处理。那么我们可以看下上面官方常见问题第三点,我们需要在消息中心创建一个本地消息:

plus.push.createMessage( str, "LocalMSG", options );

通过点击通知中心的这个本地消息,进入app实现click方法监听处理业务。
那么问题来了,经过测试我们发现,在创建本地消息的时候(receive方法中),APP一定是处于前台的,那么创建了本地通知以后,我们的receive方法一定会监听到,这样不就进入到一个死循环了么?

receive监听 -> 创建本地通知 -> receive再监听到本地通知 -> 再创建本地通知。。。

子子孙孙无穷尽也。

那么我们可以根据参考常见问题的第三点:用户在创建IOS本地消息是可以在“payload”节点添加特殊标记对消息进行区分。
这玩意是在创建消息的时候,官方模板自带的一个参数。在个推后台iOS透传的时候,有一个:image.png
这个其实只是就是把payload参数的值变成你的透传消息json,那么本地创建通知的时候这个值是什么呢?我们看上面创建本地通知的时候,第二个参数LocalMSG,这个就是我们自定义在本地推送的时候的payload参数的值。所以,在receive方法中,我们根据payload参数的值是不是我们设定的LocalMSG就可以判断监听到的推送是不是本地创建的了。

  • APP处于后台:

    当APP处于后台,receive方法监听不到消息,此时消息走消息中心推送,点击后进入APP内,走click方法处理业务,满足需求。
    iOS APP处于后台.png

Android

根据常见问题第二点,我们知道在处理Android消息的时候,需要使用标准格式的透传json:

{title:"通知标题",content:"通知内容",payload:"通知去干嘛这里可以自定义"}

这样,透传消息就不会走receive方法,而是像我们需求那样实现所有通知进入通知中心,点击通知中心走click方法处理。如果不按照此格式来,消息不会走消息中心,而是直接走监听的receive方法(APP在前台时,不在前台时,透传消息甚至监听不到)。

Android APP消息流程梳理.png

需要注意的一点是:

Android透传格式{"title":"通知1","content":"通知内容","payload":"{type:\"notify\",payload:\"通知去干嘛这里可以自定义\"}"}如果想要传输自定义json,赋值给payload,但是里面的json必须是转义过后的,且任何和官方规定格式在同一层的字段都是无效的,例如: {"id":"123","title":"通知1","content":"通知内容","payload":"{type:\"notify\",ids:\"456\"}"}
这里面第一个id:"123"在实际接收到的时候并不会存在。

5、总结

其实扯了一大堆,简而言之就是一句话:

Android推送的时候要注意后台返回的json满足官方格式即可,iOS推送要注意当APP在前台的时候,在receive方法监听的时候判断是否是本地通知。

下面是我的部分关键代码,alart()是测试阶段为了看到效果加的:

        //获取推送通知  
        plus.push.addEventListener("receive", function (msg) {  
            alert("接收到的透传推送 " + JSON.stringify(msg));  
            if (plus.os.name == "iOS") {  
                switch (msg.payload) {  
                    case "LocalMSG":  
                        alert("本地创建消息的 " + JSON.stringify(msg));  
                        break;  
                    default:  
                        //测试本地推送  
                        createLocalPushMsg(msg);  
                        break;  
                }  
            }  
        }, false);
        //点击推送进来  
        plus.push.addEventListener("click", function (msg) {  
            // 判断是从本地创建还是离线推送的消息  
            alert("点击处理消息 " + JSON.stringify(msg));  
        }, false);
        //创建本地消息  
        function createLocalPushMsg(msg) {  
            var options = {cover: false};  
            plus.push.createMessage(msg.content, "LocalMSG", options);  
            if (plus.os.name == "iOS") {  
                outLine('*如果无法创建消息,请到"设置"->"通知"中配置应用在通知中心显示!');  
            }  
        }
本文参考的官方文档附上
继续阅读 »

原文链接(看的格式可能舒服点)

需求:app通知栏收到推送,点击通知栏推送可以进入到不同的详情页


1、监听方法分析

  • receive方法:
    当APP在前台的时候,可以监听接收透传消息,APP不在前台的时候无法监听
    plus.push.addEventListener("receive", function (msg) {  
    }
    • click方法:
      1、iOS APP处于后台,透传消息会变成通知提醒,此时点击通知触发
      2、点击本地设置的推送到通知栏的通知
plus.push.addEventListener("click", function (msg) {  
}

2、技术分析

通知栏通知:

  • iOS
    在个推中,iOS 只有透传,没有通知。当APP不在前台时,透传只在通知栏提醒,点击走click方法处理业务;
  • Android
    APP透传消息都不会出现在通知栏,有两种处理方式:
    1、个推发送通知(但是点击通知只能打开APP、打开链接、下载应用)
    2、收到透传消息后,本地生成通知到通知栏(仅限于APP处于前台,receive方法中处理)

透传消息:

  • APP处于前台才可接收到,APP处于后台无法接收。且接收透传消息时,不可以直接做跳转页面等业务处理,业务处理跳转等需在点击通知栏后进行相应处理。

3、工欲善其事必先利其器,先看官方常见问题:

image.png

4、逻辑处理:

iOS

  • APP处于前台:

    服务器端推送透传消息后,直接在receive方法监听到:
    iOS APP处于前台.png

但是这不是我们要的。我们需要的是用户收到消息后在通知栏出现,而不是直接在receive方法中做业务处理。那么我们可以看下上面官方常见问题第三点,我们需要在消息中心创建一个本地消息:

plus.push.createMessage( str, "LocalMSG", options );

通过点击通知中心的这个本地消息,进入app实现click方法监听处理业务。
那么问题来了,经过测试我们发现,在创建本地消息的时候(receive方法中),APP一定是处于前台的,那么创建了本地通知以后,我们的receive方法一定会监听到,这样不就进入到一个死循环了么?

receive监听 -> 创建本地通知 -> receive再监听到本地通知 -> 再创建本地通知。。。

子子孙孙无穷尽也。

那么我们可以根据参考常见问题的第三点:用户在创建IOS本地消息是可以在“payload”节点添加特殊标记对消息进行区分。
这玩意是在创建消息的时候,官方模板自带的一个参数。在个推后台iOS透传的时候,有一个:image.png
这个其实只是就是把payload参数的值变成你的透传消息json,那么本地创建通知的时候这个值是什么呢?我们看上面创建本地通知的时候,第二个参数LocalMSG,这个就是我们自定义在本地推送的时候的payload参数的值。所以,在receive方法中,我们根据payload参数的值是不是我们设定的LocalMSG就可以判断监听到的推送是不是本地创建的了。

  • APP处于后台:

    当APP处于后台,receive方法监听不到消息,此时消息走消息中心推送,点击后进入APP内,走click方法处理业务,满足需求。
    iOS APP处于后台.png

Android

根据常见问题第二点,我们知道在处理Android消息的时候,需要使用标准格式的透传json:

{title:"通知标题",content:"通知内容",payload:"通知去干嘛这里可以自定义"}

这样,透传消息就不会走receive方法,而是像我们需求那样实现所有通知进入通知中心,点击通知中心走click方法处理。如果不按照此格式来,消息不会走消息中心,而是直接走监听的receive方法(APP在前台时,不在前台时,透传消息甚至监听不到)。

Android APP消息流程梳理.png

需要注意的一点是:

Android透传格式{"title":"通知1","content":"通知内容","payload":"{type:\"notify\",payload:\"通知去干嘛这里可以自定义\"}"}如果想要传输自定义json,赋值给payload,但是里面的json必须是转义过后的,且任何和官方规定格式在同一层的字段都是无效的,例如: {"id":"123","title":"通知1","content":"通知内容","payload":"{type:\"notify\",ids:\"456\"}"}
这里面第一个id:"123"在实际接收到的时候并不会存在。

5、总结

其实扯了一大堆,简而言之就是一句话:

Android推送的时候要注意后台返回的json满足官方格式即可,iOS推送要注意当APP在前台的时候,在receive方法监听的时候判断是否是本地通知。

下面是我的部分关键代码,alart()是测试阶段为了看到效果加的:

        //获取推送通知  
        plus.push.addEventListener("receive", function (msg) {  
            alert("接收到的透传推送 " + JSON.stringify(msg));  
            if (plus.os.name == "iOS") {  
                switch (msg.payload) {  
                    case "LocalMSG":  
                        alert("本地创建消息的 " + JSON.stringify(msg));  
                        break;  
                    default:  
                        //测试本地推送  
                        createLocalPushMsg(msg);  
                        break;  
                }  
            }  
        }, false);
        //点击推送进来  
        plus.push.addEventListener("click", function (msg) {  
            // 判断是从本地创建还是离线推送的消息  
            alert("点击处理消息 " + JSON.stringify(msg));  
        }, false);
        //创建本地消息  
        function createLocalPushMsg(msg) {  
            var options = {cover: false};  
            plus.push.createMessage(msg.content, "LocalMSG", options);  
            if (plus.os.name == "iOS") {  
                outLine('*如果无法创建消息,请到"设置"->"通知"中配置应用在通知中心显示!');  
            }  
        }
本文参考的官方文档附上
收起阅读 »

花了半天时间大概写了份 mui 的 d.ts ,mark一下

mui.min.d.ts

interface Subpages {  
  url: string  
  id: string  
  styles?: object  
  extras?: object  
}  

interface PreloadPages extends Subpages {  
  subpages?: Array<Subpages>  
}  

interface PullRefreshBase {  
  height?: string | number  
  auto?: boolean  
  contentrefresh?: string  
  callback: any  
}  
interface PullRefreshUp extends PullRefreshBase {  
  contentnomore?: string  
}  
interface pullRefreshDown extends PullRefreshBase {  
  style: 'circle'  
  color?: string  
  range?: string | number  
  offset?: string | number  
  contentdown?: string  
  contentover?: string  
}  
interface PullRefresh {  
  container: string  
  down?: pullRefreshDown  
  up?: PullRefreshUp  
}  

interface OffCanvas {  
  /** 显示 */  
  show (): void  
  /** 隐藏 */  
  close (): void  
  /** 切换 */  
  toggle (): void  
  /** 判断是否为显示状态 */  
  isShown (direction?: string): boolean  
}  

interface Numbox {  
  /** 获取当前值 */  
  getValue (): string  
  /** 动态设置新值 */  
  setValue (val: number): void  
  /** 更新选项 */  
  setOption (option: 'min' | 'step' | 'max', val: number): void  
}  

declare namespace mui {  
  /** 初始化 */  
  function init (options?: {  
    wipeBack?: boolean  
    swipe?: boolean  
    subpages?: Array<Subpages>  
    preloadPages?: Array<PreloadPages>  
    pullRefresh?: PullRefresh  
    gestureConfig?: {  
      tap?: boolean  
      doubletap?: boolean  
      longtap?: boolean  
      hold?: boolean  
      release?: boolean  
      swipeleft?: boolean  
      swiperight?: boolean  
      swipeup?: boolean  
      swipedown?: boolean  
      dragstart?: boolean  
      drag?: boolean  
      dragend?: boolean  
    }  
    keyEventBind?: {  
      backbutton?: boolean  
      menubutton?: boolean  
    }  
    beforeback?: Function  
    statusBarBackground?: string  
    preloadLimit?: number  
  }): void  
  /** 打开新窗口 */  
  function openWindow (options: {  
    url: string  
    id: string  
    styles?: object  
    extras?: object  
    createNew?: boolean  
    show?: {  
      autoShow?: boolean  
      aniShow?: object  
      duration?: number  
    }  
    waiting?: {  
      autoShow?: boolean  
      title?: string  
      options?: object  
    }  
  }): void  
  /** 自动消失消息提示框 */  
  function toast (message: string, options?: {  
    duration?: number | 'long' | 'short'  
    type?: 'div'  
  }): void  
  /** 警告框 */  
  function alert (message: string, title?: string, btnValue?: string, callback?: any, type?: 'div'): void  
  /** 确认框 */  
  function confirm (message: string, title?: string, btnValue?: string, callback?: any, type?: 'div'): void  
  /** 输入对话框 */  
  function prompt (message: string, title?: string, btnValue?: string, callback?: any, type?: 'div'): void  
  /** 触发 Dom 事件 */  
  function trigger (element: HTMLElement, event: string, data?: any): void  
  /** 触发自定义事件 */  
  function fire (target: any, event: string, data?: any): void  
  /** 遍历 */  
  function each (obj: any, callback: any): void  
  /** 合并对象 */  
  function extend (deep: boolean, target: any, ...object: Array<any>): void  
  /** 封装 setTimeOut */  
  function later (func: any, delay: number, context?: any): void  
  /** 滚动窗口屏幕到指定位置 */  
  function scrollTo (ypos: number, duration: number, callback?: any): void  
  /** 判断当前运行环境 */  
  let os: object & os  
  interface os {  
    /** 是否在 5+ 环境内 */  
    plus: boolean | undefined  
    /** 是否是流应用 */  
    stream: boolean | undefined  
    /** 是否为 IOS */  
    ios: boolean | undefined  
    /** 是否 iphone */  
    iphone: boolean | undefined  
    /** 是否 ipad */  
    ipad: boolean | undefined  
    /** 是否 android */  
    android: boolean | undefined  
    /** 是否 android 的 chrome 环境 */  
    isBadAndroid: boolean | undefined  
    /** 版本号 */  
    version: string  
  }  
  /** plusReady */  
  function plusReady (callback: any): void  
  /** 关闭最后一次弹出的对话框(H5模式) */  
  function closePopup (): void  
  /** 关闭所有对话框(H5模式) */  
  function closePopups (): void  
  /** 轮播 */  
  function slider (options: any): void  
  /** 创建遮罩 */  
  function createMask (callback: any): Mask  
  interface Mask {  
    /** 显示遮罩 */  
    show (): void  
    /** 关闭遮罩 */  
    close (): void  
  }  
  /** 选择器组件 picker */  
  class PopPicker {  
    constructor (options: { layer?: number, buttons?: Array<any>})  
    setData (options: Array<any>): void  
    pickers: Array<Picker>  
    getSelectedItem (): Array<Picker>  
    show (callback: any): void  
    hide (): void  
    dispose (): void  
  }  
  /** 日期选择器 DtPicker */  
  class DtPicker {  
    constructor (options?: any)  
    getSelectedItems (): any  
    show (callback?: any): void  
    hide (): void  
    dispose (): void  
  }  
  /** 打开新页面 */  
  function open (...options: Array<any>): any  
  /** 当前页面 */  
  function currentWebview (...options: Array<any>): any  
  /** 关闭窗口 */  
  function back (...options: Array<any>): any  
  /** 重写返回逻辑 */  
  function backFunction (...options: Array<any>): any  
  /** 双击退出应用 */  
  function backDouble (...options: Array<any>): any  
  /** 双击进入后台 */  
  function backTast (...options: Array<any>): any  
  /** 预加载 */  
  function preload (...options: Array<any>): any  
  /** Ajax */  
  function ajax (url?: string, settings?: {  
    async?: boolean  
    crossDomain?: boolean  
    data?: any  
    dataType?: 'xml' | 'html' | 'script' | 'json' | 'text'  
    error?: any  
    success?: any  
    timeout?: number  
    type?: 'GET' | 'POST'  
    headers?: any  
    processData?: boolean  
  }): void  
  /** Ajax post */  
  function post (url: string, data?: any, success?: any, dataType?: 'xml' | 'html' | 'script' | 'json' | 'text'): void  
  function get (...options: Array<any>): any  
  function getJSON (...options: Array<any>): any  
}  

interface Picker {  
  setSelectedValue (value: string, duration?: number, callback?: any): void  
  setSelectedIndex (index: number, duration?: number, callback?: any): void  
}  

interface Mui {  
  /** 绑定 Dom 事件 */  
  on (event: string, selector: string, callback: any): void  
  /** 取消事件绑定 */  
  off (event?: string, selector?: string): void  
  /** 遍历 */  
  each (callback: any): void  
  /** 弹出菜单 */  
  popover (status: 'show' | 'hide' | 'toggle', anchor?: HTMLElement | Element): void  
  /** 聚焦 input */  
  input (): void  
  /** 初始化数字输入框 numbox */  
  numbox (): Numbox  
  /** 侧滑菜单 */  
  offCanvas (active?: 'show' | 'close' | 'toggle'): OffCanvas  
  /** 滚动条 */  
  progressbar (options?: any): Progressbar  
  /** 透明标题栏 */  
  transparent (options: any): void  
  /** 区域滚动 */  
  scroll(options?: {  
    scrollY?: boolean  
    scrollX?: boolean  
    startX?: number  
    startY?: number  
    indicators?: boolean  
    deceleration?: number  
    bounce?: boolean  
  }): Scroll  
  /** 初始化 switch */  
  ['switch'] (): void  
}  

interface Scroll {  
  scrollTo (xpos: number, ypos: number, duration?: number): void  
  scrollToBottom (duration?: number): void  
}  
interface Progressbar {  
  show (): void  
  hide (): void  
  setProgress(param: any): void  
}  

/** Mui Dom 选择器 */  
declare function mui (dom: string): Mui & Array<HTMLElement>  
继续阅读 »

mui.min.d.ts

interface Subpages {  
  url: string  
  id: string  
  styles?: object  
  extras?: object  
}  

interface PreloadPages extends Subpages {  
  subpages?: Array<Subpages>  
}  

interface PullRefreshBase {  
  height?: string | number  
  auto?: boolean  
  contentrefresh?: string  
  callback: any  
}  
interface PullRefreshUp extends PullRefreshBase {  
  contentnomore?: string  
}  
interface pullRefreshDown extends PullRefreshBase {  
  style: 'circle'  
  color?: string  
  range?: string | number  
  offset?: string | number  
  contentdown?: string  
  contentover?: string  
}  
interface PullRefresh {  
  container: string  
  down?: pullRefreshDown  
  up?: PullRefreshUp  
}  

interface OffCanvas {  
  /** 显示 */  
  show (): void  
  /** 隐藏 */  
  close (): void  
  /** 切换 */  
  toggle (): void  
  /** 判断是否为显示状态 */  
  isShown (direction?: string): boolean  
}  

interface Numbox {  
  /** 获取当前值 */  
  getValue (): string  
  /** 动态设置新值 */  
  setValue (val: number): void  
  /** 更新选项 */  
  setOption (option: 'min' | 'step' | 'max', val: number): void  
}  

declare namespace mui {  
  /** 初始化 */  
  function init (options?: {  
    wipeBack?: boolean  
    swipe?: boolean  
    subpages?: Array<Subpages>  
    preloadPages?: Array<PreloadPages>  
    pullRefresh?: PullRefresh  
    gestureConfig?: {  
      tap?: boolean  
      doubletap?: boolean  
      longtap?: boolean  
      hold?: boolean  
      release?: boolean  
      swipeleft?: boolean  
      swiperight?: boolean  
      swipeup?: boolean  
      swipedown?: boolean  
      dragstart?: boolean  
      drag?: boolean  
      dragend?: boolean  
    }  
    keyEventBind?: {  
      backbutton?: boolean  
      menubutton?: boolean  
    }  
    beforeback?: Function  
    statusBarBackground?: string  
    preloadLimit?: number  
  }): void  
  /** 打开新窗口 */  
  function openWindow (options: {  
    url: string  
    id: string  
    styles?: object  
    extras?: object  
    createNew?: boolean  
    show?: {  
      autoShow?: boolean  
      aniShow?: object  
      duration?: number  
    }  
    waiting?: {  
      autoShow?: boolean  
      title?: string  
      options?: object  
    }  
  }): void  
  /** 自动消失消息提示框 */  
  function toast (message: string, options?: {  
    duration?: number | 'long' | 'short'  
    type?: 'div'  
  }): void  
  /** 警告框 */  
  function alert (message: string, title?: string, btnValue?: string, callback?: any, type?: 'div'): void  
  /** 确认框 */  
  function confirm (message: string, title?: string, btnValue?: string, callback?: any, type?: 'div'): void  
  /** 输入对话框 */  
  function prompt (message: string, title?: string, btnValue?: string, callback?: any, type?: 'div'): void  
  /** 触发 Dom 事件 */  
  function trigger (element: HTMLElement, event: string, data?: any): void  
  /** 触发自定义事件 */  
  function fire (target: any, event: string, data?: any): void  
  /** 遍历 */  
  function each (obj: any, callback: any): void  
  /** 合并对象 */  
  function extend (deep: boolean, target: any, ...object: Array<any>): void  
  /** 封装 setTimeOut */  
  function later (func: any, delay: number, context?: any): void  
  /** 滚动窗口屏幕到指定位置 */  
  function scrollTo (ypos: number, duration: number, callback?: any): void  
  /** 判断当前运行环境 */  
  let os: object & os  
  interface os {  
    /** 是否在 5+ 环境内 */  
    plus: boolean | undefined  
    /** 是否是流应用 */  
    stream: boolean | undefined  
    /** 是否为 IOS */  
    ios: boolean | undefined  
    /** 是否 iphone */  
    iphone: boolean | undefined  
    /** 是否 ipad */  
    ipad: boolean | undefined  
    /** 是否 android */  
    android: boolean | undefined  
    /** 是否 android 的 chrome 环境 */  
    isBadAndroid: boolean | undefined  
    /** 版本号 */  
    version: string  
  }  
  /** plusReady */  
  function plusReady (callback: any): void  
  /** 关闭最后一次弹出的对话框(H5模式) */  
  function closePopup (): void  
  /** 关闭所有对话框(H5模式) */  
  function closePopups (): void  
  /** 轮播 */  
  function slider (options: any): void  
  /** 创建遮罩 */  
  function createMask (callback: any): Mask  
  interface Mask {  
    /** 显示遮罩 */  
    show (): void  
    /** 关闭遮罩 */  
    close (): void  
  }  
  /** 选择器组件 picker */  
  class PopPicker {  
    constructor (options: { layer?: number, buttons?: Array<any>})  
    setData (options: Array<any>): void  
    pickers: Array<Picker>  
    getSelectedItem (): Array<Picker>  
    show (callback: any): void  
    hide (): void  
    dispose (): void  
  }  
  /** 日期选择器 DtPicker */  
  class DtPicker {  
    constructor (options?: any)  
    getSelectedItems (): any  
    show (callback?: any): void  
    hide (): void  
    dispose (): void  
  }  
  /** 打开新页面 */  
  function open (...options: Array<any>): any  
  /** 当前页面 */  
  function currentWebview (...options: Array<any>): any  
  /** 关闭窗口 */  
  function back (...options: Array<any>): any  
  /** 重写返回逻辑 */  
  function backFunction (...options: Array<any>): any  
  /** 双击退出应用 */  
  function backDouble (...options: Array<any>): any  
  /** 双击进入后台 */  
  function backTast (...options: Array<any>): any  
  /** 预加载 */  
  function preload (...options: Array<any>): any  
  /** Ajax */  
  function ajax (url?: string, settings?: {  
    async?: boolean  
    crossDomain?: boolean  
    data?: any  
    dataType?: 'xml' | 'html' | 'script' | 'json' | 'text'  
    error?: any  
    success?: any  
    timeout?: number  
    type?: 'GET' | 'POST'  
    headers?: any  
    processData?: boolean  
  }): void  
  /** Ajax post */  
  function post (url: string, data?: any, success?: any, dataType?: 'xml' | 'html' | 'script' | 'json' | 'text'): void  
  function get (...options: Array<any>): any  
  function getJSON (...options: Array<any>): any  
}  

interface Picker {  
  setSelectedValue (value: string, duration?: number, callback?: any): void  
  setSelectedIndex (index: number, duration?: number, callback?: any): void  
}  

interface Mui {  
  /** 绑定 Dom 事件 */  
  on (event: string, selector: string, callback: any): void  
  /** 取消事件绑定 */  
  off (event?: string, selector?: string): void  
  /** 遍历 */  
  each (callback: any): void  
  /** 弹出菜单 */  
  popover (status: 'show' | 'hide' | 'toggle', anchor?: HTMLElement | Element): void  
  /** 聚焦 input */  
  input (): void  
  /** 初始化数字输入框 numbox */  
  numbox (): Numbox  
  /** 侧滑菜单 */  
  offCanvas (active?: 'show' | 'close' | 'toggle'): OffCanvas  
  /** 滚动条 */  
  progressbar (options?: any): Progressbar  
  /** 透明标题栏 */  
  transparent (options: any): void  
  /** 区域滚动 */  
  scroll(options?: {  
    scrollY?: boolean  
    scrollX?: boolean  
    startX?: number  
    startY?: number  
    indicators?: boolean  
    deceleration?: number  
    bounce?: boolean  
  }): Scroll  
  /** 初始化 switch */  
  ['switch'] (): void  
}  

interface Scroll {  
  scrollTo (xpos: number, ypos: number, duration?: number): void  
  scrollToBottom (duration?: number): void  
}  
interface Progressbar {  
  show (): void  
  hide (): void  
  setProgress(param: any): void  
}  

/** Mui Dom 选择器 */  
declare function mui (dom: string): Mui & Array<HTMLElement>  
收起阅读 »

图漾深度摄像头的基本使用方法

摄像头

搞到一款图漾的3d相机有好久了,一直也只是编译了sample代码跑起来看看样子,并没有着手看SDK以及开发的事。近几日对照SDK以及其中的SimpleView_FetchFrame例子,捋了捋头绪。代码如下:

include "../common/Utils.hpp"

int main(int argc, char* argv[])
{
//初始化
TYInitLib();

// 打开设备  
// 用设备ID打开设备,同时构建此设备的设备管理器。  
TY_DEV_HANDLE hDevice;  
TYOpenDevice("207000000866", &hDevice);  

// 使能组件  
// 按位或上组件结构体中的值,即可打开设备。  
TYEnableComponents(hDevice, TY_COMPONENT_RGB_CAM | TY_COMPONENT_DEPTH_CAM | TY_COMPONENT_IR_CAM_LEFT | TY_COMPONENT_IR_CAM_RIGHT);  

// 取得帧缓存大小。  
// 说一下这一步的目的,由于打开不同组件(打开哪些组件),以及不同组件参数设定(分辨率)的原因,每一帧数据的大小是不固定的,  
// 所以要用此函数计算一下当前设备以及当前设定下,一帧数据出来,需要多大的缓存buffer。  
// 因为后面需要压入buffer队列进行数据读取,所以要保证buffer的大小能否装下一帧数据。  
int32_t frameSize;  
TYGetFrameBufferSize(hDevice, &frameSize);  

// 驱动内部维护一个queue,用户往队列中enqueue空的buffer,  
// 设备用每一帧的framedata去填充这个空的buffer,填充后,将此buffer弹出队列(dequeue),返回给用户使用。  
// 这几个buffer是循环使用的,弹出被用户取出数据后,又会回到队列尾部。理论上将,只需要两个buffer即可循环使用。  
int frameBuffer_number = 3;  
char* frameBuffer[frameBuffer_number];  
for (int i = 0; i < frameBuffer_number; ++i)  
{  
    frameBuffer[i] = new char[frameSize];  
    TYEnqueueBuffer(hDevice, frameBuffer[i], frameSize);  
}  

//开始拍摄  
TYStartCapture(hDevice);  

//取景后不断有帧输出,需要循环取得帧数据,并进行解析输出。  
TY_FRAME_DATA frame;  
cv::Mat depth, irl, irr, color;  
while(1)  
{  
    // 取得帧  
    TYFetchFrame(hDevice, &frame, -1);  

    // 这句为整个程序的核心,解析得到的帧,解析为cv::Mat类型的图像,跟OpenCV对接后即可进行后续的处理。 defined in Utils.hpp line36  
    parseFrame(frame, &depth, &irl, &irr, &color, 0);  

    //图像显示  
    cv::imshow("Depth", depth);  
    cv::imshow("LeftIR", irl);  
    cv::imshow("RightIR", irr);  
    cv::imshow("Color", color);  

    //检测  
    if (cv::waitKey(1) == 'q') { break; }  

    // 这里就是申请的buffer循环使用的根本,每次buffer被dequeue用户取得帧后,在这个帧处理函数中,最后又把当前的buffer压入队列中,循环使用,  
    // 由于队列特性,队首出列,队尾入列,所以会有循环使用的样子。  
    TYEnqueueBuffer(hDevice, frame.userBuffer,http://www.appsaa.com  , frame.bufferSize);  
}  

//停止拍摄。  
TYStopCapture(hDevice);  
//关闭设备。  
TYCloseDevice(hDevice);  
//反初始化,注销API。  
TYDeinitLib();  
//delete释放内存。  
for (int j = 0; j < frameBuffer_number; ++j)  
{  
    delete frameBuffer[j];  
}  

return 0;  

}

继续阅读 »

搞到一款图漾的3d相机有好久了,一直也只是编译了sample代码跑起来看看样子,并没有着手看SDK以及开发的事。近几日对照SDK以及其中的SimpleView_FetchFrame例子,捋了捋头绪。代码如下:

include "../common/Utils.hpp"

int main(int argc, char* argv[])
{
//初始化
TYInitLib();

// 打开设备  
// 用设备ID打开设备,同时构建此设备的设备管理器。  
TY_DEV_HANDLE hDevice;  
TYOpenDevice("207000000866", &hDevice);  

// 使能组件  
// 按位或上组件结构体中的值,即可打开设备。  
TYEnableComponents(hDevice, TY_COMPONENT_RGB_CAM | TY_COMPONENT_DEPTH_CAM | TY_COMPONENT_IR_CAM_LEFT | TY_COMPONENT_IR_CAM_RIGHT);  

// 取得帧缓存大小。  
// 说一下这一步的目的,由于打开不同组件(打开哪些组件),以及不同组件参数设定(分辨率)的原因,每一帧数据的大小是不固定的,  
// 所以要用此函数计算一下当前设备以及当前设定下,一帧数据出来,需要多大的缓存buffer。  
// 因为后面需要压入buffer队列进行数据读取,所以要保证buffer的大小能否装下一帧数据。  
int32_t frameSize;  
TYGetFrameBufferSize(hDevice, &frameSize);  

// 驱动内部维护一个queue,用户往队列中enqueue空的buffer,  
// 设备用每一帧的framedata去填充这个空的buffer,填充后,将此buffer弹出队列(dequeue),返回给用户使用。  
// 这几个buffer是循环使用的,弹出被用户取出数据后,又会回到队列尾部。理论上将,只需要两个buffer即可循环使用。  
int frameBuffer_number = 3;  
char* frameBuffer[frameBuffer_number];  
for (int i = 0; i < frameBuffer_number; ++i)  
{  
    frameBuffer[i] = new char[frameSize];  
    TYEnqueueBuffer(hDevice, frameBuffer[i], frameSize);  
}  

//开始拍摄  
TYStartCapture(hDevice);  

//取景后不断有帧输出,需要循环取得帧数据,并进行解析输出。  
TY_FRAME_DATA frame;  
cv::Mat depth, irl, irr, color;  
while(1)  
{  
    // 取得帧  
    TYFetchFrame(hDevice, &frame, -1);  

    // 这句为整个程序的核心,解析得到的帧,解析为cv::Mat类型的图像,跟OpenCV对接后即可进行后续的处理。 defined in Utils.hpp line36  
    parseFrame(frame, &depth, &irl, &irr, &color, 0);  

    //图像显示  
    cv::imshow("Depth", depth);  
    cv::imshow("LeftIR", irl);  
    cv::imshow("RightIR", irr);  
    cv::imshow("Color", color);  

    //检测  
    if (cv::waitKey(1) == 'q') { break; }  

    // 这里就是申请的buffer循环使用的根本,每次buffer被dequeue用户取得帧后,在这个帧处理函数中,最后又把当前的buffer压入队列中,循环使用,  
    // 由于队列特性,队首出列,队尾入列,所以会有循环使用的样子。  
    TYEnqueueBuffer(hDevice, frame.userBuffer,http://www.appsaa.com  , frame.bufferSize);  
}  

//停止拍摄。  
TYStopCapture(hDevice);  
//关闭设备。  
TYCloseDevice(hDevice);  
//反初始化,注销API。  
TYDeinitLib();  
//delete释放内存。  
for (int j = 0; j < frameBuffer_number; ++j)  
{  
    delete frameBuffer[j];  
}  

return 0;  

}

收起阅读 »

一行代码搞定数据库操作

本地数据库

ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库。你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作。ThinkJD会自动管理数据库连接,使用完毕或程序异常都会关闭连接以免造成内存溢出。

//数据库配置(只需调用一次)
D.setDbConfig("jdbc:mysql://127.0.0.1:3306/DbName?characterEncoding=UTF-8","root","root");

//JavaBean模式,自动获取表名、主键、自增属性、字段名和数据
User user = new User();
user.setAge(10);
user.setName("Hello");
user.setSex(true);
//插入数据
long id=D.M(user).add();
//查询数据
user=D.M(User.class).find(id);
//更新数据
user.setSex(false);
D.M(user).field("sex").save();//不指定字段名默认更新JavaBean的所有非空属性
//删除数据
D.M(user).delete();
//D.M(User.class).delete(id);

//Table模式,手动指定表名、主键、自增属性、字段名和数据
//插入数据
long id=D.M("user").field("name,weight").data("Tom",60).add();
//更新数据
D.M("user").field("name,weight").data("Tom",100).where("id=?",id).save();
//查询数据
user=D.M(User.class).find(id);
//删除数据
D.M("user").delete(id);
//数据库配置(只需调用一次)
D.setDbConfig("jdbc:mysql://127.0.0.1:3306/DbName?characterEncoding=UTF-8","root","root");

//JavaBean模式,自动获取表名、主键、自增属性、字段名和数据
User user = new User();
user.setAge(10);
user.setName("Hello");
user.setSex(true);
//插入数据
long id=D.M(user).add();
//查询数据
user=D.M(User.class).find(id);
//更新数据
user.setSex(false);
D.M(user).field("sex").save();//不指定字段名默认更新JavaBean的所有非空属性
//删除数据
D.M(user).delete();
//D.M(User.class).delete(id);

//Table模式,手动指定表名、主键、自增属性、字段名和数据
//插入数据
long id=D.M("user").field("name,weight").data("Tom",60).add();
//更新数据
D.M("user").field("name,weight").data("Tom",100).where("id=?",id).save();
//查询数据
user=D.M(User.class).find(id);
//删除数据
D.M("user").delete(id);
项目主页 https://gitee.com/Leytton/ThinkJD (码云) https://github.com/Leytton/ThinkJD (Github)

测试项目 https://github.com/Leytton/ThinkJD_Demo

继续阅读 »

ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库。你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作。ThinkJD会自动管理数据库连接,使用完毕或程序异常都会关闭连接以免造成内存溢出。

//数据库配置(只需调用一次)
D.setDbConfig("jdbc:mysql://127.0.0.1:3306/DbName?characterEncoding=UTF-8","root","root");

//JavaBean模式,自动获取表名、主键、自增属性、字段名和数据
User user = new User();
user.setAge(10);
user.setName("Hello");
user.setSex(true);
//插入数据
long id=D.M(user).add();
//查询数据
user=D.M(User.class).find(id);
//更新数据
user.setSex(false);
D.M(user).field("sex").save();//不指定字段名默认更新JavaBean的所有非空属性
//删除数据
D.M(user).delete();
//D.M(User.class).delete(id);

//Table模式,手动指定表名、主键、自增属性、字段名和数据
//插入数据
long id=D.M("user").field("name,weight").data("Tom",60).add();
//更新数据
D.M("user").field("name,weight").data("Tom",100).where("id=?",id).save();
//查询数据
user=D.M(User.class).find(id);
//删除数据
D.M("user").delete(id);
//数据库配置(只需调用一次)
D.setDbConfig("jdbc:mysql://127.0.0.1:3306/DbName?characterEncoding=UTF-8","root","root");

//JavaBean模式,自动获取表名、主键、自增属性、字段名和数据
User user = new User();
user.setAge(10);
user.setName("Hello");
user.setSex(true);
//插入数据
long id=D.M(user).add();
//查询数据
user=D.M(User.class).find(id);
//更新数据
user.setSex(false);
D.M(user).field("sex").save();//不指定字段名默认更新JavaBean的所有非空属性
//删除数据
D.M(user).delete();
//D.M(User.class).delete(id);

//Table模式,手动指定表名、主键、自增属性、字段名和数据
//插入数据
long id=D.M("user").field("name,weight").data("Tom",60).add();
//更新数据
D.M("user").field("name,weight").data("Tom",100).where("id=?",id).save();
//查询数据
user=D.M(User.class).find(id);
//删除数据
D.M("user").delete(id);
项目主页 https://gitee.com/Leytton/ThinkJD (码云) https://github.com/Leytton/ThinkJD (Github)

测试项目 https://github.com/Leytton/ThinkJD_Demo

收起阅读 »

MUI如何安卓离线打包,在Android Studio创建Hello World离线打包工程

App离线打包

在离线打包中,离线打包过xcode的倒没啥多大问题,就输安卓那边问题比较多,打包了两天我就分享一下我的方法吧,因为eclipse中已经不再更新了,所以我现在的例子就是用Android Studio,环境我就不提供搭建了,自己上官网下载“死丢丢”吧。

1 创建Android原生工程
首先创建一个空的Android Studio工程
打开AndroidStudio点击File->New->New Project

然后一路点击“next”到下面这个页面点击“finish”即可

下面是我从官网离线打包中安卓sdk下载的资源

其中的HBuilder-Integrate-AS是属于官网的例子,SDK是属于离线所需要的各种sdk

现在找到sdk里面有个libs里面的包,把它复制到所新建的AS项目中libs去

假如有需要其他模块包的后需要选中libs目录里的库文件,鼠标右键打开菜单,选择“Add As Library...”将填加到工程内的jar文件链接到工程里

这边没有需要太多权限东西所以只复制

lib.5plus.base-release.aar


复制完成之后在其下的build.gradle中声明引用,然后同步资源

sourceSets {  
    main {  
        jniLibs.srcDirs = ['libs']  
    }  
}  

repositories {  
    flatDir {  
        dirs 'libs'  
    }  
}  

compile(name: 'lib.5plus.base-release', ext: 'aar')

接下来得复制我们的资源项目进入我们的AS项目中去了

添加资源到工程

在main目录上右键打开菜单,点击“Show in Explorer”打开文件所在的目录,把sdk里面的assets整个复制进去项目里面中去

这里我就不一一解说里面的内容了,想知道的同学可以在下方评论。

添加Web应用资源到工程
在assets目录下创建apps/[appid]/www目录,将web应用拷贝到www目录下,【APPID】为Web应用mainfest.json文件id节点的内容。

注意:应用存放的目录是有层级的,也就是apps下的【appid】的www下文件形式,目录千万不要命名成apps.[appid].www不要被as的表现迷惑,新建的目录类型为Android resource directory

接着我们来编辑AndroidManifest的文件

打开该文件,

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />  
</intent-filter>  

</activity>
修改成:
<activity android:name="io.dcloud.PandoraEntry">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />  
</intent-filter>  

</activity>

最后一步,修改control指引,回到assets中去找到data目录,修改dcloud_conntrol.xml中的appid成为我们的【appid】

到这里我们可以运行我们helloworld项目了,简单的离线打包完成,具体我们要根据我们项目中所要的资源包来导入jar,以及添加所对应的权限文件。我们也可以根据我们项目修改对应的appicon和启动页。

继续阅读 »

在离线打包中,离线打包过xcode的倒没啥多大问题,就输安卓那边问题比较多,打包了两天我就分享一下我的方法吧,因为eclipse中已经不再更新了,所以我现在的例子就是用Android Studio,环境我就不提供搭建了,自己上官网下载“死丢丢”吧。

1 创建Android原生工程
首先创建一个空的Android Studio工程
打开AndroidStudio点击File->New->New Project

然后一路点击“next”到下面这个页面点击“finish”即可

下面是我从官网离线打包中安卓sdk下载的资源

其中的HBuilder-Integrate-AS是属于官网的例子,SDK是属于离线所需要的各种sdk

现在找到sdk里面有个libs里面的包,把它复制到所新建的AS项目中libs去

假如有需要其他模块包的后需要选中libs目录里的库文件,鼠标右键打开菜单,选择“Add As Library...”将填加到工程内的jar文件链接到工程里

这边没有需要太多权限东西所以只复制

lib.5plus.base-release.aar


复制完成之后在其下的build.gradle中声明引用,然后同步资源

sourceSets {  
    main {  
        jniLibs.srcDirs = ['libs']  
    }  
}  

repositories {  
    flatDir {  
        dirs 'libs'  
    }  
}  

compile(name: 'lib.5plus.base-release', ext: 'aar')

接下来得复制我们的资源项目进入我们的AS项目中去了

添加资源到工程

在main目录上右键打开菜单,点击“Show in Explorer”打开文件所在的目录,把sdk里面的assets整个复制进去项目里面中去

这里我就不一一解说里面的内容了,想知道的同学可以在下方评论。

添加Web应用资源到工程
在assets目录下创建apps/[appid]/www目录,将web应用拷贝到www目录下,【APPID】为Web应用mainfest.json文件id节点的内容。

注意:应用存放的目录是有层级的,也就是apps下的【appid】的www下文件形式,目录千万不要命名成apps.[appid].www不要被as的表现迷惑,新建的目录类型为Android resource directory

接着我们来编辑AndroidManifest的文件

打开该文件,

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />  
</intent-filter>  

</activity>
修改成:
<activity android:name="io.dcloud.PandoraEntry">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />  
</intent-filter>  

</activity>

最后一步,修改control指引,回到assets中去找到data目录,修改dcloud_conntrol.xml中的appid成为我们的【appid】

到这里我们可以运行我们helloworld项目了,简单的离线打包完成,具体我们要根据我们项目中所要的资源包来导入jar,以及添加所对应的权限文件。我们也可以根据我们项目修改对应的appicon和启动页。

收起阅读 »

getBrightness无法获取自动亮度下的亮度值

HTML5+ mui

我想实现一个页面可以调节亮度,但是关闭当前页面后亮度还原为系统默认亮度;//

然后发现如果系统亮度如果是手动,getBrightness可以获取到系统的亮度值;
如果是把系统设置为自动亮度,getBrightness只会获取到上一次手动设置亮度的值;
测试机三星S9+,系统安卓8.0,

    var beforeBrights = '';  
            document.addEventListener('plusready',function(){  
                 beforeBrights = plus.screen.getBrightness();  
                                alert(beforeBrights);  
            },false)

不知道是bug问题还是本来就无法获取系统自动亮度状态下的亮度值

继续阅读 »

我想实现一个页面可以调节亮度,但是关闭当前页面后亮度还原为系统默认亮度;//

然后发现如果系统亮度如果是手动,getBrightness可以获取到系统的亮度值;
如果是把系统设置为自动亮度,getBrightness只会获取到上一次手动设置亮度的值;
测试机三星S9+,系统安卓8.0,

    var beforeBrights = '';  
            document.addEventListener('plusready',function(){  
                 beforeBrights = plus.screen.getBrightness();  
                                alert(beforeBrights);  
            },false)

不知道是bug问题还是本来就无法获取系统自动亮度状态下的亮度值

收起阅读 »

Maven打包都有哪些方式,较为简单是什么

  Maven可以使用mvn package指令对项目进行打包,如果使用Java -jar xxx.jar执行运行jar文件,会出现"no main manifest attribute, in xxx.jar"(没有设置Main-Class)、ClassNotFoundException(找不到依赖包)等错误。

  要想jar包能直接通过java -jar xxx.jar运行,需要满足:

  1、在jar包中的META-INF/MANIFEST.MF中指定Main-Class,这样才能确定程序的入口在哪里;

  2、要能加载到依赖包。

  使用Maven有以下几种方法可以生成能直接运行的jar包,可以根据需要选择一种合适的方法。

  使用maven-jar-plugin和maven-dependency-plugin插件打包

  在pom.xml中配置:

  maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,com.xxg.Main指定MANIFEST.MF中的Main-Class,true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。本文由专业的app开发报价燚轩科技整理发布。

继续阅读 »

  Maven可以使用mvn package指令对项目进行打包,如果使用Java -jar xxx.jar执行运行jar文件,会出现"no main manifest attribute, in xxx.jar"(没有设置Main-Class)、ClassNotFoundException(找不到依赖包)等错误。

  要想jar包能直接通过java -jar xxx.jar运行,需要满足:

  1、在jar包中的META-INF/MANIFEST.MF中指定Main-Class,这样才能确定程序的入口在哪里;

  2、要能加载到依赖包。

  使用Maven有以下几种方法可以生成能直接运行的jar包,可以根据需要选择一种合适的方法。

  使用maven-jar-plugin和maven-dependency-plugin插件打包

  在pom.xml中配置:

  maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,com.xxg.Main指定MANIFEST.MF中的Main-Class,true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。本文由专业的app开发报价燚轩科技整理发布。

收起阅读 »

有问必答,小问题无偿 大问题有偿

外包

有问必答,小问题简单问题免费解决 大问题复杂问题有偿解决(望理解) 承接开发各种第三方插件 app 项目 及 离线打包指导等等。 需要联系 qq : 37894663

有问必答,小问题简单问题免费解决 大问题复杂问题有偿解决(望理解) 承接开发各种第三方插件 app 项目 及 离线打包指导等等。 需要联系 qq : 37894663

左侧竖条导航栏点击出现效果的实现

侧滑导航

  大部分的网站导航栏都是在网页的顶端,这类导航栏看起来非常一般,而有些在左侧竖着显示的导航栏就比较好看一些了,但是今天为大家介绍的是左侧竖条导航栏实现点击出现的效果,也就是刚开始只显示导航,不显示分类栏,而点击导航就可以显示分类栏了,下面一起来看下源代码的实现吧。
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/jquery.min.js"></script>
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js">
</script>
<style>
html,
body {
padding: 0;
margin: 0;
}

    main {  
        width: 100%;  
    }  

    .main {  
        width: 100%;  
        min-height: 100vh;  
        background-color: #ccc;  
    }  

    .x_left {  
        position: fixed;  
        left: 0;  
        top: 100px;  
        width: 100px;  
        /* border: 1px solid red; */  
    }  

    .x_left_title {  
        padding: 10px 0;  
        margin: 2px 0;  
        width: 50px;  
        background-color: white;  
        box-shadow:  0 0 5px 1px rgb(99, 99, 99);  
        display: flex;  
        justify-content: center;  
        align-items: center;  
        position: relative;  
    }  

    .x_left_main {  
        display: flex;  
        flex-flow: column;  
        /* border: 1px solid red; */  
        position: relative;  
        width: 0;  
    }  

    .x_left_main span {  
        padding: 10px 0;  
        margin: 3px 0;  
        width: 100px;  
        background-color: white;  
        box-shadow:  0 0 5px 1px rgb(122, 147, 160);  
        display: flex;  
        justify-content: center;  
        align-items: center;  
        position: relative;  
        left: -100px;  
    }  
</style>  

</head>

<body>
<main>
<div class="main">
<div class="x_left">
<div class="x_left_title">
导航
</div>
<div class="x_left_main">
<span>aaa11111111</span>
<span>aaa22222222</span>
<span>aaa33333333</span>
<span>aaa44444444</span>
<span>aaa55555555</span>
<span>aaa66666666</span>
<span>aaa77777777</span>
<span>aaa88888888</span>
<span>aaa99999999</span>
</div>
</div>
</div>
</main>
<script>
var show = "";
var hidden = ""
var hidden_top = "";
var hidden_top_num = "";
var hidden_bottom_num = "";
var length = $(".x_left_main span").length;
var num = 0;
var whether = 99;
var qsb = 99

    $(".x_left_title").click(function(){  
        if(whether==99&&qsb==99){  
            qsb = 1  
            $(this).stop().animate({width:"100px"},1000)  
            var num = 0;  
            $(".x_left_main span").eq(num).stop().animate({  
                left:"0"  
            },150)  
            show = setInterval(function(){  
                if(num!=length){  
                    num++  
                    $(".x_left_main span").eq(num).stop().animate({  
                        left:"0"  
                    },150)  
                }else{  
                    clearInterval(show)  
                    whether = 1  
                    qsb = 99  
                }  
            },150)  
        }else{  
            if(qsb==99&&whether==1){  
                qsb = 1  
                $(this).stop().animate({width:"50px"},1000)  
                var num = 0;  
                $(".x_left_main span").eq(num).stop().animate({  
                    left:"-100px"  
                },150)  
                show = setInterval(function(){  
                    if(num!=length){  
                        num++  
                        $(".x_left_main span").eq(num).stop().animate({  
                            left:"-100px"  
                        },150)  
                    }else{  
                        clearInterval(show)  
                        whether = 99  
                        qsb = 99  
                    }  
                },150)  
            }  

        }  

    })  
    $(".x_left_main span").each(function(i){  
        $(this).click(function(){  
            $(".x_left_title").stop().animate({width:"50px"},1000)  
            hidden_top_num = i  
            hidden_bottom_num = i  
            $(this).stop().animate({  
                left:"-100px"  
            })  
            hidden_top = setInterval(function(){  
                if(hidden_top_num!=0){  
                    hidden_top_num--  
                    $(".x_left_main span").eq(hidden_top_num).stop().animate({  
                        left:"-100px"  
                    })  
                }else{  
                    clearInterval(hidden_top)  
                    whether = 99  
                    qsb = 99  
                }  
            },150)  
            hidden_bottom = setInterval(function(){  
                if(hidden_bottom_num!=length){  
                    hidden_bottom_num++  
                    $(".x_left_main span").eq(hidden_bottom_num).stop().animate({  
                        left:"-100px"  
                    })  
                }else{  
                    clearInterval(hidden_bottom)  
                    whether = 99  
                    qsb = 99  
                }  
            },150)  
        })  
    })  

</script>  

</body>

</html>

  看到这里详细大家已经可以预测出实际效果了吧,这种效果是不是要比传统的导航栏更加具有吸引力呢?那么大家也赶紧动手尝试一下吧,如果还存在不理解的地方,可以留言咨询哦。

  本文由专业的app开发报价燚轩科技整理发布,如需转载请注明出处!

继续阅读 »

  大部分的网站导航栏都是在网页的顶端,这类导航栏看起来非常一般,而有些在左侧竖着显示的导航栏就比较好看一些了,但是今天为大家介绍的是左侧竖条导航栏实现点击出现的效果,也就是刚开始只显示导航,不显示分类栏,而点击导航就可以显示分类栏了,下面一起来看下源代码的实现吧。
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/jquery.min.js"></script>
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js">
</script>
<style>
html,
body {
padding: 0;
margin: 0;
}

    main {  
        width: 100%;  
    }  

    .main {  
        width: 100%;  
        min-height: 100vh;  
        background-color: #ccc;  
    }  

    .x_left {  
        position: fixed;  
        left: 0;  
        top: 100px;  
        width: 100px;  
        /* border: 1px solid red; */  
    }  

    .x_left_title {  
        padding: 10px 0;  
        margin: 2px 0;  
        width: 50px;  
        background-color: white;  
        box-shadow:  0 0 5px 1px rgb(99, 99, 99);  
        display: flex;  
        justify-content: center;  
        align-items: center;  
        position: relative;  
    }  

    .x_left_main {  
        display: flex;  
        flex-flow: column;  
        /* border: 1px solid red; */  
        position: relative;  
        width: 0;  
    }  

    .x_left_main span {  
        padding: 10px 0;  
        margin: 3px 0;  
        width: 100px;  
        background-color: white;  
        box-shadow:  0 0 5px 1px rgb(122, 147, 160);  
        display: flex;  
        justify-content: center;  
        align-items: center;  
        position: relative;  
        left: -100px;  
    }  
</style>  

</head>

<body>
<main>
<div class="main">
<div class="x_left">
<div class="x_left_title">
导航
</div>
<div class="x_left_main">
<span>aaa11111111</span>
<span>aaa22222222</span>
<span>aaa33333333</span>
<span>aaa44444444</span>
<span>aaa55555555</span>
<span>aaa66666666</span>
<span>aaa77777777</span>
<span>aaa88888888</span>
<span>aaa99999999</span>
</div>
</div>
</div>
</main>
<script>
var show = "";
var hidden = ""
var hidden_top = "";
var hidden_top_num = "";
var hidden_bottom_num = "";
var length = $(".x_left_main span").length;
var num = 0;
var whether = 99;
var qsb = 99

    $(".x_left_title").click(function(){  
        if(whether==99&&qsb==99){  
            qsb = 1  
            $(this).stop().animate({width:"100px"},1000)  
            var num = 0;  
            $(".x_left_main span").eq(num).stop().animate({  
                left:"0"  
            },150)  
            show = setInterval(function(){  
                if(num!=length){  
                    num++  
                    $(".x_left_main span").eq(num).stop().animate({  
                        left:"0"  
                    },150)  
                }else{  
                    clearInterval(show)  
                    whether = 1  
                    qsb = 99  
                }  
            },150)  
        }else{  
            if(qsb==99&&whether==1){  
                qsb = 1  
                $(this).stop().animate({width:"50px"},1000)  
                var num = 0;  
                $(".x_left_main span").eq(num).stop().animate({  
                    left:"-100px"  
                },150)  
                show = setInterval(function(){  
                    if(num!=length){  
                        num++  
                        $(".x_left_main span").eq(num).stop().animate({  
                            left:"-100px"  
                        },150)  
                    }else{  
                        clearInterval(show)  
                        whether = 99  
                        qsb = 99  
                    }  
                },150)  
            }  

        }  

    })  
    $(".x_left_main span").each(function(i){  
        $(this).click(function(){  
            $(".x_left_title").stop().animate({width:"50px"},1000)  
            hidden_top_num = i  
            hidden_bottom_num = i  
            $(this).stop().animate({  
                left:"-100px"  
            })  
            hidden_top = setInterval(function(){  
                if(hidden_top_num!=0){  
                    hidden_top_num--  
                    $(".x_left_main span").eq(hidden_top_num).stop().animate({  
                        left:"-100px"  
                    })  
                }else{  
                    clearInterval(hidden_top)  
                    whether = 99  
                    qsb = 99  
                }  
            },150)  
            hidden_bottom = setInterval(function(){  
                if(hidden_bottom_num!=length){  
                    hidden_bottom_num++  
                    $(".x_left_main span").eq(hidden_bottom_num).stop().animate({  
                        left:"-100px"  
                    })  
                }else{  
                    clearInterval(hidden_bottom)  
                    whether = 99  
                    qsb = 99  
                }  
            },150)  
        })  
    })  

</script>  

</body>

</html>

  看到这里详细大家已经可以预测出实际效果了吧,这种效果是不是要比传统的导航栏更加具有吸引力呢?那么大家也赶紧动手尝试一下吧,如果还存在不理解的地方,可以留言咨询哦。

  本文由专业的app开发报价燚轩科技整理发布,如需转载请注明出处!

收起阅读 »

中国技术界小奇迹:HBuilder开发者突破200万

DCloud

更新:目前HBuilder的开发者数量已经突破600万,以下为历史文章


截止2018年5月2日,国产IDE--HBuilder开发者数量正式突破200万
在众多开发者的支持下,DCloud公司创造了一个小奇迹,取得中国开发者服务团队历史上未曾达到的成绩。
目前HBuilder与sublime、webstorm、vscode并驾齐驱为前端界四大开发工具,
下图是四大工具在第一季度的百度指数对比,可以看到HBuilder仍然在快速增长。

百度指数链接:http://zhishu.baidu.com/?tpl=trend&type=0&area=0&time=13&word=hbuilder%2Csublime%2Cwebstorm%2Cvscode

开发工具一直是歪果仁称霸的地方,还从来没有国人成功过。
HBuilder在列强环绕的局面里立住了脚,过程非常艰辛。

  • 在技术难度方面:
    全球掌握代码分析提示技术的团队并不多,DCloud成为其中之一。

  • 在商业难度方面:
    外国竞品在国外销售许可,赚取足够的利润,或由IT巨头资助开源项目。
    而在中国,销售软件许可走不通,投入足够多心血做免费开发工具,需要一个团队有极其执著的梦想。

在技术和商业的多重压力下,我们能取得今天的成绩,确属奇迹。
在此也感谢你的支持和包容,没有你对HBuilder的支持,我们没有信心走到今天。

我们对过去的成绩心存敬畏,但对未来心怀更大梦想。
下一代开发工具HBuilderX已经推出,我们期待这个全新的产品能够超越国外竞品,并成功出海,让外国人用用中国人做的开发工具!

上一代HBuilder由于Eclipse架构问题,还是偏重。
全新的HBuilderX是基于C++架构的:

  • 轻巧 (安装包十余M)
  • 极速(1秒启动),大文档打开速度更超过其他优秀编辑器
  • 强大,HBuilder惯以强大的代码提示著称
    对了,HBuilderX还是体验远超竞品的markdown编辑器。
    HBuilderX的主页:

欢迎你前来体验,并给我们反馈意见,帮助我们完善这个新产品。
一起共创下一个奇迹!

DCloud作为一个为开发者而生的公司。还有更多服务提供给开发者。

  • 1.手机跨屏开发引擎
    DCloud的mui,与react native并列成为最受欢迎的跨平台开发框架,遥遥领先于其他框架。
    下图是主流跨平台引擎的近一年百度指数对比:

    百度指数链接如下:http://zhishu.baidu.com/?tpl=trend&type=0&area=0&time=13&word=mui%2Ccordova%2Creact+native%2Cweex

当然mui也有下一代产品了,叫Uni-App,具备了强大的纯原生渲染引擎,大幅提升了App的性能体验。
并且下一代产品,不止是要跨iOS和Android,还要跨微信、支付宝、百度的小程序、手机厂商快应用,以及输出到浏览器。
移动互联网的下半场,应用的形态不止是iOS和Android的App,更多平台需要支持,我们相信Uni-App会取得比mui更大的成功。
详见

  • DCloud除了帮助开发者做出App,还要帮助开发者运营好App
    开发者要做成一个App,不止考虑技术。DCloud为其他关键环节也提供了免费工具,降低App的成功门槛。让天下没有难做的App!
    D-AD广告联盟,帮助开发者变现赚钱
    D-Portal应用发布平台,帮助开发者获取用户
    Uni-Stat统计平台,帮助开发者提供运营分析、收集错误和用户反馈,改善留存

DCloud的各项运营服务都与开发工具无缝结合,应用打包时打个勾就能开通广告。

  • 2.支持创新、抵制侵权
    APICloud公司之前破解抄袭HBuilder源码,并抵赖和欺瞒公众。目前法院已经正式宣判APICloud赔偿DCloud损失并公开道歉,为保护中国自主创新知识产权树立了一个标杆案例。详见
    在中国做技术创新本也不易,保护中国的知识产权环境,人人有责。
    希望大家抵制侵权、破解。
    用正版、用国产,我自豪!

  • 3.国产的进步
    不管是在制造业还是在IT技术领域,“外国的月亮比较圆”的帽子正在被一批批有激情有才华的人摘掉。vue框架、HBuilder、微信小程序,都取得了成功。接下来DCloud团队也会加强对vue、小程序的支持,打造国产闭环开发体验。
     
    不管是免费的开发工具、还是运营工具,DCloud都致力于帮助开发者成功。
    开发者的成功是对我们最大的鼓励。
    未来仍然任重道远,我们也仍有很多不足,但我们相信在各位共同的支持下,未来会越来越好,下一个奇迹在等待我们!

继续阅读 »

更新:目前HBuilder的开发者数量已经突破600万,以下为历史文章


截止2018年5月2日,国产IDE--HBuilder开发者数量正式突破200万
在众多开发者的支持下,DCloud公司创造了一个小奇迹,取得中国开发者服务团队历史上未曾达到的成绩。
目前HBuilder与sublime、webstorm、vscode并驾齐驱为前端界四大开发工具,
下图是四大工具在第一季度的百度指数对比,可以看到HBuilder仍然在快速增长。

百度指数链接:http://zhishu.baidu.com/?tpl=trend&type=0&area=0&time=13&word=hbuilder%2Csublime%2Cwebstorm%2Cvscode

开发工具一直是歪果仁称霸的地方,还从来没有国人成功过。
HBuilder在列强环绕的局面里立住了脚,过程非常艰辛。

  • 在技术难度方面:
    全球掌握代码分析提示技术的团队并不多,DCloud成为其中之一。

  • 在商业难度方面:
    外国竞品在国外销售许可,赚取足够的利润,或由IT巨头资助开源项目。
    而在中国,销售软件许可走不通,投入足够多心血做免费开发工具,需要一个团队有极其执著的梦想。

在技术和商业的多重压力下,我们能取得今天的成绩,确属奇迹。
在此也感谢你的支持和包容,没有你对HBuilder的支持,我们没有信心走到今天。

我们对过去的成绩心存敬畏,但对未来心怀更大梦想。
下一代开发工具HBuilderX已经推出,我们期待这个全新的产品能够超越国外竞品,并成功出海,让外国人用用中国人做的开发工具!

上一代HBuilder由于Eclipse架构问题,还是偏重。
全新的HBuilderX是基于C++架构的:

  • 轻巧 (安装包十余M)
  • 极速(1秒启动),大文档打开速度更超过其他优秀编辑器
  • 强大,HBuilder惯以强大的代码提示著称
    对了,HBuilderX还是体验远超竞品的markdown编辑器。
    HBuilderX的主页:

欢迎你前来体验,并给我们反馈意见,帮助我们完善这个新产品。
一起共创下一个奇迹!

DCloud作为一个为开发者而生的公司。还有更多服务提供给开发者。

  • 1.手机跨屏开发引擎
    DCloud的mui,与react native并列成为最受欢迎的跨平台开发框架,遥遥领先于其他框架。
    下图是主流跨平台引擎的近一年百度指数对比:

    百度指数链接如下:http://zhishu.baidu.com/?tpl=trend&type=0&area=0&time=13&word=mui%2Ccordova%2Creact+native%2Cweex

当然mui也有下一代产品了,叫Uni-App,具备了强大的纯原生渲染引擎,大幅提升了App的性能体验。
并且下一代产品,不止是要跨iOS和Android,还要跨微信、支付宝、百度的小程序、手机厂商快应用,以及输出到浏览器。
移动互联网的下半场,应用的形态不止是iOS和Android的App,更多平台需要支持,我们相信Uni-App会取得比mui更大的成功。
详见

  • DCloud除了帮助开发者做出App,还要帮助开发者运营好App
    开发者要做成一个App,不止考虑技术。DCloud为其他关键环节也提供了免费工具,降低App的成功门槛。让天下没有难做的App!
    D-AD广告联盟,帮助开发者变现赚钱
    D-Portal应用发布平台,帮助开发者获取用户
    Uni-Stat统计平台,帮助开发者提供运营分析、收集错误和用户反馈,改善留存

DCloud的各项运营服务都与开发工具无缝结合,应用打包时打个勾就能开通广告。

  • 2.支持创新、抵制侵权
    APICloud公司之前破解抄袭HBuilder源码,并抵赖和欺瞒公众。目前法院已经正式宣判APICloud赔偿DCloud损失并公开道歉,为保护中国自主创新知识产权树立了一个标杆案例。详见
    在中国做技术创新本也不易,保护中国的知识产权环境,人人有责。
    希望大家抵制侵权、破解。
    用正版、用国产,我自豪!

  • 3.国产的进步
    不管是在制造业还是在IT技术领域,“外国的月亮比较圆”的帽子正在被一批批有激情有才华的人摘掉。vue框架、HBuilder、微信小程序,都取得了成功。接下来DCloud团队也会加强对vue、小程序的支持,打造国产闭环开发体验。
     
    不管是免费的开发工具、还是运营工具,DCloud都致力于帮助开发者成功。
    开发者的成功是对我们最大的鼓励。
    未来仍然任重道远,我们也仍有很多不足,但我们相信在各位共同的支持下,未来会越来越好,下一个奇迹在等待我们!

收起阅读 »