Commit f1a978d3 authored by lihaochen's avatar lihaochen

🎉 initial commit

parents
node_modules
dist/
.DS_Store
\ No newline at end of file
node_modules
docs/.vuepress/dist
<div align="center">
<h1>快应用开发者文档</h1>
</div>
<div align="center">
<a href="https://github.com/prettier/prettier">
<img src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square" alt="prettier">
</a>
<a href="https://nodejs.org/en/">
<img src="https://img.shields.io/badge/node-%3E=%208.0.0-green.svg" alt="node version">
</a>
</div>
## 目标与理念
此为基于 [VuePress](https://vuepress.vuejs.org/zh/) 所搭建的「快应用」开发者文档。
## 先决条件
[Node.js](https://nodejs.org/en/) (>= 8.*), Npm 版本 5+ (更推荐使用 [Yarn](https://yarnpkg.com/zh-Hans/docs/install#mac-stable)).
## 如何使用
```bash
# 统一安装依赖
yarn
yarn start
```
## 如何提交
```bash
# 安装
npm i -g gitmoji-cli
# 使用
gitmoji -i
git add .
git commit
```
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "vuepress",
"short_name": "奇美拉文档",
"start_url": ".",
"display": "standalone",
"background_color": "#fff",
"theme_color": "#3eaf7c",
"icons": [
{
"src": "/quickapp.ico",
"sizes": "120x120",
"type": "image/png"
}
]
}
$accentColor = #4761f6
\ No newline at end of file
The MIT License (MIT)
Copyright (c) 2018-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<template>
<form
id="search-form"
class="algolia-search-wrapper search-box"
role="search"
>
<input
id="algolia-search-input"
class="search-query"
:placeholder="placeholder"
>
</form>
</template>
<script>
export default {
props: ['options'],
data () {
return {
placeholder: undefined
}
},
mounted () {
this.initialize(this.options, this.$lang)
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
},
methods: {
initialize (userOptions, lang) {
Promise.all([
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'),
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
]).then(([docsearch]) => {
docsearch = docsearch.default
const { algoliaOptions = {}} = userOptions
docsearch(Object.assign(
{},
userOptions,
{
inputSelector: '#algolia-search-input',
// #697 Make docsearch work well at i18n mode.
algoliaOptions: Object.assign({
'facetFilters': [`lang:${lang}`].concat(algoliaOptions.facetFilters || [])
}, algoliaOptions),
handleSelected: (input, event, suggestion) => {
const { pathname, hash } = new URL(suggestion.url)
this.$router.push(`${pathname}${hash}`)
}
}
))
})
},
update (options, lang) {
this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
this.initialize(options, lang)
}
},
watch: {
$lang (newValue) {
this.update(this.options, newValue)
},
options (newValue) {
this.update(newValue, this.$lang)
}
}
}
</script>
<style lang="stylus">
.algolia-search-wrapper
& > span
vertical-align middle
.algolia-autocomplete
line-height normal
.ds-dropdown-menu
background-color #fff
border 1px solid #999
border-radius 4px
font-size 16px
margin 6px 0 0
padding 4px
text-align left
&:before
border-color #999
[class*=ds-dataset-]
border none
padding 0
.ds-suggestions
margin-top 0
.ds-suggestion
border-bottom 1px solid $borderColor
.algolia-docsearch-suggestion--highlight
color #2c815b
.algolia-docsearch-suggestion
border-color $borderColor
padding 0
.algolia-docsearch-suggestion--category-header
padding 5px 10px
margin-top 0
background $accentColor
color #fff
font-weight 600
.algolia-docsearch-suggestion--highlight
background rgba(255, 255, 255, 0.6)
.algolia-docsearch-suggestion--wrapper
padding 0
.algolia-docsearch-suggestion--title
font-weight 600
margin-bottom 0
color $textColor
.algolia-docsearch-suggestion--subcategory-column
vertical-align top
padding 5px 7px 5px 5px
border-color $borderColor
background #f1f3f5
&:after
display none
.algolia-docsearch-suggestion--subcategory-column-text
color #555
.algolia-docsearch-footer
border-color $borderColor
.ds-cursor .algolia-docsearch-suggestion--content
background-color #e7edf3 !important
color $textColor
@media (min-width: $MQMobile)
.algolia-search-wrapper
.algolia-autocomplete
.algolia-docsearch-suggestion
.algolia-docsearch-suggestion--subcategory-column
float none
width 150px
min-width 150px
display table-cell
.algolia-docsearch-suggestion--content
float none
display table-cell
width 100%
vertical-align top
.ds-dropdown-menu
min-width 515px !important
@media (max-width: $MQMobile)
.algolia-search-wrapper
.ds-dropdown-menu
min-width calc(100vw - 4rem) !important
max-width calc(100vw - 4rem) !important
.algolia-docsearch-suggestion--wrapper
padding 5px 7px 5px 5px !important
.algolia-docsearch-suggestion--subcategory-column
padding 0 !important
background white !important
.algolia-docsearch-suggestion--subcategory-column-text:after
content " > "
font-size 10px
line-height 14.4px
display inline-block
width 5px
margin -3px 3px 0
vertical-align middle
</style>
<template>
<div
class="dropdown-wrapper"
:class="{ open }"
>
<a
class="dropdown-title"
@click="toggle"
>
<span class="title">{{ item.text }}</span>
<span
class="arrow"
:class="open ? 'down' : 'right'"
></span>
</a>
<DropdownTransition>
<ul
class="nav-dropdown"
v-show="open"
>
<li
class="dropdown-item"
:key="subItem.link || index"
v-for="(subItem, index) in item.items"
>
<h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4>
<ul
class="dropdown-subitem-wrapper"
v-if="subItem.type === 'links'"
>
<li
class="dropdown-subitem"
:key="childSubItem.link"
v-for="childSubItem in subItem.items"
>
<NavLink :item="childSubItem"/>
</li>
</ul>
<NavLink
v-else
:item="subItem"
/>
</li>
</ul>
</DropdownTransition>
</div>
</template>
<script>
import NavLink from '@theme/components/NavLink.vue'
import DropdownTransition from '@theme/components/DropdownTransition.vue'
export default {
components: { NavLink, DropdownTransition },
data () {
return {
open: false
}
},
props: {
item: {
required: true
}
},
methods: {
toggle () {
this.open = !this.open
}
}
}
</script>
<style lang="stylus">
.dropdown-wrapper
cursor pointer
.dropdown-title
display block
&:hover
border-color transparent
.arrow
vertical-align middle
margin-top -1px
margin-left 0.4rem
.nav-dropdown
.dropdown-item
color inherit
line-height 1.7rem
h4
margin 0.45rem 0 0
border-top 1px solid #eee
padding 0.45rem 1.5rem 0 1.25rem
.dropdown-subitem-wrapper
padding 0
list-style none
.dropdown-subitem
font-size 0.9em
a
display block
line-height 1.7rem
position relative
border-bottom none
font-weight 400
margin-bottom 0
padding 0 1.5rem 0 1.25rem
&:hover
color $accentColor
&.router-link-active
color $accentColor
&::after
content ""
width 0
height 0
border-left 5px solid $accentColor
border-top 3px solid transparent
border-bottom 3px solid transparent
position absolute
top calc(50% - 2px)
left 9px
&:first-child h4
margin-top 0
padding-top 0
border-top 0
@media (max-width: $MQMobile)
.dropdown-wrapper
&.open .dropdown-title
margin-bottom 0.5rem
.nav-dropdown
transition height .1s ease-out
overflow hidden
.dropdown-item
h4
border-top 0
margin-top 0
padding-top 0
h4, & > a
font-size 15px
line-height 2rem
.dropdown-subitem
font-size 14px
padding-left 1rem
@media (min-width: $MQMobile)
.dropdown-wrapper
height 1.8rem
&:hover .nav-dropdown
// override the inline style.
display block !important
.dropdown-title .arrow
// make the arrow always down at desktop
border-left 4px solid transparent
border-right 4px solid transparent
border-top 6px solid $arrowBgColor
border-bottom 0
.nav-dropdown
display none
// Avoid height shaked by clicking
height auto !important
box-sizing border-box;
max-height calc(100vh - 2.7rem)
overflow-y auto
position absolute
top 100%
right 0
background-color #fff
padding 0.6rem 0
border 1px solid #ddd
border-bottom-color #ccc
text-align left
border-radius 0.25rem
white-space nowrap
margin 0
</style>
<template>
<transition
name="dropdown"
@enter="setHeight"
@after-enter="unsetHeight"
@before-leave="setHeight"
>
<slot/>
</transition>
</template>
<script>
export default {
name: 'DropdownTransition',
methods: {
setHeight (items) {
// explicitly set height so that it can be transitioned
items.style.height = items.scrollHeight + 'px'
},
unsetHeight (items) {
items.style.height = ''
}
}
}
</script>
<style lang="stylus">
.dropdown-enter, .dropdown-leave-to
height 0 !important
</style>
<template>
<main class="home" aria-labelledby="main-title">
<div class="flex-container">
<header class="hero">
<img
v-if="data.heroImage"
src='../assets/hero.png'
:alt="data.heroAlt || 'hero'"
>
<h1 v-if="data.heroText !== null" id="main-title">{{ data.heroText || $title || 'Hello' }}</h1>
<p
class="action"
v-if="data.actionText && data.actionLink"
>
<NavLink
class="action-button"
:item="actionLink"
/>
</p>
</header>
<div id="link">
<div class="block" v-for="item in link">
<a :href= "item.url">{{item.title}}</a>
</div>
</div>
</div>
<Content class="theme-default-content custom"/>
<div
class="footer"
v-if="data.footer"
>
{{ data.footer }}
</div>
</main>
</template>
<script>
import NavLink from '@theme/components/NavLink.vue'
export default {
data : () => {
return {
link: [
{title: '教程', url: '/reference'},
{title: '框架', url: '/framework'},
{title: '组件', url: '/component'},
{title: 'API', url: '/api'}
]
}
},
components: { NavLink },
computed: {
data () {
return this.$page.frontmatter
},
actionLink () {
return {
link: this.data.actionLink,
text: this.data.actionText
}
}
}
}
</script>
<style lang="stylus">
.home
#link
text-align center
justify-content center
.block
text-align: center;
display inline-block
min-width 2.5rem
background-color #fff
border 1px solid #ebeef5
box-shadow 0 2px 12px 0 rgba(0,0,0,.1)
padding .6rem 1rem
margin .5rem 1rem
border-radius 1.5rem
height 100vh
display flex
flex-direction column
justify-content space-evenly
padding $navbarHeight 2rem 0
max-width 960px
margin 0px auto
.hero
text-align center
img
max-width: 40%
max-height 280px
display block
margin 3rem auto 1.5rem
h1
font-size 1.2rem
h1, .description, .action
margin 1.8rem auto
.description
max-width 35rem
font-size 1.6rem
line-height 1.3
color lighten($textColor, 40%)
.action-button
display inline-block
font-size 1.2rem
color #fff
background-color $accentColor
padding 0.8rem 1.6rem
border-radius 4px
transition background-color .1s ease
box-sizing border-box
border-bottom 1px solid darken($accentColor, 10%)
&:hover
background-color lighten($accentColor, 10%)
.footer
padding 2.5rem
border-top 1px solid $borderColor
text-align center
color lighten($textColor, 25%)
@media (max-width: $MQMobile)
.home
.features
flex-direction column
.feature
max-width 100%
padding 0 2.5rem
@media (max-width: $MQMobileNarrow)
.home
padding-left 1.5rem
padding-right 1.5rem
.hero
img
max-height 210px
margin 2rem auto 1.2rem
h1
font-size 1.5rem
h1, .description, .action
margin 1.2rem auto
.description
font-size 1.2rem
.action-button
font-size 1rem
padding 0.6rem 1.2rem
.feature
h2
font-size 1.25rem
</style>
<template>
<router-link
class="nav-link"
:to="link"
v-if="!isExternal(link)"
:exact="exact"
>{{ item.text }}</router-link>
<a
v-else
:href="link"
class="nav-link external"
:target="isMailto(link) || isTel(link) ? null : '_blank'"
:rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'"
>
{{ item.text }}
<OutboundLink/>
</a>
</template>
<script>
import { isExternal, isMailto, isTel, ensureExt } from '../util'
export default {
props: {
item: {
required: true
}
},
computed: {
link () {
return ensureExt(this.item.link)
},
exact () {
if (this.$site.locales) {
return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
}
return this.link === '/'
}
},
methods: {
isExternal,
isMailto,
isTel
}
}
</script>
<template>
<nav
class="nav-links"
v-if="userLinks.length || repoLink"
>
<!-- user links -->
<div
class="nav-item"
v-for="item in userLinks"
:key="item.link"
>
<DropdownLink
v-if="item.type === 'links'"
:item="item"
/>
<NavLink
v-else
:item="item"
/>
</div>
<!-- repo link -->
<a
v-if="repoLink"
:href="repoLink"
class="repo-link"
target="_blank"
rel="noopener noreferrer"
>
{{ repoLabel }}
<OutboundLink/>
</a>
</nav>
</template>
<script>
import DropdownLink from '@theme/components/DropdownLink.vue'
import { resolveNavLinkItem } from '../util'
import NavLink from '@theme/components/NavLink.vue'
export default {
components: { NavLink, DropdownLink },
computed: {
userNav () {
return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || []
},
nav () {
const { locales } = this.$site
if (locales && Object.keys(locales).length > 1) {
const currentLink = this.$page.path
const routes = this.$router.options.routes
const themeLocales = this.$site.themeConfig.locales || {}
const languageDropdown = {
text: this.$themeLocaleConfig.selectText || 'Languages',
items: Object.keys(locales).map(path => {
const locale = locales[path]
const text = themeLocales[path] && themeLocales[path].label || locale.lang
let link
// Stay on the current page
if (locale.lang === this.$lang) {
link = currentLink
} else {
// Try to stay on the same page
link = currentLink.replace(this.$localeConfig.path, path)
// fallback to homepage
if (!routes.some(route => route.path === link)) {
link = path
}
}
return { text, link }
})
}
return [...this.userNav, languageDropdown]
}
return this.userNav
},
userLinks () {
return (this.nav || []).map(link => {
return Object.assign(resolveNavLinkItem(link), {
items: (link.items || []).map(resolveNavLinkItem)
})
})
},
repoLink () {
const { repo } = this.$site.themeConfig
if (repo) {
return /^https?:/.test(repo)
? repo
: `https://github.com/${repo}`
}
},
repoLabel () {
if (!this.repoLink) return
if (this.$site.themeConfig.repoLabel) {
return this.$site.themeConfig.repoLabel
}
const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
const platforms = ['GitHub', 'GitLab', 'Bitbucket']
for (let i = 0; i < platforms.length; i++) {
const platform = platforms[i]
if (new RegExp(platform, 'i').test(repoHost)) {
return platform
}
}
return 'Source'
}
}
}
</script>
<style lang="stylus">
.nav-links
display inline-block
a
line-height 1.4rem
color inherit
&:hover, &.router-link-active
color $accentColor
.nav-item
position relative
display inline-block
margin-left 1.5rem
line-height 2rem
&:first-child
margin-left 0
.repo-link
margin-left 1.5rem
@media (max-width: $MQMobile)
.nav-links
.nav-item, .repo-link
margin-left 0
@media (min-width: $MQMobile)
.nav-links a
&:hover, &.router-link-active
color $textColor
.nav-item > a:not(.external)
&:hover, &.router-link-active
margin-bottom -2px
border-bottom 2px solid lighten($accentColor, 8%)
</style>
<template>
<header class="navbar">
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/>
<router-link
:to="$localePath"
class="home-link"
>
<img
class="logo"
src='../assets/quick-app-logo.png'
:alt="$siteTitle"
>
<span
ref="siteName"
class="site-name"
v-if="$siteTitle"
:class="{ 'can-hide': $site.themeConfig.logo }"
>{{ $siteTitle }}</span>
</router-link>
<div
class="links"
:style="linksWrapMaxWidth ? {
'max-width': linksWrapMaxWidth + 'px'
} : {}"
>
<AlgoliaSearchBox
v-if="isAlgoliaSearch"
:options="algolia"
/>
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false"/>
<NavLinks class="can-hide"/>
</div>
</header>
</template>
<script>
import AlgoliaSearchBox from '@AlgoliaSearchBox'
import SearchBox from '@SearchBox'
import SidebarButton from '@theme/components/SidebarButton.vue'
import NavLinks from '@theme/components/NavLinks.vue'
export default {
components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox },
data () {
return {
linksWrapMaxWidth: null
}
},
mounted () {
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.linksWrapMaxWidth = null
} else {
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
}
}
handleLinksWrapWidth()
window.addEventListener('resize', handleLinksWrapWidth, false)
},
computed: {
algolia () {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
},
isAlgoliaSearch () {
return this.algolia && this.algolia.apiKey && this.algolia.indexName
}
}
}
function css (el, property) {
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView
// null means not to return pseudo styles
return win.getComputedStyle(el, null)[property]
}
</script>
<style lang="stylus">
$navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 1.5rem
.navbar
padding $navbar-vertical-padding $navbar-horizontal-padding
line-height $navbarHeight - 1.4rem
a, span, img
display inline-block
.logo
height $navbarHeight - 1.4rem
min-width $navbarHeight - 1.4rem
margin-right 0.8rem
vertical-align top
.site-name
font-size 1.3rem
font-weight 600
color $textColor
position relative
.links
padding-left 1.5rem
box-sizing border-box
background-color white
white-space nowrap
font-size 0.9rem
position absolute
right $navbar-horizontal-padding
top $navbar-vertical-padding
display flex
.search-box
flex: 0 0 auto
vertical-align top
@media (max-width: $MQMobile)
.navbar
padding-left 4rem
.can-hide
display none
.links
padding-left 1.5rem
.site-name
width calc(100vw - 9.4rem)
overflow hidden
white-space nowrap
text-overflow ellipsis
</style>
<template>
<main class="page">
<slot name="top" />
<Content class="theme-default-content" />
<PageEdit />
<PageNav v-bind="{ sidebarItems }" />
<slot name="bottom" />
</main>
</template>
<script>
import PageEdit from '@theme/components/PageEdit.vue'
import PageNav from '@theme/components/PageNav.vue'
export default {
components: { PageEdit, PageNav },
props: ['sidebarItems']
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl';
.page {
padding-bottom: 2rem;
display: block;
}
</style>
<template>
<footer class="page-edit">
<div class="edit-link" v-if="editLink">
<a :href="editLink" target="_blank" rel="noopener noreferrer">{{ editLinkText }}</a>
<OutboundLink />
</div>
<div class="last-updated" v-if="lastUpdated">
<span class="prefix">{{ lastUpdatedText }}:</span>
<span class="time">{{ lastUpdated }}</span>
</div>
</footer>
</template>
<script>
import { endingSlashRE, outboundRE } from '../util'
export default {
name: 'PageEdit',
computed: {
lastUpdated () {
return this.$page.lastUpdated
},
lastUpdatedText () {
if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
return this.$themeLocaleConfig.lastUpdated
}
if (typeof this.$site.themeConfig.lastUpdated === 'string') {
return this.$site.themeConfig.lastUpdated
}
return 'Last Updated'
},
editLink () {
if (this.$page.frontmatter.editLink === false) {
return
}
const {
repo,
editLinks,
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = this.$site.themeConfig
if (docsRepo && editLinks && this.$page.relativePath) {
return this.createEditLink(
repo,
docsRepo,
docsDir,
docsBranch,
this.$page.relativePath
)
}
},
editLinkText () {
return (
this.$themeLocaleConfig.editLinkText
|| this.$site.themeConfig.editLinkText
|| `Edit this page`
)
}
},
methods: {
createEditLink (repo, docsRepo, docsDir, docsBranch, path) {
const bitbucket = /bitbucket.org/
if (bitbucket.test(repo)) {
const base = outboundRE.test(docsRepo) ? docsRepo : repo
return (
base.replace(endingSlashRE, '')
+ `/src`
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
+ `?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
)
}
const base = outboundRE.test(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`
return (
base.replace(endingSlashRE, '')
+ `/edit`
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
)
}
}
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl';
.page-edit {
@extend $wrapper;
padding-top: 1rem;
padding-bottom: 1rem;
overflow: auto;
.edit-link {
display: inline-block;
a {
color: lighten($textColor, 25%);
margin-right: 0.25rem;
}
}
.last-updated {
float: right;
font-size: 0.9em;
.prefix {
font-weight: 500;
color: lighten($textColor, 25%);
}
.time {
font-weight: 400;
color: #aaa;
}
}
}
@media (max-width: $MQMobile) {
.page-edit {
.edit-link {
margin-bottom: 0.5rem;
}
.last-updated {
font-size: 0.8em;
float: none;
text-align: left;
}
}
}
</style>
<template>
<div class="page-nav" v-if="prev || next">
<p class="inner">
<div v-if="prev" class="prev page-navigator" v-on:click="clickPrevious">
<div class="navigation-mark">
<span class="navigation-flag">Previous</span>
<router-link style="pointer-events: none" v-if="prev" class="prev router-tag" :to="prev.path">{{ prev.title || prev.path }}</router-link>
</div>
</div>
<div v-if="next" class="next page-navigator" v-on:click="clickNext">
<div class="navigation-mark">
<span class="navigation-flag">Next</span>
<router-link style="pointer-events: none" v-if="next" class="next router-tag" :to="next.path">{{ next.title || next.path }}</router-link>
</div>
</div>
</p>
</div>
</template>
<script>
import { resolvePage } from '../util'
import isString from 'lodash/isString'
import isNil from 'lodash/isNil'
export default {
name: 'PageNav',
props: ['sidebarItems'],
computed: {
prev () {
return resolvePageLink(LINK_TYPES.PREV, this)
},
next () {
return resolvePageLink(LINK_TYPES.NEXT, this)
}
},
methods: {
clickPrevious: function () {
document.querySelector('.prev.router-tag').click()
},
clickNext: function () {
document.querySelector('.next.router-tag').click()
}
}
}
function resolvePrev (page, items) {
return find(page, items, -1)
}
function resolveNext (page, items) {
return find(page, items, 1)
}
const LINK_TYPES = {
NEXT: {
resolveLink: resolveNext,
getThemeLinkConfig: ({ nextLinks }) => nextLinks,
getPageLinkConfig: ({ frontmatter }) => frontmatter.next
},
PREV: {
resolveLink: resolvePrev,
getThemeLinkConfig: ({ prevLinks }) => prevLinks,
getPageLinkConfig: ({ frontmatter }) => frontmatter.prev
}
}
function resolvePageLink (
linkType,
{ $themeConfig, $page, $route, $site, sidebarItems }
) {
const { resolveLink, getThemeLinkConfig, getPageLinkConfig } = linkType
// Get link config from theme
const themeLinkConfig = getThemeLinkConfig($themeConfig)
// Get link config from current page
const pageLinkConfig = getPageLinkConfig($page)
// Page link config will overwrite global theme link config if defined
const link = isNil(pageLinkConfig) ? themeLinkConfig : pageLinkConfig
if (link === false) {
return
} else if (isString(link)) {
return resolvePage($site.pages, link, $route.path)
} else {
return resolveLink($page, sidebarItems)
}
}
function find (page, items, offset) {
const res = []
flatten(items, res)
for (let i = 0; i < res.length; i++) {
const cur = res[i]
if (cur.type === 'page' && cur.path === decodeURIComponent(page.path)) {
return res[i + offset]
}
}
}
function flatten (items, res) {
for (let i = 0, l = items.length; i < l; i++) {
if (items[i].type === 'group') {
flatten(items[i].children || [], res)
} else {
res.push(items[i])
}
}
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl';
.navigation-flag {
font-size: 12px;
font-family: Content-font, Roboto, sans-serif;
font-weight: 400;
line-height: 1.625;
color: #9DAAB6;
}
.navigation-mark {
display: flex;
flex-direction: column;
}
.page-navigator {
box-shadow: rgba(116, 129, 141, 0.1) 0px 3px 8px 0px;
border-width: 1px;
border-style: solid;
border-color: rgb(230, 236, 241);
width: 40%;
height: 50px;
display: inline-flex;
padding: 0 10px;
flex-direction: row;
align-items: center;
justify-content: space-around;
cursor: pointer;
}
.page-navigator:hover {
border-color: #4761f6;
color: #4761f6;
}
.page-nav {
@extend $wrapper;
padding-top: 1rem;
padding-bottom: 0;
.inner {
min-height: 2rem;
margin-top: 0;
border-top: 1px solid $borderColor;
padding-top: 1rem;
overflow: auto; // clear float
}
.router-tag {
font-size: 16px;
font-family: Content-font, Roboto, sans-serif;
font-weight: 700;
line-height: 1.5;
}
.next {
float: right;
}
}
</style>
<template>
<aside class="sidebar">
<NavLinks/>
<slot name="top"/>
<SidebarLinks :depth="0" :items="items"/>
<slot name="bottom"/>
</aside>
</template>
<script>
import SidebarLinks from '@theme/components/SidebarLinks.vue'
import NavLinks from '@theme/components/NavLinks.vue'
export default {
name: 'Sidebar',
components: { SidebarLinks, NavLinks },
props: ['items']
}
</script>
<style lang="stylus">
.sidebar
ul
padding 0
margin 0
list-style-type none
a
display inline-block
.nav-links
display none
border-bottom 1px solid $borderColor
padding 0.5rem 0 0.75rem 0
a
font-weight 600
.nav-item, .repo-link
display block
line-height 1.25rem
font-size 1.1em
padding 0.5rem 0 0.5rem 1.5rem
& > .sidebar-links
padding 1.5rem 0
& > li > a.sidebar-link
font-size 1.1em
line-height 1.7
font-weight bold
& > li:not(:first-child)
margin-top .75rem
@media (max-width: $MQMobile)
.sidebar
.nav-links
display block
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
top calc(1rem - 2px)
& > .sidebar-links
padding 1rem 0
</style>
<template>
<div class="sidebar-button" @click="$emit('toggle-sidebar')">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512">
<path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path>
</svg>
</div>
</template>
<style lang="stylus">
.sidebar-button
cursor pointer
display none
width 1.25rem
height 1.25rem
position absolute
padding 0.6rem
top 0.6rem
left 1rem
.icon
display block
width 1.25rem
height 1.25rem
@media (max-width: $MQMobile)
.sidebar-button
display block
</style>
<template>
<section
class="sidebar-group"
:class="[
{
collapsable,
'is-sub-group': depth !== 0
},
`depth-${depth}`
]"
>
<router-link
v-if="item.path"
class="sidebar-heading clickable"
:class="{
open,
'active': isActive($route, item.path)
}"
:to="item.path"
@click.native="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'">
</span>
</router-link>
<p
v-else
class="sidebar-heading"
:class="{ open }"
@click="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'">
</span>
</p>
<DropdownTransition>
<SidebarLinks
class="sidebar-group-items"
:items="item.children"
v-if="open || !collapsable"
:sidebarDepth="item.sidebarDepth"
:depth="depth + 1"
/>
</DropdownTransition>
</section>
</template>
<script>
import { isActive } from '../util'
import DropdownTransition from '@theme/components/DropdownTransition.vue'
export default {
name: 'SidebarGroup',
props: ['item', 'open', 'collapsable', 'depth'],
components: { DropdownTransition },
// ref: https://vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
beforeCreate () {
this.$options.components.SidebarLinks = require('./SidebarLinks.vue').default
},
methods: { isActive }
}
</script>
<style lang="stylus">
.sidebar-group
.sidebar-group
padding-left 0.5em
&:not(.collapsable)
.sidebar-heading:not(.clickable)
cursor auto
color inherit
// refine styles of nested sidebar groups
&.is-sub-group
padding-left 0
& > .sidebar-heading
font-size 0.95em
line-height 1.4
font-weight normal
padding-left 2rem
&:not(.clickable)
opacity 0.5
& > .sidebar-group-items
padding-left 1rem
& > li > .sidebar-link
font-size: 0.95em;
border-left none
&.depth-2
& > .sidebar-heading
border-left none
.sidebar-heading
color $textColor
transition color .15s ease
cursor pointer
font-size 1.1em
font-weight bold
// text-transform uppercase
padding 0.35rem 1.5rem 0.35rem 1.25rem
width 100%
box-sizing border-box
margin 0
border-left 0.25rem solid transparent
&.open, &:hover
color inherit
.arrow
position relative
top -0.12em
left 0.5em
&.clickable
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
&:hover
color $accentColor
.sidebar-group-items
transition height .1s ease-out
font-size 0.95em
overflow hidden
</style>
<script>
import { isActive, hashRE, groupHeaders } from '../util'
export default {
functional: true,
props: ['item', 'sidebarDepth'],
render (h,
{
parent: {
$page,
$site,
$route,
$themeConfig,
$themeLocaleConfig
},
props: {
item,
sidebarDepth
}
}) {
// use custom active class matching logic
// due to edge case of paths ending with / + hash
const selfActive = isActive($route, item.path)
// for sidebar: auto pages, a hash link should be active if one of its child
// matches
const active = item.type === 'auto'
? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
: selfActive
const link = item.type === 'external'
? renderExternal(h, item.path, item.title || item.path)
: renderLink(h, item.path, item.title || item.path, active)
const maxDepth = [
$page.frontmatter.sidebarDepth,
sidebarDepth,
$themeLocaleConfig.sidebarDepth,
$themeConfig.sidebarDepth,
1
].find(depth => depth !== undefined)
const displayAllHeaders = $themeLocaleConfig.displayAllHeaders
|| $themeConfig.displayAllHeaders
if (item.type === 'auto') {
return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
} else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
const children = groupHeaders(item.headers)
return [link, renderChildren(h, children, item.path, $route, maxDepth)]
} else {
return link
}
}
}
function renderLink (h, to, text, active) {
return h('router-link', {
props: {
to,
activeClass: '',
exactActiveClass: ''
},
class: {
active,
'sidebar-link': true
}
}, text)
}
function renderChildren (h, children, path, route, maxDepth, depth = 1) {
if (!children || depth > maxDepth) return null
return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => {
const active = isActive(route, path + '#' + c.slug)
return h('li', { class: 'sidebar-sub-header' }, [
renderLink(h, path + '#' + c.slug, c.title, active),
renderChildren(h, c.children, path, route, maxDepth, depth + 1)
])
}))
}
function renderExternal (h, to, text) {
return h('a', {
attrs: {
href: to,
target: '_blank',
rel: 'noopener noreferrer'
},
class: {
'sidebar-link': true
}
}, [text, h('OutboundLink')])
}
</script>
<style lang="stylus">
.sidebar .sidebar-sub-headers
padding-left 1rem
font-size 0.95em
a.sidebar-link
font-size 1em
font-weight 400
display inline-block
color $textColor
border-left 0.25rem solid transparent
padding 0.35rem 1rem 0.35rem 1.25rem
line-height 1.4
width: 100%
box-sizing: border-box
&:hover
color $accentColor
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
.sidebar-group &
padding-left 2rem
.sidebar-sub-headers &
padding-top 0.25rem
padding-bottom 0.25rem
border-left none
&.active
font-weight 500
</style>
<template>
<ul
class="sidebar-links"
v-if="items.length"
>
<li v-for="(item, i) in items" :key="i">
<SidebarGroup
v-if="item.type === 'group'"
:item="item"
:open="openGroupIndex.indexOf(i) > -1"
:collapsable="item.collapsable || item.collapsible"
:depth="depth"
@toggle="toggleGroup(i)"
/>
<SidebarLink
v-else
:sidebarDepth="sidebarDepth"
:item="item"
/>
</li>
</ul>
</template>
<script>
import SidebarGroup from '@theme/components/SidebarGroup.vue'
import SidebarLink from '@theme/components/SidebarLink.vue'
import { isActive } from '../util'
export default {
name: 'SidebarLinks',
components: { SidebarGroup, SidebarLink },
props: [
'items',
'depth', // depth of current sidebar links
'sidebarDepth' // depth of headers to be extracted
],
data () {
// 默认打开每一栏的第一项
return {
openGroupIndex: [0]
}
},
created () {
this.refreshIndex()
},
watch: {
'$route' () {
this.refreshIndex()
}
},
methods: {
refreshIndex () {
const index = resolveOpenGroupIndex(
this.$route,
this.items
)
if (index > -1) {
this.openGroupIndex.push(index)
}
},
toggleGroup (index) {
const ifExist = this.openGroupIndex.indexOf(index)
if(ifExist > -1) {
this.openGroupIndex.splice(ifExist, 1)
} else {
this.openGroupIndex.push(index)
}
},
isActive (page) {
return isActive(this.$route, page.regularPath)
}
}
}
function resolveOpenGroupIndex (route, items) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
if (descendantIsActive(route, item)) {
return i
}
}
return -1
}
function descendantIsActive (route, item) {
if (item.type === 'group') {
return item.children.some(child => {
if (child.type === 'group') {
return descendantIsActive(route, child)
} else {
return child.type === 'page' && isActive(route, child.path)
}
})
}
return false
}
</script>
<script>
export default {
functional: true,
props: {
type: {
type: String,
default: 'tip'
},
text: String,
vertical: {
type: String,
default: 'top'
}
},
render (h, { props, slots }) {
return h('span', {
class: ['badge', props.type],
style: {
verticalAlign: props.vertical
}
}, props.text || slots().default)
}
}
</script>
<style lang="stylus" scoped>
.badge
display inline-block
font-size 14px
height 18px
line-height 18px
border-radius 3px
padding 0 6px
color white
background-color #42b983
&.tip, &.green
background-color #42b983
&.error
background-color #DA5961 //#f66
&.warning, &.warn, &.yellow
background-color darken(#ffe564, 35%)
& + &
margin-left 5px
</style>
const path = require('path')
// Theme API.
module.exports = (options, ctx) => ({
alias() {
const { themeConfig, siteConfig } = ctx
// resolve algolia
const isAlgoliaSearch =
themeConfig.algolia ||
Object.keys((siteConfig.locales && themeConfig.locales) || {}).some(base => themeConfig.locales[base].algolia)
return {
'@AlgoliaSearchBox': isAlgoliaSearch
? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue')
: path.resolve(__dirname, 'noopModule.js')
}
},
plugins: [
['@vuepress/active-header-links', options.activeHeaderLinks],
'@vuepress/search',
'@vuepress/plugin-nprogress',
[
'container',
{
type: 'tip',
defaultTitle: {
'/zh/': '提示'
}
}
],
[
'container',
{
type: 'warning',
defaultTitle: {
'/zh/': '注意'
}
}
],
[
'container',
{
type: 'danger',
defaultTitle: {
'/zh/': '警告'
}
}
]
]
})
<template>
<div class="theme-container">
<div class="theme-default-content">
<h1>404</h1>
<blockquote>{{ getMsg() }}</blockquote>
<router-link to="/">Take me home.</router-link>
</div>
</div>
</template>
<script>
const msgs = [
`There's nothing here.`,
`How did we get here?`,
`That's a Four-Oh-Four.`,
`Looks like we've got some broken links.`
]
export default {
methods: {
getMsg () {
return msgs[Math.floor(Math.random() * msgs.length)]
}
}
}
</script>
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
>
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"
/>
<div
class="sidebar-mask"
@click="toggleSidebar(false)"
></div>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar"
>
<slot
name="sidebar-top"
slot="top"
/>
<slot
name="sidebar-bottom"
slot="bottom"
/>
</Sidebar>
<Home v-if="$page.frontmatter.home"/>
<Page
v-else
:sidebar-items="sidebarItems"
>
<slot
name="page-top"
slot="top"
/>
<slot
name="page-bottom"
slot="bottom"
/>
</Page>
</div>
</template>
<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems } from '../util'
export default {
components: { Home, Page, Sidebar, Navbar },
data () {
return {
isSidebarOpen: false
}
},
computed: {
shouldShowNavbar () {
const { themeConfig } = this.$site
const { frontmatter } = this.$page
if (
frontmatter.navbar === false
|| themeConfig.navbar === false) {
return false
}
return (
this.$title
|| themeConfig.logo
|| themeConfig.repo
|| themeConfig.nav
|| this.$themeLocaleConfig.nav
)
},
shouldShowSidebar () {
const { frontmatter } = this.$page
return (
!frontmatter.home
&& frontmatter.sidebar !== false
&& this.sidebarItems.length
)
},
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
},
pageClasses () {
const userPageClass = this.$page.frontmatter.pageClass
return [
{
'no-navbar': !this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': !this.shouldShowSidebar
},
userPageClass
]
}
},
mounted () {
this.$router.afterEach(() => {
this.isSidebarOpen = false
})
},
methods: {
toggleSidebar (to) {
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
this.$emit('toggle-sidebar', this.isSidebarOpen)
},
// side swipe
onTouchStart (e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
}
},
onTouchEnd (e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x
const dy = e.changedTouches[0].clientY - this.touchStart.y
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true)
} else {
this.toggleSidebar(false)
}
}
}
}
}
</script>
@require './config'
.arrow
display inline-block
width 0
height 0
&.up
border-left 4px solid transparent
border-right 4px solid transparent
border-bottom 6px solid $arrowBgColor
&.down
border-left 4px solid transparent
border-right 4px solid transparent
border-top 6px solid $arrowBgColor
&.right
border-top 4px solid transparent
border-bottom 4px solid transparent
border-left 6px solid $arrowBgColor
&.left
border-top 4px solid transparent
border-bottom 4px solid transparent
border-right 6px solid $arrowBgColor
{$contentClass}
code
color lighten($textColor, 20%)
padding 0.25rem 0.5rem
margin 0
font-size 0.85em
background-color rgba(27,31,35,0.05)
border-radius 3px
.token
&.deleted
color #EC5975
&.inserted
color $accentColor
{$contentClass}
pre, pre[class*="language-"]
line-height 1.4
padding 1.25rem 1.5rem
margin 0.85rem 0
background-color $codeBgColor
border-radius 6px
overflow auto
code
color #fff
padding 0
background-color transparent
border-radius 0
div[class*="language-"]
position relative
background-color $codeBgColor
border-radius 6px
.highlight-lines
user-select none
padding-top 1.3rem
position absolute
top 0
left 0
width 100%
line-height 1.4
.highlighted
background-color rgba(0, 0, 0, 66%)
pre, pre[class*="language-"]
background transparent
position relative
z-index 1
&::before
position absolute
z-index 3
top 0.8em
right 1em
font-size 0.75rem
color rgba(255, 255, 255, 0.4)
&:not(.line-numbers-mode)
.line-numbers-wrapper
display none
&.line-numbers-mode
.highlight-lines .highlighted
position relative
&:before
content ' '
position absolute
z-index 3
left 0
top 0
display block
width $lineNumbersWrapperWidth
height 100%
background-color rgba(0, 0, 0, 66%)
pre
padding-left $lineNumbersWrapperWidth + 1 rem
vertical-align middle
.line-numbers-wrapper
position absolute
top 0
width $lineNumbersWrapperWidth
text-align center
color rgba(255, 255, 255, 0.3)
padding 1.25rem 0
line-height 1.4
br
user-select none
.line-number
position relative
z-index 4
user-select none
font-size 0.85em
&::after
content ''
position absolute
z-index 2
top 0
left 0
width $lineNumbersWrapperWidth
height 100%
border-radius 6px 0 0 6px
border-right 1px solid rgba(0, 0, 0, 66%)
background-color $codeBgColor
for lang in $codeLang
div{'[class~="language-' + lang + '"]'}
&:before
content ('' + lang)
div[class~="language-javascript"]
&:before
content "js"
div[class~="language-typescript"]
&:before
content "ts"
div[class~="language-markup"]
&:before
content "html"
div[class~="language-markdown"]
&:before
content "md"
div[class~="language-json"]:before
content "json"
div[class~="language-ruby"]:before
content "rb"
div[class~="language-python"]:before
content "py"
div[class~="language-bash"]:before
content "sh"
div[class~="language-php"]:before
content "php"
@import '~prismjs/themes/prism-tomorrow.css'
$contentClass = '.theme-default-content'
.custom-block
.custom-block-title
font-weight 600
margin-bottom -0.4rem
&.tip, &.warning, &.danger
padding .1rem 1.5rem
border-left-width .5rem
border-left-style solid
margin 1rem 0
&.tip
background-color #f3f5f7
border-color #42b983
&.warning
background-color rgba(255,229,100,.3)
border-color darken(#ffe564, 35%)
color darken(#ffe564, 70%)
.custom-block-title
color darken(#ffe564, 50%)
a
color $textColor
&.danger
background-color #ffe6e6
border-color darken(red, 20%)
color darken(red, 70%)
.custom-block-title
color darken(red, 40%)
a
color $textColor
@require './config'
@require './code'
@require './custom-blocks'
@require './arrow'
@require './wrapper'
@require './toc'
html, body
padding 0
margin 0
background-color #fff
body
font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
font-size 16px
color $textColor
.page
padding-left $sidebarWidth
.navbar
position fixed
z-index 20
top 0
left 0
right 0
height $navbarHeight
background-color #fff
box-sizing border-box
border-bottom 1px solid $borderColor
.sidebar-mask
position fixed
z-index 9
top 0
left 0
width 100vw
height 100vh
display none
.sidebar
font-size 16px
background-color #fff
width $sidebarWidth
position fixed
z-index 10
margin 0
top $navbarHeight
left 0
bottom 0
box-sizing border-box
border-right 1px solid $borderColor
overflow-y auto
{$contentClass}:not(.custom)
@extend $wrapper
> *:first-child
margin-top $navbarHeight
a:hover
text-decoration underline
p.demo
padding 1rem 1.5rem
border 1px solid #ddd
border-radius 4px
img
max-width 100%
{$contentClass}.custom
padding 0
margin 0
img
max-width 100%
a
font-weight 500
color $accentColor
text-decoration none
p a code
font-weight 400
color $accentColor
kbd
background #eee
border solid 0.15rem #ddd
border-bottom solid 0.25rem #ddd
border-radius 0.15rem
padding 0 0.15em
blockquote
font-size 1rem
color #999;
border-left .2rem solid #dfe2e5
margin 1rem 0
padding .25rem 0 .25rem 1rem
& > p
margin 0
ul, ol
padding-left 1.2em
strong
font-weight 600
h1, h2, h3, h4, h5, h6
font-weight 600
line-height 1.25
{$contentClass}:not(.custom) > &
margin-top (0.5rem - $navbarHeight)
padding-top ($navbarHeight + 1rem)
margin-bottom 0
&:first-child
margin-top -1.5rem
margin-bottom 1rem
+ p, + pre, + .custom-block
margin-top 2rem
&:hover .header-anchor
opacity: 1
h1
font-size 2.2rem
h2
font-size 1.65rem
padding-bottom .3rem
border-bottom 1px solid $borderColor
h3
font-size 1.35rem
a.header-anchor
font-size 0.85em
float left
margin-left -0.87em
padding-right 0.23em
margin-top 0.125em
opacity 0
&:hover
text-decoration none
code, kbd, .line-number
font-family source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace
p, ul, ol
line-height 1.7
hr
border 0
border-top 1px solid $borderColor
table
border-collapse collapse
margin 1rem 0
display: block
overflow-x: auto
tr
border-top 1px solid #dfe2e5
&:nth-child(2n)
background-color #f6f8fa
th, td
border 1px solid #dfe2e5
padding .6em 1em
.theme-container
&.sidebar-open
.sidebar-mask
display: block
&.no-navbar
{$contentClass}:not(.custom) > h1, h2, h3, h4, h5, h6
margin-top 1.5rem
padding-top 0
.sidebar
top 0
@media (min-width: ($MQMobile + 1px))
.theme-container.no-sidebar
.sidebar
display none
.page
padding-left 0
@require 'mobile.styl'
@require './config'
$mobileSidebarWidth = $sidebarWidth * 0.82
// narrow desktop / iPad
@media (max-width: $MQNarrow)
.sidebar
font-size 15px
width $mobileSidebarWidth
.page
padding-left $mobileSidebarWidth
// wide mobile
@media (max-width: $MQMobile)
.sidebar
top 0
padding-top $navbarHeight
transform translateX(-100%)
transition transform .2s ease
.page
padding-left 0
.theme-container
&.sidebar-open
.sidebar
transform translateX(0)
&.no-navbar
.sidebar
padding-top: 0
// narrow mobile
@media (max-width: $MQMobileNarrow)
h1
font-size 1.9rem
{$contentClass}
div[class*="language-"]
margin 0.85rem -1.5rem
border-radius 0
.table-of-contents
.badge
vertical-align middle
$wrapper
max-width $contentWidth
margin 0 auto
padding 2rem 2.5rem
@media (max-width: $MQNarrow)
padding 2rem
@media (max-width: $MQMobileNarrow)
padding 1.5rem
export const hashRE = /#.*$/
export const extRE = /\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^[a-z]+:/i
export function normalize(path) {
return decodeURI(path)
.replace(hashRE, '')
.replace(extRE, '')
}
export function getHash(path) {
const match = path.match(hashRE)
if (match) {
return match[0]
}
}
export function isExternal(path) {
return outboundRE.test(path)
}
export function isMailto(path) {
return /^mailto:/.test(path)
}
export function isTel(path) {
return /^tel:/.test(path)
}
export function ensureExt(path) {
if (isExternal(path)) {
return path
}
const hashMatch = path.match(hashRE)
const hash = hashMatch ? hashMatch[0] : ''
const normalized = normalize(path)
if (endingSlashRE.test(normalized)) {
return path
}
return normalized + '.html' + hash
}
export function isActive(route, path) {
const routeHash = route.hash
const linkHash = getHash(path)
if (linkHash && routeHash !== linkHash) {
return false
}
const routePath = normalize(route.path)
const pagePath = normalize(path)
return routePath === pagePath
}
export function resolvePage(pages, rawPath, base) {
if (isExternal(rawPath)) {
return {
type: 'external',
path: rawPath
}
}
if (base) {
rawPath = resolvePath(rawPath, base)
}
const path = normalize(rawPath)
for (let i = 0; i < pages.length; i++) {
if (normalize(pages[i].regularPath) === path) {
return Object.assign({}, pages[i], {
type: 'page',
path: ensureExt(pages[i].path)
})
}
}
console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
return {}
}
function resolvePath(relative, base, append) {
const firstChar = relative.charAt(0)
if (firstChar === '/') {
return relative
}
if (firstChar === '?' || firstChar === '#') {
return base + relative
}
const stack = base.split('/')
// remove trailing segment if:
// - not appending
// - appending to trailing slash (last segment is empty)
if (!append || !stack[stack.length - 1]) {
stack.pop()
}
// resolve relative path
const segments = relative.replace(/^\//, '').split('/')
for (let i = 0; i < segments.length; i++) {
const segment = segments[i]
if (segment === '..') {
stack.pop()
} else if (segment !== '.') {
stack.push(segment)
}
}
// ensure leading slash
if (stack[0] !== '') {
stack.unshift('')
}
return stack.join('/')
}
/**
* @param { Page } page
* @param { string } regularPath
* @param { SiteData } site
* @param { string } localePath
* @returns { SidebarGroup }
*/
export function resolveSidebarItems(page, regularPath, site, localePath) {
const { pages, themeConfig } = site
const localeConfig = localePath && themeConfig.locales ? themeConfig.locales[localePath] || themeConfig : themeConfig
const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
if (pageSidebarConfig === 'auto') {
return resolveHeaders(page)
}
const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
if (!sidebarConfig) {
return []
} else {
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
return config ? config.map(item => resolveItem(item, pages, base)) : []
}
}
/**
* @param { Page } page
* @returns { SidebarGroup }
*/
function resolveHeaders(page) {
const headers = groupHeaders(page.headers || [])
return [
{
type: 'group',
collapsable: false,
title: page.title,
path: null,
children: headers.map(h => ({
type: 'auto',
title: h.title,
basePath: page.path,
path: page.path + '#' + h.slug,
children: h.children || []
}))
}
]
}
export function groupHeaders(headers) {
// group h3s under h2
headers = headers.map(h => Object.assign({}, h))
let lastH2
headers.forEach(h => {
if (h.level === 2) {
lastH2 = h
} else if (lastH2) {
;(lastH2.children || (lastH2.children = [])).push(h)
}
})
return headers.filter(h => h.level === 2)
}
export function resolveNavLinkItem(linkItem) {
return Object.assign(linkItem, {
type: linkItem.items && linkItem.items.length ? 'links' : 'link'
})
}
/**
* @param { Route } route
* @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
* @returns { base: string, config: SidebarConfig }
*/
export function resolveMatchingConfig(regularPath, config) {
if (Array.isArray(config)) {
return {
base: '/',
config: config
}
}
for (const base in config) {
if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
return {
base,
config: config[base]
}
}
}
return {}
}
function ensureEndingSlash(path) {
return /(\.html|\/)$/.test(path) ? path : path + '/'
}
function resolveItem(item, pages, base, groupDepth = 1) {
if (typeof item === 'string') {
return resolvePage(pages, item, base)
} else if (Array.isArray(item)) {
return Object.assign(resolvePage(pages, item[0], base), {
title: item[1]
})
} else {
if (groupDepth > 10) {
console.error('[vuepress] detected a too deep nested sidebar group.')
}
const children = item.children || []
if (children.length === 0 && item.path) {
return Object.assign(resolvePage(pages, item.path, base), {
title: item.title
})
}
return {
type: 'group',
path: item.path,
title: item.title,
sidebarDepth: item.sidebarDepth,
children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
collapsable: item.collapsable !== false
}
}
}
---
home: true
heroText: 欢迎来到快应用 Light版
heroImage: ./assets/hero.png
tagline: 快应用文档(Light 版)
actionText: Getting Started →
actionLink: /framework/
features:
- title: 什么是快应用?
details: 快应用是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。
- title: 奇美拉是什么?
details: 兼顾微信小程序的语法开发出的快应用平台,使用户可以用微信小程序低成本的接入快应用平台。
- title: 通过文档你将学会
details: 快应用奇美拉版本(小程序兼容版本)的使用方法。
footer: MIT Licensed | Copyright © 2019-present quickapp team
---
## 基础
| 名称 | 功能说明 |
| --- | --- |
| [qa.canIUse](/api/base/qa.canIUse.html) | 判断指定API(含调用方式/回调/参数/返回值/返回值的属性)或者组件(含属性)在当前快应用版本是否可用。 |
| [qa.base64ToArrayBuffer](/api/base/qa.base64ToArrayBuffer.html) | 将 Base64 字符串转成 ArrayBuffer 对象 |
| [qa.arrayBufferToBase64](/api/base/qa.arrayBufferToBase64.html) | 将 ArrayBuffer 对象转成 Base64 字符串 |
### 系统
#### 系统信息
| 名称 | 功能说明 |
| --- | --- |
| [qa.getSystemInfoSync](/api/base/system/qa.getSystemInfoSync.html) | [qa.getSystemInfo](/api/base/system/qa.getSystemInfo.html) 的同步版本接口 |
| [qa.getSystemInfo](/api/base/system/qa.getSystemInfo.html) | 获取系统信息 |
### 快应用
#### 应用级事件
| 名称 | 功能说明 |
| ----------------------------------------------------------- | ------------------------------------ |
| [qa.onError](/api/base/app/qa.onError.html) | 监听快应用错误事件 |
| [qa.onAppShow](/api/base/app/qa.onAppShow.html) | 监听快应用切前台事件 |
| [qa.onAppHide](/api/base/app/qa.onAppHide.html) | 监听快应用切后台事件 |
| [qa.offPageNotFound](/api/base/app/qa.offPageNotFound.html) | 取消监听快应用要打开的页面不存在事件 |
| [qa.offError](/api/base/app/qa.offError.html) | 取消监听快应用错误事件 |
| [qa.offAppShow](/api/base/app/qa.offAppShow.html) | 取消监听快应用切前台事件 |
| [qa.offAppHide](/api/base/app/qa.offAppHide.html) | 取消监听快应用切后台事件 |
### 调试
| 名称 | 功能说明 |
| ----------------------------------------------------------- | -------------------- |
| [qa.setEnableDebug](/api/base/debug/qa.setEnableDebug.html) | 设置是否打开调试开关 |
#### console
| 名称 | 功能说明 |
| --- | --- |
| [console.debug](/api/base/debug/console.debug.html) | 向调试面板中打印 debug 日志 |
| [console.error](/api/base/debug/console.error.html) | 向调试面板中打印 error 日志 |
| [console.group](/api/base/debug/console.group.html) | 在调试面板中创建一个新的分组 |
| [console.groupEnd](/api/base/debug/console.groupEnd.html) | 结束由 [console.group](/api/base/debug/console.group.html) 创建的分组 |
| [console.info](/api/base/debug/console.info.html) | 向调试面板中打印 info 日志 |
| [console.log](/api/base/debug/console.log.html) | 向调试面板中打印 log 日志 |
| [console.warn](/api/base/debug/console.warn.html) | 向调试面板中打印 warn 日志 |
### 定时器
| 名称 | 功能说明 |
| --------------------------------------------------- | ------------------------------- |
| [clearInterval](/api/base/timer/clearInterval.html) | 取消由 setInterval 设置的定时器 |
| [clearTimeout](/api/base/timer/clearTimeout.html) | 取消由 setTimeout 设置的定时器 |
| [setInterval](/api/base/timer/setInterval.html) | 设定一个定时器 |
| [setTimeout](/api/base/timer/setTimeout.html) | 设定一个定时器 |
## 路由
| 名称 | 功能说明 |
| -------------------------------------------------- | ------------------------------------------------ |
| [qa.switchTab](/api/route/qa.switchTab.html) | 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 |
| [qa.reLaunch](/api/route/qa.reLaunch.html) | 关闭所有页面,打开到应用内的某个页面 |
| [qa.redirectTo](/api/route/qa.redirectTo.html) | 关闭当前页面,跳转到应用内的某个页面 |
| [qa.navigateTo](/api/route/qa.navigateTo.html) | 保留当前页面,跳转到应用内的某个页面 |
| [qa.navigateBack](/api/route/qa.navigateBack.html) | 关闭当前页面,返回上一页面或多级页面 |
## 界面
### 交互
| 名称 | 功能说明 |
| ----------------------------------------------------------------- | ------------------- |
| [qa.showToast](/api/ui/interaction/qa.showToast.html) | 显示消息提示框 |
| [qa.showModal](/api/ui/interaction/qa.showModal.html) | 显示模态对话框 |
| [qa.showLoading](/api/ui/interaction/qa.showLoading.html) | 显示 loading 提示框 |
| [qa.showActionSheet](/api/ui/interaction/qa.showActionSheet.html) | 显示操作菜单 |
| [qa.hideToast](/api/ui/interaction/qa.hideToast.html) | 隐藏消息提示框 |
| [qa.hideLoading](/api/ui/interaction/qa.hideLoading.html) | 隐藏 loading 提示框 |
### 导航栏
| 名称 | 功能说明 |
| --- | --- |
| [qa.showNavigationBarLoading](/api/ui/navigation-bar/qa.showNavigationBarLoading.html) | 显示当前页面的导航条加载动画 |
| [qa.setNavigationBarTitle](/api/ui/navigation-bar/qa.setNavigationBarTitle.html) | 设置当前当前页面的标题,即时生效 |
| [qa.setNavigationBarColor](/api/ui/navigation-bar/qa.setNavigationBarColor.html) | 设置当前页面的导航条颜色 |
| [qa.hideNavigationBarLoading](/api/ui/navigation-bar/qa.hideNavigationBarLoading.html) | 隐藏当前页面的导航条加载动画 |
### 背景
| 名称 | 功能说明 |
| --- | --- |
| [qa.setBackgroundTextStyle](/api/ui/background/qa.setBackgroundTextStyle.html) | 动态设置下拉背景字体、loading 图的样式 |
| [qa.setBackgroundColor](/api/ui/background/qa.setBackgroundColor.html) | 动态设置窗口的背景色 |
### Tab Bar
| 名称 | 功能说明 |
| ----------------------------------------------------------------- | -------------------------------- |
| [qa.showTabBarRedDot](/api/ui/tab-bar/qa.showTabBarRedDot.html) | 显示 tabBar 某一项的右上角的红点 |
| [qa.showTabBar](/api/ui/tab-bar/qa.showTabBar.html) | 显示 tabBar |
| [qa.setTabBarStyle](/api/ui/tab-bar/qa.setTabBarStyle.html) | 动态设置 tabBar 的整体样式 |
| [qa.setTabBarItem](/api/ui/tab-bar/qa.setTabBarItem.html) | 动态设置 tabBar 某一项的内容 |
| [qa.setTabBarBadge](/api/ui/tab-bar/qa.setTabBarBadge.html) | 为 tabBar 某一项的右上角添加文本 |
| [qa.removeTabBarBadge](/api/ui/tab-bar/qa.removeTabBarBadge.html) | 移除 tabBar 某一项右上角的文本 |
| [qa.hideTabBarRedDot](/api/ui/tab-bar/qa.hideTabBarRedDot.html) | 隐藏 tabBar 某一项的右上角的红点 |
| [qa.hideTabBar](/api/ui/tab-bar/qa.hideTabBar.html) | 隐藏 tabBar |
### 字体
| 名称 | 功能说明 |
| ---------------------------------------------------- | ---------------- |
| [qa.loadFontFace](/api/ui/font/qa.loadFontFace.html) | 动态加载网络字体 |
### 下拉刷新
| 名称 | 功能说明 |
| --------------------------------------------------------------------------------- | -------------------- |
| [qa.stopPullDownRefresh](/api/ui/pull-down-refresh/qa.stopPullDownRefresh.html) | 停止当前页面下拉刷新 |
| [qa.startPullDownRefresh](/api/ui/pull-down-refresh/qa.startPullDownRefresh.html) | 开始下拉刷新 |
### 滚动
| 名称 | 功能说明 |
| ------------------------------------------------------ | -------------------- |
| [qa.pageScrollTo](/api/ui/scroll/qa.pageScrollTo.html) | 将页面滚动到目标位置 |
### 动画
| 名称 | 功能说明 |
| --- | --- |
| [qa.createAnimation](/api/ui/animation/qa.createAnimation.html) | 创建一个动画实例 [animation](/api/ui/animation/Animation.html) |
#### Animation
| 名称 | 功能说明 |
| --- | --- |
| [Animation.height](/api/ui/animation/Animation.height.html) | 设置高度 |
| [Animation.left](/api/ui/animation/Animation.left.html) | 设置 left 值 |
| [Animation.matrix](/api/ui/animation/Animation.matrix.html) | 同 [transform-function matrix](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix) |
| [Animation.matrix3d](/api/ui/animation/Animation.matrix3d.html) | 同 [transform-function matrix3d](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d) |
| [Animation.opacity](/api/ui/animation/Animation.opacity.html) | 设置透明度 |
| [Animation.right](/api/ui/animation/Animation.right.html) | 设置 right 值 |
| [Animation.rotate](/api/ui/animation/Animation.rotate.html) | 从原点顺时针旋转一个角度 |
| [Animation.rotate3d](/api/ui/animation/Animation.rotate3d.html) | 从 X 轴顺时针旋转一个角度 |
| [Animation.rotateX](/api/ui/animation/Animation.rotateX.html) | 从 X 轴顺时针旋转一个角度 |
| [Animation.rotateY](/api/ui/animation/Animation.rotateY.html) | 从 Y 轴顺时针旋转一个角度 |
| [Animation.rotateZ](/api/ui/animation/Animation.rotateZ.html) | 从 Z 轴顺时针旋转一个角度 |
| [Animation.scale](/api/ui/animation/Animation.scale.html) | 缩放 |
| [Animation.scale3d](/api/ui/animation/Animation.scale3d.html) | 缩放 |
| [Animation.scaleX](/api/ui/animation/Animation.scaleX.html) | 缩放 X 轴 |
| [Animation.scaleY](/api/ui/animation/Animation.scaleY.html) | 缩放 Y 轴 |
| [Animation.scaleZ](/api/ui/animation/Animation.scaleZ.html) | 缩放 Z 轴 |
| [Animation.skew](/api/ui/animation/Animation.skew.html) | 对 X、Y 轴坐标进行倾斜 |
| [Animation.skewX](/api/ui/animation/Animation.skewX.html) | 对 X 轴坐标进行倾斜 |
| [Animation.skewY](/api/ui/animation/Animation.skewY.html) | 对 Y 轴坐标进行倾斜 |
| [Animation.step](/api/ui/animation/Animation.step.html) | 表示一组动画完成 |
| [Animation.top](/api/ui/animation/Animation.top.html) | 设置 top 值 |
| [Animation.translate](/api/ui/animation/Animation.translate.html) | 平移变换 |
| [Animation.translate3d](/api/ui/animation/Animation.translate3d.html) | 对 xyz 坐标进行平移变换 |
| [Animation.translateX](/api/ui/animation/Animation.translateX.html) | 对 X 轴平移 |
| [Animation.translateY](/api/ui/animation/Animation.translateY.html) | 对 Y 轴平移 |
| [Animation.translateZ](/api/ui/animation/Animation.translateZ.html) | 对 Z 轴平移 |
| [Animation.width](/api/ui/animation/Animation.width.html) | 设置宽度 |
| [Animation.backgroundColor](/api/ui/animation/Animation.backgroundColor.html) | 设置背景色 |
| [Animation.bottom](/api/ui/animation/Animation.bottom.html) | 设置 bottom 值 |
| [Animation.export](/api/ui/animation/Animation.export.html) | 导出动画队列 |
### 自定义组件
| 名称 | 功能说明 |
| -------------------------------------------------------- | ---------------------------------- |
| [qa.nextTick](/api/ui/custom-component/qa.nextTick.html) | 延迟一部分操作到下一个时间片再执行 |
### 菜单
| 名称 | 功能说明 |
| --- | --- |
| [qa.getMenuButtonBoundingClientRect](/api/ui/menu/qa.getMenuButtonBoundingClientRect.html) | 获取菜单按钮(右上角menu按钮)的布局位置信息 |
## 网络
### 发起请求
| 名称 | 功能说明 |
| -------------------------------------------------- | ------------------- |
| [qa.request](/api/network/request/qa.request.html) | 发起 HTTPS 网络请求的接口 |
#### RequestTask
| 名称 | 功能说明 |
| ---------------------------------------------------------------- | ------------ |
| [RequestTask.abort](/api/network/request/RequestTask.abort.html) | 中断该请求任务 |
### 下载
| 名称 | 功能说明 |
| ------------------------------------------------------------- | ------------------ |
| [qa.downloadFile](/api/network/download/qa.downloadFile.html) | 下载文件资源到本地的接口 |
#### DownloadTask
| 名称 | 功能说明 |
| --- | --- |
| [DownloadTask.abort](/api/network/download/DownloadTask.abort.html) | 中断进行中的下载任务 |
| [DownloadTask.offProgressUpdate](/api/network/download/DownloadTask.offProgressUpdate.html) | 取消订阅**下载进度变化事件** |
| [DownloadTask.onProgressUpdate](/api/network/download/DownloadTask.onProgressUpdate.html) | 订阅**下载进度变化事件**事件 |
### 上传
| 名称 | 功能说明 |
| ------------------------------------------------------- | ---------------------- |
| [qa.uploadFile](/api/network/upload/qa.uploadFile.html) | 将本地文件上传到服务器端 |
#### UploadTask
| 名称 | 功能说明 |
| ------------------------------------------------------------------------------------- | ------------------------ |
| [UploadTask.abort](/api/network/upload/UploadTask.abort.html) | 中断该上传任务 |
| [UploadTask.offProgressUpdate](/api/network/upload/UploadTask.offProgressUpdate.html) | 取消订阅**上传进度变化事件** |
| [UploadTask.onProgressUpdate](/api/network/upload/UploadTask.onProgressUpdate.html) | 订阅**上传进度变化事件**回调 |
### WebSocket
| 名称 | 功能说明 |
| ------------------------------------------------------------------------ | ------------------------------------- |
| [qa.sendSocketMessage](/api/network/websocket/qa.sendSocketMessage.html) | 通过已连接成功的WebSocket连接发送数据 |
| [qa.onSocketOpen](/api/network/websocket/qa.onSocketOpen.html) | 订阅**WebSocket连接打开事件**回调 |
| [qa.onSocketMessage](/api/network/websocket/qa.onSocketMessage.html) | 订阅**WebSocket接受到服务器的消息事件**回调 |
| [qa.onSocketError](/api/network/websocket/qa.onSocketError.html) | 订阅**WebSocket错误事件**回调 |
| [qa.onSocketClose](/api/network/websocket/qa.onSocketClose.html) | 订阅**WebSocket连接关闭事件**回调 |
| [qa.connectSocket](/api/network/websocket/qa.connectSocket.html) | 创建新的WebSocket连接 |
| [qa.closeSocket](/api/network/websocket/qa.closeSocket.html) | 关闭WebSocket连接 |
#### SocketTask
| 名称 | 功能说明 |
| ------------------------------------------------------------------------ | ------------------------------------- |
| [SocketTask.close](/api/network/websocket/SocketTask.close.html) | 关闭当前WebSocket连接 |
| [SocketTask.onClose](/api/network/websocket/SocketTask.onClose.html) | 订阅**WebSocket连接关闭事件**回调 |
| [SocketTask.onError](/api/network/websocket/SocketTask.onError.html) | 订阅**WebSocket错误事件**回调 |
| [SocketTask.onMessage](/api/network/websocket/SocketTask.onMessage.html) | 订阅**WebSocket接受到服务器的消息事件**回调 |
| [SocketTask.onOpen](/api/network/websocket/SocketTask.onOpen.html) | 订阅**WebSocket连接打开事件**回调 |
| [SocketTask.send](/api/network/websocket/SocketTask.send.html) | 通过已创建的WebSocket连接发送数据 |
## 数据缓存
| 名称 | 功能说明 |
| --- | --- |
| [qa.setStorageSync](/api/storage/qa.setStorageSync.html) | [qa.setStorage](/api/storage/qa.setStorage.html) 的同步版本 |
| [qa.setStorage](/api/storage/qa.setStorage.html) | 将数据存储在本地缓存中指定的 key 中 |
| [qa.removeStorageSync](/api/storage/qa.removeStorageSync.html) | [qa.removeStorage](/api/storage/qa.removeStorage.html) 的同步版本 |
| [qa.removeStorage](/api/storage/qa.removeStorage.html) | 从本地缓存中移除指定 key |
| [qa.getStorageSync](/api/storage/qa.getStorageSync.html) | [qa.getStorage](/api/storage/qa.getStorage.html) 的同步版本 |
| [qa.getStorageInfoSync](/api/storage/qa.getStorageInfoSync.html) | [qa.getStorageInfo](/api/storage/qa.getStorageInfo.html) 的同步版本 |
| [qa.getStorageInfo](/api/storage/qa.getStorageInfo.html) | 异步获取当前 storage 的相关信息 |
| [qa.getStorage](/api/storage/qa.getStorage.html) | 从本地缓存中异步获取指定 key 的内容 |
| [qa.clearStorageSync](/api/storage/qa.clearStorageSync.html) | [qa.clearStorage](/api/storage/qa.clearStorage.html) 的同步版本 |
| [qa.clearStorage](/api/storage/qa.clearStorage.html) | 清理本地数据缓存 |
## 媒体
### 地图
| 名称 | 功能说明 |
| --- | --- |
| [qa.createMapContext](/api/media/map/qa.createMapContext.html) | 创建 [map](/api/../component/map.html) 上下文 [MapContext](/api/media/map/MapContext.html) 对象 |
#### MapContext
| 名称 | 功能说明 |
| -------------------------------------------------------------------------------- | -------------------------- |
| [MapContext.getCenterLocation](/api/media/map/MapContext.getCenterLocation.html) | 获取当前地图中心的经纬度 |
| [MapContext.getRegion](/api/media/map/MapContext.getRegion.html) | 获取当前地图的视野范围 |
| [MapContext.getScale](/api/media/map/MapContext.getScale.html) | 获取当前地图的缩放级别 |
| [MapContext.includePoints](/api/media/map/MapContext.includePoints.html) | 缩放视野展示所有经纬度 |
| [MapContext.moveToLocation](/api/media/map/MapContext.moveToLocation.html) | 将地图中心移动到当前定位点 |
| [MapContext.translateMarker](/api/media/map/MapContext.translateMarker.html) | 平移 marker,带动画 |
### 图片
| 名称 | 功能说明 |
| ---------------------------------------------------------------------------- | -------------------------------- |
| [qa.saveImageToPhotosAlbum](/api/media/image/qa.saveImageToPhotosAlbum.html) | 保存图片到系统相册 |
| [qa.previewImage](/api/media/image/qa.previewImage.html) | 在新页面中全屏预览图片 |
| [qa.getImageInfo](/api/media/image/qa.getImageInfo.html) | 获取图片信息 |
| [qa.compressImage](/api/media/image/qa.compressImage.html) | 压缩图片接口,可选压缩质量 |
| [qa.chooseImage](/api/media/image/qa.chooseImage.html) | 从本地相册选择图片或使用相机拍照 |
### 视频
| 名称 | 功能说明 |
| --- | --- |
| [qa.saveVideoToPhotosAlbum](/api/media/video/qa.saveVideoToPhotosAlbum.html) | 保存视频到系统相册 |
| [qa.createVideoContext](/api/media/video/qa.createVideoContext.html) | 创建 [video](/api/../component/video.html) 上下文 [VideoContext](/api/media/video/VideoContext.html) 对象 |
| [qa.chooseVideo](/api/media/video/qa.chooseVideo.html) | 拍摄视频或从手机相册中选视频 |
#### VideoContext
| 名称 | 功能说明 |
| -------------------------------------------------------------------------------------- | -------------- |
| [VideoContext.exitFullScreen](/api/media/video/VideoContext.exitFullScreen.html) | 退出全屏 |
| [VideoContext.pause](/api/media/video/VideoContext.pause.html) | 暂停视频 |
| [VideoContext.play](/api/media/video/VideoContext.play.html) | 播放视频 |
| [VideoContext.requestFullScreen](/api/media/video/VideoContext.requestFullScreen.html) | 进入全屏 |
| [VideoContext.seek](/api/media/video/VideoContext.seek.html) | 跳转到指定位置 |
| [VideoContext.stop](/api/media/video/VideoContext.stop.html) | 停止视频 |
### 音频
| 名称 | 功能说明 |
| --- | --- |
| [qa.setInnerAudioOption](/api/media/audio/qa.setInnerAudioOption.html) | 设置 [InnerAudioContext](/api/media/audio/InnerAudioContext.html) 的播放选项 |
| [qa.createInnerAudioContext](/api/media/audio/qa.createInnerAudioContext.html) | 创建用于音频播放 [audio](../../../component/audio.html) 的上下文 [InnerAudioContext](/api/media/audio/InnerAudioContext.html) 对象 |
#### InnerAudioContext
| 名称 | 功能说明 |
| --- | --- |
| [InnerAudioContext.destroy](/api/media/audio/InnerAudioContext.destroy.html) | 销毁当前InnerAudioContext实例 |
| [InnerAudioContext.offCanplay](/api/media/audio/InnerAudioContext.offCanplay.html) | 取消订阅**音频进入可以播放状态事件** |
| [InnerAudioContext.offEnded](/api/media/audio/InnerAudioContext.offEnded.html) | 取消订阅**音频自然播放至结束的事件** |
| [InnerAudioContext.offError](/api/media/audio/InnerAudioContext.offError.html) | 取消订阅**音频播放错误事件** |
| [InnerAudioContext.offPause](/api/media/audio/InnerAudioContext.offPause.html) | 取消订阅**音频暂停事件** |
| [InnerAudioContext.offPlay](/api/media/audio/InnerAudioContext.offPlay.html) | 取消订阅**音频播放事件** |
| [InnerAudioContext.offSeeked](/api/media/audio/InnerAudioContext.offSeeked.html) | 取消订阅**音频完成跳转操作的事件** |
| [InnerAudioContext.offSeeking](/api/media/audio/InnerAudioContext.offSeeking.html) | 取消订阅**音频进行跳转操作的事件** |
| [InnerAudioContext.offStop](/api/media/audio/InnerAudioContext.offStop.html) | 取消订阅**音频停止事件** |
| [InnerAudioContext.offTimeUpdate](/api/media/audio/InnerAudioContext.offTimeUpdate.html) | 取消订阅**音频播放进度更新事件** |
| [InnerAudioContext.offWaiting](/api/media/audio/InnerAudioContext.offWaiting.html) | 取消订阅**音频加载中事件** |
| [InnerAudioContext.onCanplay](/api/media/audio/InnerAudioContext.onCanplay.html) | 订阅**音频进入可以播放状态的事件**回调 |
| [InnerAudioContext.onEnded](/api/media/audio/InnerAudioContext.onEnded.html) | 订阅**音频自然播放至结束的事件**回调 |
| [InnerAudioContext.onError](/api/media/audio/InnerAudioContext.onError.html) | 订阅**音频播放错误事件**回调 |
| [InnerAudioContext.onPause](/api/media/audio/InnerAudioContext.onPause.html) | 订阅**音频暂停事件**回调 |
| [InnerAudioContext.onPlay](/api/media/audio/InnerAudioContext.onPlay.html) | 订阅**音频播放事件**回调 |
| [InnerAudioContext.onSeeked](/api/media/audio/InnerAudioContext.onSeeked.html) | 订阅**音频完成跳转操作的事件**回调 |
| [InnerAudioContext.onSeeking](/api/media/audio/InnerAudioContext.onSeeking.html) | 订阅**音频进行跳转操作的事件**回调 |
| [InnerAudioContext.onStop](/api/media/audio/InnerAudioContext.onStop.html) | 订阅**音频停止事件**回调 |
| [InnerAudioContext.onTimeUpdate](/api/media/audio/InnerAudioContext.onTimeUpdate.html) | 订阅**音频播放进度更新事件**回调 |
| [InnerAudioContext.onWaiting](/api/media/audio/InnerAudioContext.onWaiting.html) | 订阅**音频加载中事件**回调 |
| [InnerAudioContext.pause](/api/media/audio/InnerAudioContext.pause.html) | 暂停播放音频 |
| [InnerAudioContext.play](/api/media/audio/InnerAudioContext.play.html) | 播放音频 |
| [InnerAudioContext.seek](/api/media/audio/InnerAudioContext.seek.html) | 跳转到该音频的指定位置 |
| [InnerAudioContext.stop](/api/media/audio/InnerAudioContext.stop.html) | 停止播放音频 |
### 背景音频
| 名称 | 功能说明 |
| --- | --- |
| [qa.stopBackgroundAudio](/api/media/background-audio/qa.stopBackgroundAudio.html) | 停止播放音乐 |
| [qa.seekBackgroundAudio](/api/media/background-audio/qa.seekBackgroundAudio.html) | 控制音乐播放进度 |
| [qa.playBackgroundAudio](/api/media/background-audio/qa.playBackgroundAudio.html) | 使用后台播放器播放音乐 |
| [qa.pauseBackgroundAudio](/api/media/background-audio/qa.pauseBackgroundAudio.html) | 暂停播放音乐 |
| [qa.onBackgroundAudioStop](/api/media/background-audio/qa.onBackgroundAudioStop.html) | 监听音乐停止事件 |
| [qa.onBackgroundAudioPlay](/api/media/background-audio/qa.onBackgroundAudioPlay.html) | 监听音乐播放事件 |
| [qa.onBackgroundAudioPause](/api/media/background-audio/qa.onBackgroundAudioPause.html) | 监听音乐暂停事件 |
| [qa.getBackgroundAudioPlayerState](/api/media/background-audio/qa.getBackgroundAudioPlayerState.html) | 获取后台音乐播放状态 |
| [qa.getBackgroundAudioManager](/api/media/background-audio/qa.getBackgroundAudioManager.html) | 获取**全局唯一**的背景音频管理器 |
#### BackgroundAudioManager
| 名称 | 功能说明 |
| --- | --- |
| [BackgroundAudioManager.onPlay](/api/media/background-audio/BackgroundAudioManager.onPlay.html) | 监听背景音频播放事件 |
| [BackgroundAudioManager.onSeeked](/api/media/background-audio/BackgroundAudioManager.onSeeked.html) | 监听背景音频完成跳转操作事件 |
| [BackgroundAudioManager.onSeeking](/api/media/background-audio/BackgroundAudioManager.onSeeking.html) | 监听背景音频开始跳转操作事件 |
| [BackgroundAudioManager.onStop](/api/media/background-audio/BackgroundAudioManager.onStop.html) | 监听背景音频停止事件 |
| [BackgroundAudioManager.onTimeUpdate](/api/media/background-audio/BackgroundAudioManager.onTimeUpdate.html) | 监听背景音频播放进度更新事件,只有快应用在前台时会回调 |
| [BackgroundAudioManager.onWaiting](/api/media/background-audio/BackgroundAudioManager.onWaiting.html) | 监听音频加载中事件 |
| [BackgroundAudioManager.pause](/api/media/background-audio/BackgroundAudioManager.pause.html) | 暂停音乐 |
| [BackgroundAudioManager.play](/api/media/background-audio/BackgroundAudioManager.play.html) | 播放音乐 |
| [BackgroundAudioManager.seek](/api/media/background-audio/BackgroundAudioManager.seek.html) | 跳转到指定位置 |
| [BackgroundAudioManager.stop](/api/media/background-audio/BackgroundAudioManager.stop.html) | 停止音乐 |
| [BackgroundAudioManager.onCanplay](/api/media/background-audio/BackgroundAudioManager.onCanplay.html) | 监听背景音频进入可播放状态事件 |
| [BackgroundAudioManager.onEnded](/api/media/background-audio/BackgroundAudioManager.onEnded.html) | 监听背景音频自然播放结束事件 |
| [BackgroundAudioManager.onError](/api/media/background-audio/BackgroundAudioManager.onError.html) | 监听背景音频播放错误事件 |
| [BackgroundAudioManager.onPause](/api/media/background-audio/BackgroundAudioManager.onPause.html) | 监听背景音频暂停事件 |
### 录音
| 名称 | 功能说明 |
| --- | --- |
| [qa.stopRecord](/api/media/recorder/qa.stopRecord.html) | 停止录音 |
| [qa.startRecord](/api/media/recorder/qa.startRecord.html) | 开始录音 |
| [qa.getRecorderManager](/api/media/recorder/qa.getRecorderManager.html) | 获取**全局唯一**的录音管理器 RecorderManager |
#### RecorderManager
| 名称 | 功能说明 |
| ----------------------------------------------------------------------------- | ---------------- |
| [RecorderManager.onError](/api/media/recorder/RecorderManager.onError.html) | 订阅**录音错误事件**回调 |
| [RecorderManager.onPause](/api/media/recorder/RecorderManager.onPause.html) | 订阅**录音暂停事件**回调(只支持 Android 7.0 及以上设备) |
| [RecorderManager.onResume](/api/media/recorder/RecorderManager.onResume.html) | 订阅**录音继续事件**回调(只支持 Android 7.0 及以上设备) |
| [RecorderManager.onStart](/api/media/recorder/RecorderManager.onStart.html) | 订阅**录音开始事件**回调 |
| [RecorderManager.onStop](/api/media/recorder/RecorderManager.onStop.html) | 订阅**录音结束事件**回调 |
| [RecorderManager.pause](/api/media/recorder/RecorderManager.pause.html) | 暂停录音 (只支持 Android 7.0 及以上设备) |
| [RecorderManager.resume](/api/media/recorder/RecorderManager.resume.html) | 继续录音 (只支持 Android 7.0 及以上设备) |
| [RecorderManager.start](/api/media/recorder/RecorderManager.start.html) | 开始录音 |
| [RecorderManager.stop](/api/media/recorder/RecorderManager.stop.html) | 停止录音 |
## 位置
| 名称 | 功能说明 |
| --------------------------------------------------------- | -------------------------- |
| [qa.openLocation](/api/location/qa.openLocation.html) | 使用快应用内置地图查看位置 |
| [qa.getLocation](/api/location/qa.getLocation.html) | 获取当前的地理位置、速度 |
| [qa.chooseLocation](/api/location/qa.chooseLocation.html) | 打开地图选择位置 |
## 画布
| 名称 | 功能说明 |
| --- | --- |
| [qa.createCanvasContext](/api/canvas/qa.createCanvasContext.html) | 创建 canvas 的绘图上下文 [CanvasContext](/api/canvas/CanvasContext.html) 对象 |
| [qa.canvasPutImageData](/api/canvas/qa.canvasPutImageData.html) | 将像素数据绘制到画布 |
| [qa.canvasGetImageData](/api/canvas/qa.canvasGetImageData.html) | 获取 canvas 区域隐含的像素数据 |
### CanvasContext
| 名称 | 功能说明 |
| --- | --- |
| [CanvasContext.arc](/api/canvas/CanvasContext.arc.html) | 创建一条弧线 |
| [CanvasContext.arcTo](/api/canvas/CanvasContext.arcTo.html) | 根据控制点和半径绘制圆弧路径 |
| [CanvasContext.beginPath](/api/canvas/CanvasContext.beginPath.html) | 开始创建一个路径 |
| [CanvasContext.bezierCurveTo](/api/canvas/CanvasContext.bezierCurveTo.html) | 创建三次方贝塞尔曲线路径 |
| [CanvasContext.clearRect](/api/canvas/CanvasContext.clearRect.html) | 清除画布上在该矩形区域内的内容 |
| [CanvasContext.clip](/api/canvas/CanvasContext.clip.html) | 从原始画布中剪切任意形状和尺寸 |
| [CanvasContext.closePath](/api/canvas/CanvasContext.closePath.html) | 关闭一个路径 |
| [CanvasContext.createCircularGradient](/api/canvas/CanvasContext.createCircularGradient.html) | 创建一个圆形的渐变颜色 |
| [CanvasContext.createLinearGradient](/api/canvas/CanvasContext.createLinearGradient.html) | 创建一个线性的渐变颜色 |
| [CanvasContext.createPattern](/api/canvas/CanvasContext.createPattern.html) | 对指定的图像创建模式的方法,可在指定的方向上重复元图像 |
| [CanvasContext.draw](/api/canvas/CanvasContext.draw.html) | 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中 |
| [CanvasContext.drawImage](/api/canvas/CanvasContext.drawImage.html) | 绘制图像到画布 |
| [CanvasContext.fill](/api/canvas/CanvasContext.fill.html) | 对当前路径中的内容进行填充 |
| [CanvasContext.fillRect](/api/canvas/CanvasContext.fillRect.html) | 填充一个矩形 |
| [CanvasContext.fillText](/api/canvas/CanvasContext.fillText.html) | 在画布上绘制被填充的文本 |
| [CanvasContext.lineTo](/api/canvas/CanvasContext.lineTo.html) | 增加一个新点,然后创建一条从上次指定点到目标点的线 |
| [CanvasContext.measureText](/api/canvas/CanvasContext.measureText.html) | 测量文本尺寸信息 |
| [CanvasContext.moveTo](/api/canvas/CanvasContext.moveTo.html) | 把路径移动到画布中的指定点,不创建线条 |
| [CanvasContext.quadraticCurveTo](/api/canvas/CanvasContext.quadraticCurveTo.html) | 创建二次贝塞尔曲线路径 |
| [CanvasContext.rect](/api/canvas/CanvasContext.rect.html) | 创建一个矩形路径 |
| [CanvasContext.restore](/api/canvas/CanvasContext.restore.html) | 恢复之前保存的绘图上下文 |
| [CanvasContext.rotate](/api/canvas/CanvasContext.rotate.html) | 以原点为中心顺时针旋转当前坐标轴 |
| [CanvasContext.save](/api/canvas/CanvasContext.save.html) | 保存绘图上下文 |
| [CanvasContext.scale](/api/canvas/CanvasContext.scale.html) | 在调用后,之后创建的路径其横纵坐标会被缩放 |
| [CanvasContext.setFillStyle](/api/canvas/CanvasContext.setFillStyle.html) | 设置填充色 |
| [CanvasContext.setFontSize](/api/canvas/CanvasContext.setFontSize.html) | 设置字体的字号 |
| [CanvasContext.setGlobalAlpha](/api/canvas/CanvasContext.setGlobalAlpha.html) | 设置全局画笔透明度 |
| [CanvasContext.setLineCap](/api/canvas/CanvasContext.setLineCap.html) | 设置线条的端点样式 |
| [CanvasContext.setLineDash](/api/canvas/CanvasContext.setLineDash.html) | 设置虚线样式 |
| [CanvasContext.setLineJoin](/api/canvas/CanvasContext.setLineJoin.html) | 设置线条的交点样式 |
| [CanvasContext.setLineWidth](/api/canvas/CanvasContext.setLineWidth.html) | 设置线条的宽度 |
| [CanvasContext.setMiterLimit](/api/canvas/CanvasContext.setMiterLimit.html) | 设置最大斜接长度 |
| [CanvasContext.setStrokeStyle](/api/canvas/CanvasContext.setStrokeStyle.html) | 设置描边颜色 |
| [CanvasContext.setTextAlign](/api/canvas/CanvasContext.setTextAlign.html) | 设置文字的对齐 |
| [CanvasContext.setTextBaseline](/api/canvas/CanvasContext.setTextBaseline.html) | 设置文字的竖直对齐 |
| [CanvasContext.setTransform](/api/canvas/CanvasContext.setTransform.html) | 使用矩阵重新设置(覆盖)当前变换的方法 |
| [CanvasContext.stroke](/api/canvas/CanvasContext.stroke.html) | 画出当前路径的边框 |
| [CanvasContext.strokeRect](/api/canvas/CanvasContext.strokeRect.html) | 画一个矩形(非填充) |
| [CanvasContext.strokeText](/api/canvas/CanvasContext.strokeText.html) | 给定的 (x, y) 位置绘制文本描边的方法 |
| [CanvasContext.transform](/api/canvas/CanvasContext.transform.html) | 使用矩阵多次叠加当前变换的方法 |
| [CanvasContext.translate](/api/canvas/CanvasContext.translate.html) | 对当前坐标系的原点 (0, 0) 进行变换 |
### CanvasGradient
| 名称 | 功能说明 |
| --------------------------------------------------------------------------- | ---------------- |
| [CanvasGradient.addColorStop](/api/canvas/CanvasGradient.addColorStop.html) | 添加颜色的渐变点 |
| [Image](/api/canvas/Image.html) | 图片对象 |
## 文件
| 名称 | 功能说明 |
| --------------------------------------------------------- | -------------------------------------- |
| [qa.saveFile](/api/file/qa.saveFile.html) | 保存文件到本地 |
| [qa.removeSavedFile](/api/file/qa.removeSavedFile.html) | 删除本地缓存文件 |
| [qa.openDocument](/api/file/qa.openDocument.html) | 新开页面打开文档 |
| [qa.getSavedFileList](/api/file/qa.getSavedFileList.html) | 获取该快应用下已保存的本地缓存文件列表 |
| [qa.getSavedFileInfo](/api/file/qa.getSavedFileInfo.html) | 获取本地文件的文件信息 |
| [qa.getFileInfo](/api/file/qa.getFileInfo.html) | 获取文件信息 |
## 开放接口
### alipay
| 名称 | 功能说明 |
| ---------------------------------------------------------------------- | ------------------ |
| [qa.requestAliPayment](/api/open-api/alipay/qa.requestAliPayment.html) | 使用支付宝完成支付 |
### 登录
| 名称 | 功能说明 |
| ----------------------------------------------------------- | ---------------------------- |
| [qa.login](/api/open-api/login/qa.login.html) | 调用接口获取登录凭证(code) |
### 快应用跳转
| 名称 | 功能说明 |
| ------------------------------------------------------------------------------------------ | ------------------ |
| [qa.navigateToQuickapp](/api/open-api/quickapp-navigate/qa.navigateToQuickapp.html) | 打开另一个快应用 |
| [qa.navigateBackQuickapp](/api/open-api/quickapp-navigate/qa.navigateBackQuickapp.html) | 返回到上一个快应用 |
### 用户信息
| 名称 | 功能说明 |
| ------------------------------------------------------------- | ------------ |
| [qa.getUserInfo](/api/open-api/user-info/qa.getUserInfo.html) | 获取用户信息 |
### 授权
| 名称 | 功能说明 |
| --------------------------------------------------------- | ---------------------- |
| [qa.authorize](/api/open-api/authorize/qa.authorize.html) | 提前向用户发起授权请求 |
### 设置
| 名称 | 功能说明 |
| --- | --- |
| [qa.getSetting](/api/open-api/setting/qa.getSetting.html) | 获取用户的当前设置 |
| [AuthSetting](/api/open-api/setting/AuthSetting.html) | 用户授权设置信息,详情参考[权限](/api/../framework/open-ability/authorize.html) |
### vendorpay
| 名称 | 功能说明 |
| --- | --- |
| [qa.getVendorPaymentProvider](/api/open-api/vendorpay/qa.getVendorPaymentProvider.html) | 获取服务提供商,同步接口 |
| [qa.requestVendorPayment](/api/open-api/vendorpay/qa.requestVendorPayment.html) | 使用设备商提供的支付完成付款 |
### wxpay
| 名称 | 功能说明 |
| ------------------------------------------------------------------- | ------------------------------ |
| [qa.getWxPaymentType](/api/open-api/wxpay/qa.getWxPaymentType.html) | 获取当前可用的微信支付调用方式 |
| [qa.requestWxPayment](/api/open-api/wxpay/qa.requestWxPayment.html) | 发起微信支付 |
## 设备
### Wi-Fi
| 名称 | 功能说明 |
| ---------------------------------------------------------------- | ----------------------------- |
| [qa.stopWifi](/api/device/wifi/qa.stopWifi.html) | 关闭 Wi-Fi 模块 |
| [qa.startWifi](/api/device/wifi/qa.startWifi.html) | 初始化 Wi-Fi 模块 |
| [qa.onWifiConnected](/api/device/wifi/qa.onWifiConnected.html) | 监听连接上 Wi-Fi 的事件 |
| [qa.onGetWifiList](/api/device/wifi/qa.onGetWifiList.html) | 监听获取到 Wi-Fi 列表数据事件 |
| [qa.getWifiList](/api/device/wifi/qa.getWifiList.html) | 请求获取 Wi-Fi 列表 |
| [qa.getConnectedWifi](/api/device/wifi/qa.getConnectedWifi.html) | 获取已连接中的 Wi-Fi 信息 |
| [qa.connectWifi](/api/device/wifi/qa.connectWifi.html) | 连接 Wi-Fi |
| [WifiInfo](/api/device/wifi/WifiInfo.html) | Wifi 信息 |
### 低功耗蓝牙
| 名称 | 功能说明 |
| --- | --- |
| [qa.readBLECharacteristicValue](/api/device/bluetooth-ble/qa.readBLECharacteristicValue.html) | 读取低功耗蓝牙设备的特征值的二进制数据值 |
| [qa.onBLEConnectionStateChange](/api/device/bluetooth-ble/qa.onBLEConnectionStateChange.html) | 监听低功耗蓝牙连接状态的改变事件 |
| [qa.onBLECharacteristicValueChange](/api/device/bluetooth-ble/qa.onBLECharacteristicValueChange.html) | 监听低功耗蓝牙设备的特征值变化事件 |
| [qa.notifyBLECharacteristicValueChange](/api/device/bluetooth-ble/qa.notifyBLECharacteristicValueChange.html) | 启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值 |
| [qa.getBLEDeviceServices](/api/device/bluetooth-ble/qa.getBLEDeviceServices.html) | 获取蓝牙设备所有服务(service) |
| [qa.getBLEDeviceCharacteristics](/api/device/bluetooth-ble/qa.getBLEDeviceCharacteristics.html) | 获取蓝牙设备某个服务中所有特征值(characteristic) |
| [qa.createBLEConnection](/api/device/bluetooth-ble/qa.createBLEConnection.html) | 连接低功耗蓝牙设备 |
| [qa.closeBLEConnection](/api/device/bluetooth-ble/qa.closeBLEConnection.html) | 断开与低功耗蓝牙设备的连接 |
| [qa.writeBLECharacteristicValue](/api/device/bluetooth-ble/qa.writeBLECharacteristicValue.html) | 向低功耗蓝牙设备特征值中写入二进制数据 |
### 联系人
| 名称 | 功能说明 |
| ----------------------------------------------------------------- | -------------------- |
| [qa.addPhoneContact](/api/device/contact/qa.addPhoneContact.html) | 添加手机通讯录联系人 |
### 蓝牙
| 名称 | 功能说明 |
| --- | --- |
| [qa.stopBluetoothDevicesDiscovery](/api/device/bluetooth/qa.stopBluetoothDevicesDiscovery.html) | 停止搜寻附近的蓝牙外围设备 |
| [qa.startBluetoothDevicesDiscovery](/api/device/bluetooth/qa.startBluetoothDevicesDiscovery.html) | 开始搜寻附近的蓝牙外围设备 |
| [qa.openBluetoothAdapter](/api/device/bluetooth/qa.openBluetoothAdapter.html) | 初始化蓝牙模块 |
| [qa.onBluetoothDeviceFound](/api/device/bluetooth/qa.onBluetoothDeviceFound.html) | 监听寻找到新设备的事件 |
| [qa.onBluetoothAdapterStateChange](/api/device/bluetooth/qa.onBluetoothAdapterStateChange.html) | 监听蓝牙适配器状态变化事件 |
| [qa.getConnectedBluetoothDevices](/api/device/bluetooth/qa.getConnectedBluetoothDevices.html) | 根据 uuid 获取处于已连接状态的设备 |
| [qa.getBluetoothDevices](/api/device/bluetooth/qa.getBluetoothDevices.html) | 获取在蓝牙模块生效期间所有已发现的蓝牙设备 |
| [qa.getBluetoothAdapterState](/api/device/bluetooth/qa.getBluetoothAdapterState.html) | 获取本机蓝牙适配器状态 |
| [qa.closeBluetoothAdapter](/api/device/bluetooth/qa.closeBluetoothAdapter.html) | 关闭蓝牙模块 |
### 电量
| 名称 | 功能说明 |
| --- | --- |
| [qa.getBatteryInfoSync](/api/device/battery/qa.getBatteryInfoSync.html) | [qa.getBatteryInfo](/api/device/battery/qa.getBatteryInfo.html) 的同步版本 |
| [qa.getBatteryInfo](/api/device/battery/qa.getBatteryInfo.html) | 获取设备电量 |
### 剪贴板
| 名称 | 功能说明 |
| --------------------------------------------------------------------- | -------------------- |
| [qa.setClipboardData](/api/device/clipboard/qa.setClipboardData.html) | 设置系统剪贴板的内容 |
| [qa.getClipboardData](/api/device/clipboard/qa.getClipboardData.html) | 获取系统剪贴板的内容 |
### 网络
| 名称 | 功能说明 |
| ----------------------------------------------------------------------------- | -------------------- |
| [qa.onNetworkStatusChange](/api/device/network/qa.onNetworkStatusChange.html) | 监听网络状态变化事件 |
| [qa.getNetworkType](/api/device/network/qa.getNetworkType.html) | 获取网络类型 |
### 屏幕
| 名称 | 功能说明 |
| ------------------------------------------------------------------------ | -------------------- |
| [qa.setScreenBrightness](/api/device/screen/qa.setScreenBrightness.html) | 设置屏幕亮度 |
| [qa.setKeepScreenOn](/api/device/screen/qa.setKeepScreenOn.html) | 设置是否保持常亮状态 |
| [qa.onUserCaptureScreen](/api/device/screen/qa.onUserCaptureScreen.html) | 监听用户主动截屏事件 |
| [qa.getScreenBrightness](/api/device/screen/qa.getScreenBrightness.html) | 获取屏幕亮度 |
### 电话
| 名称 | 功能说明 |
| ----------------------------------------------------------- | -------- |
| [qa.makePhoneCall](/api/device/phone/qa.makePhoneCall.html) | 拨打电话 |
### 加速计
| 名称 | 功能说明 |
| ----------------------------------------------------------------------------------- | ------------------ |
| [qa.stopAccelerometer](/api/device/accelerometer/qa.stopAccelerometer.html) | 关闭加速度计监听器 |
| [qa.startAccelerometer](/api/device/accelerometer/qa.startAccelerometer.html) | 启动监听加速度计数据 |
| [qa.onAccelerometerChange](/api/device/accelerometer/qa.onAccelerometerChange.html) | 注册加速度数据回调监听器 |
### 罗盘
| 名称 | 功能说明 |
| ----------------------------------------------------------------- | -------------------- |
| [qa.stopCompass](/api/device/compass/qa.stopCompass.html) | 关闭罗盘监听器 |
| [qa.startCompass](/api/device/compass/qa.startCompass.html) | 启动监听罗盘数据 |
| [qa.onCompassChange](/api/device/compass/qa.onCompassChange.html) | 注册罗盘数据回调监听器 |
### 设备方向
| 名称 | 功能说明 |
| -------------------------------------------------------------------------------------- | ---------------------- |
| [qa.stopDeviceMotionListening](/api/device/motion/qa.stopDeviceMotionListening.html) | 关闭设备方向监听器 |
| [qa.startDeviceMotionListening](/api/device/motion/qa.startDeviceMotionListening.html) | 启动监听设备方向数据 |
| [qa.onDeviceMotionChange](/api/device/motion/qa.onDeviceMotionChange.html) | 注册设备方向变化数据回调监听器 |
### 陀螺仪
| 名称 | 功能说明 |
| ----------------------------------------------------------------------- | ---------------------- |
| [qa.stopGyroscope](/api/device/gyroscope/qa.stopGyroscope.html) | 关闭陀螺仪计监听器 |
| [qa.startGyroscope](/api/device/gyroscope/qa.startGyroscope.html) | 启动监听陀螺仪数据 |
| [qa.onGyroscopeChange](/api/device/gyroscope/qa.onGyroscopeChange.html) | 注册陀螺仪数据回调监听器 |
### 性能
| 名称 | 功能说明 |
| --------------------------------------------------------------------- | -------------------- |
| [qa.onMemoryWarning](/api/device/performance/qa.onMemoryWarning.html) | 监听内存不足告警事件 |
### 扫码
| 名称 | 功能说明 |
| ------------------------------------------------ | -------------------------- |
| [qa.scanCode](/api/device/scan/qa.scanCode.html) | 调起客户端扫码界面进行扫码 |
### 振动
| 名称 | 功能说明 |
| ----------------------------------------------------------- | --------------------------------- |
| [qa.vibrateShort](/api/device/vibrate/qa.vibrateShort.html) | 使手机发生较短时间的振动(15 ms) |
| [qa.vibrateLong](/api/device/vibrate/qa.vibrateLong.html) | 使手机发生较长时间的振动(400 ms) |
## QXML
| 名称 | 功能说明 |
| --- | --- |
| [qa.createSelectorQuery](/api/qxml/qa.createSelectorQuery.html) | 返回一个 SelectorQuery 对象实例 |
| [qa.createIntersectionObserver](/api/qxml/qa.createIntersectionObserver.html) | 创建并返回一个 IntersectionObserver 对象实例 |
### IntersectionObserver
| 名称 | 功能说明 |
| --- | --- |
| [IntersectionObserver.disconnect](/api/qxml/IntersectionObserver.disconnect.html) | 停止监听 |
| [IntersectionObserver.observe](/api/qxml/IntersectionObserver.observe.html) | 指定目标节点并开始监听相交状态变化情况 |
| [IntersectionObserver.relativeTo](/api/qxml/IntersectionObserver.relativeTo.html) | 使用选择器指定一个节点,作为参照区域之一 |
| [IntersectionObserver.relativeToViewport](/api/qxml/IntersectionObserver.relativeToViewport.html) | 指定页面显示区域作为参照区域之一 |
### NodesRef
| 名称 | 功能说明 |
| ------------------------------------------------------------------------- | ------------------------------- |
| [NodesRef.boundingClientRect](/api/qxml/NodesRef.boundingClientRect.html) | 添加节点的布局位置的查询请求 |
| [NodesRef.context](/api/qxml/NodesRef.context.html) | 添加节点的 Context 对象查询请求 |
| [NodesRef.fields](/api/qxml/NodesRef.fields.html) | 获取节点的相关信息 |
| [NodesRef.scrollOffset](/api/qxml/NodesRef.scrollOffset.html) | 添加节点的滚动位置查询请求 |
### SelectorQuery
| 名称 | 功能说明 |
| --- | --- |
| [SelectorQuery.selectViewport](/api/qxml/SelectorQuery.selectViewport.html) | 选择显示区域 |
| [SelectorQuery.exec](/api/qxml/SelectorQuery.exec.html) | 执行所有的请求 |
| [SelectorQuery.in](/api/qxml/SelectorQuery.in.html) | 将选择器的选取范围更改为自定义组件 `component` 内 |
| [SelectorQuery.select](/api/qxml/SelectorQuery.select.html) | 在当前页面下选择第一个匹配选择器 `selector` 的节点 |
| [SelectorQuery.selectAll](/api/qxml/SelectorQuery.selectAll.html) | 在当前页面下选择匹配选择器 selector 的所有节点 |
# qa.getLaunchOptionsSync()
获取快应用启动时的配置选项。与 App.onLaunch 的回调参数一致。
## 返回值
Object
| 属性 | 类型 | 说明 |
| ------------ | ------ | --------------------------------------------------------------------------- |
| path | string | 启动快应用的路径 |
| query | object | 启动快应用的 query 参数 |
| referrerInfo | object | 来源信息。从另一个快应用、App 进入快应用时返回。否则返回 {}。(参见后文注意) |
### referrerInfo 的结构
| 属性 | 类型 | 说明 |
| --------- | ------ | ------------------------------------------------- |
| appId | string | 来源快应用、App 的 appId |
| extraData | object | 来源快应用传过来的数据,scene=1037 或 1038 时支持 |
::: warning 部分版本在无 referrerInfo 的时候会返回 undefined,建议使用 options.referrerInfo && options.referrerInfo.appId 进行判断。 :::
# qa.offAppHide(function callback)
取消监听快应用切后台事件
## 参数
### function callback
快应用切后台事件的回调函数
# qa.offAppShow(function callback)
取消监听快应用切前台事件
## 参数
### function callback
快应用切前台事件的回调函数
# qa.offError(function callback)
取消监听快应用错误事件。
## 参数
### function callback
快应用错误事件的回调函数
# qa.offPageNotFound(function callback)
取消监听快应用要打开的页面不存在事件
## 参数
### function callback
快应用要打开的页面不存在事件的回调函数
# qa.onAppHide(function callback)
监听快应用切后台事件。该事件与 [`App.onHide`](../../../../reference/api/App.html#onhide) 的回调时机一致。
## 参数
### function callback
快应用切后台事件的回调函数
# qa.onAppShow(function callback)
监听快应用切前台事件。该事件与 [`App.onShow`](../../../../reference/api/App.html#onshowobject-object) 的回调参数一致。
## 参数
### function callback
快应用切前台事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ----- | ------ | ------------------------- |
| path | string | 快应用切前台的路径 |
| query | Object | 快应用切前台的 query 参数 |
# qa.onError(function callback)
监听快应用错误事件。如脚本错误或 API 调用报错等。该事件与 [`App.onError`](../../../../reference/api/App.html#onerrorstring-error) 的回调时机与参数一致。
## 参数
### function callback
快应用错误事件的回调函数
#### 参数
##### string error
错误信息,包含堆栈
# console.debug()
向调试面板中打印 debug 日志
## 参数
### any ...args
日志内容,可以有任意多个。
# console.error()
向调试面板中打印 error 日志
## 参数
### any ...args
日志内容,可以有任意多个。
# console.group(string label)
在调试面板中创建一个新的分组。随后输出的内容都会被添加一个缩进,表示该内容属于当前分组。调用 [console.groupEnd](console.groupEnd.html)之后分组结束。
## 参数
### string label
分组标记,可选。
## 注意
仅在工具中有效,在 vConsole 中为空函数实现。
# console.groupEnd()
结束由 [console.group](console.group.html) 创建的分组
## 注意
仅在工具中有效,在 vConsole 中为空函数实现。
# console.info()
向调试面板中打印 info 日志
## 参数
### any ...args
日志内容,可以有任意多个。
# console.log()
向调试面板中打印 log 日志
## 参数
### any ...args
日志内容,可以有任意多个。
# console
向调试面板中打印日志。console 是一个全局对象,可以直接访问。在快应用中,向 vConsole 中输出日志。
## 方法
### [console.debug()](console.debug.html)
向调试面板中打印 debug 日志
### [console.log()](console.log.html)
向调试面板中打印 log 日志
### [console.info()](console.info.html)
向调试面板中打印 info 日志
### [console.warn()](console.warn.html)
向调试面板中打印 warn 日志
### [console.error()](console.error.html)
向调试面板中打印 error 日志
### [console.group(string label)](console.group.html)
在调试面板中创建一个新的分组。随后输出的内容都会被添加一个缩进,表示该内容属于当前分组。调用 [console.groupEnd](console.groupEnd.html)之后分组结束。
### [console.groupEnd()](console.groupEnd.html)
结束由 [console.group](console.group.html) 创建的分组
## 注意
::: warning
- 由于 vConsole 功能有限,以及不同客户端对 console 方法的支持情况有差异,建议开发者在快应用中只使用本文档中提供的方法。
# console.warn()
向调试面板中打印 warn 日志
## 参数
### any ...args
日志内容,可以有任意多个。
# qa.setEnableDebug(Object object)
设置是否打开调试开关。此开关对正式版也能生效。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| enableDebug | boolean | | 是 | 是否打开调试 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
// 打开调试
qa.setEnableDebug({
enableDebug: true
})
// 关闭调试
qa.setEnableDebug({
enableDebug: false
})
```
## Tips
::: warning
- 在正式版打开调试还有一种方法,就是先在开发版或体验版打开调试,再切到正式版就能看到 vConsole。 :::
# string qa.arrayBufferToBase64(ArrayBuffer arrayBuffer)
将 ArrayBuffer 对象转成 Base64 字符串
## 参数
### ArrayBuffer arrayBuffer
要转换成 Base64 字符串的 ArrayBuffer 对象
## 返回值
### string
Base64 字符串
## 示例代码
```js
const arrayBuffer = new Uint8Array([11, 22, 33])
const base64 = qa.arrayBufferToBase64(arrayBuffer)
```
# ArrayBuffer qa.base64ToArrayBuffer(string base64)
将 Base64 字符串转成 ArrayBuffer 对象
## 参数
### string base64
要转化成 ArrayBuffer 对象的 Base64 字符串
## 返回值
### ArrayBuffer
ArrayBuffer 对象
## 示例代码
```js
const base64 = 'CxYh'
const arrayBuffer = qa.base64ToArrayBuffer(base64)
```
# boolean qa.canIUse(string schema)
判断指定API(含调用方式/回调/参数/返回值/返回值的属性)或者组件(含属性)在当前快应用版本是否可用。
## 参数
### string schema
对于API,支持下列调用Schema:
```
`${API}.${method}.${param}.${options}`
```
对于组件,支持下列调用Schema:
```
`${component}.${attribute}.${option}`
```
## 返回值
### boolean
指定API或者组件在当前快应用版本是否可用
## 参数说明
| Schema | 含义 |
| :------------: | :--------------------------------------------------------: |
| `${API}` | API 名字 |
| `${method}` | 调用方式,支持的有效值为 return, success, object, callback |
| `${param}` | 参数 or 返回值 |
| `${options}` | 参数的可选值 |
| `${component}` | 组件名字 |
| `${attribute}` | 组件属性 |
| `${option}` | 组件属性的可选值 |
## 示例代码
```js
qa.canIUse('openBluetoothAdapter')
qa.canIUse('getSystemInfoSync.return.screenWidth')
qa.canIUse('getSystemInfo.success.screenWidth')
qa.canIUse('showToast.object.image')
qa.canIUse('onCompassChange.callback.direction')
qa.canIUse('request.object.method.GET')
qa.canIUse('scroll-view')
qa.canIUse('text.selectable')
qa.canIUse('button.type.primary')
```
# qa.setTrustedUrls(Array array)
为组件 [web-view](/component/web-view.html) 所承载网页,配置可信任的网址(支持正则表达式)。
## 参数
### Array trustedUrlsArray
将认为可信任的网址,以数组的形式传入,届时该网页即可调用 [web-view](/component/web-view.html) 组件中所提供的 API 能力;对于数组中所配置的子项,可以是完整的网页地址,也可以是符合预期的正则表达式([web-view](/component/web-view.html) 的属性 `src` 所指定的链接,默认是可信任的,不必填入)。
## 返回值
无返回值。
## 示例代码
```js
// app.js
qa.setTrustedUrls([
'https://your-domain-name.cn/explore/',
/^https?:\/\/your-domain-name.com/,
/^https?:\/\/(www\.)your-domain-name.com/,
/^https?:\/\/([a-z0-9]*\.)your-domain-name.com/
])
```
# qa.getSystemInfo(Object object)
获取系统信息
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">必填</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ---------------------- | ------- | --------------------------- |
| brand | string | 手机品牌 | |
| model | string | 手机型号 | |
| pixelRatio | number | 手机像素比 | |
| screenWidth | number | 手机屏幕宽度,单位 px | |
| screenHeight | number | 手机屏幕高度,单位 px | |
| windowWidth | number | 手机可使用窗口宽度,单位 px | |
| windowHeight | number | 手机可使用窗口高度,单位 px | |
| statusBarHeight | number | 手机状态栏的高度,单位 px | |
| language | string | 当前手机系统的语言 | |
| version | string | 快应用引擎版本号,字符串类型,比如"1054" | |
| SDKVersion | string | 快应用引擎版本号, number类型,比如1054 | |
| system | string | 手机操作系统及版本 | |
| platform | string | 手机平台,比如"android" | |
| fontSizeSetting | number | 用户设置字体大小(单位 px) | |
| cameraAuthorized | boolean | 当前快应用是否获得摄像头权限 | |
| locationAuthorized | boolean | 当前快应用是否获得定位权限 | |
| microphoneAuthorized | boolean | 当前快应用是否获得麦克风权限 | |
| bluetoothEnabled | boolean | 手机蓝牙的系统权限开关 | |
| locationEnabled | boolean | 手机地理位置的系统开关 | |
| wifiEnabled | boolean | 手机Wi-Fi的系统开关 | |
## 示例代码
```javascript
qa.getSystemInfo({
success(res) {
console.log(res.brand)
console.log(res.pixelRatio)
console.log(res.screenWidth)
console.log(res.screenHeight)
console.log(res.language)
console.log(res.statusBarHeight)
console.log(res.platform)
}
})
```
# Object qa.getSystemInfoSync()
[qa.getSystemInfo](qa.getSystemInfo.html) 的同步版本接口
## 返回值
### Object res
| 属性 | 类型 | 说明 |
| ---------------------- | ------- | --------------------------- |
| brand | string | 手机品牌 | |
| model | string | 手机型号 | |
| pixelRatio | number | 手机像素比 | |
| screenWidth | number | 手机屏幕宽度,单位 px | |
| screenHeight | number | 手机屏幕高度,单位 px | |
| windowWidth | number | 手机可使用窗口宽度,单位 px | |
| windowHeight | number | 手机可使用窗口高度,单位 px | |
| statusBarHeight | number | 手机状态栏的高度,单位 px | |
| language | string | 当前手机系统的语言 | |
| version | string | 快应用引擎版本号,字符串类型,比如"1054" | |
| SDKVersion | string | 快应用引擎版本号, number类型,比如1054 | |
| system | string | 手机操作系统及版本 | |
| platform | string | 手机平台,比如"android" | |
| fontSizeSetting | number | 用户设置字体大小(单位 px) | |
| cameraAuthorized | boolean | 当前快应用是否获得摄像头权限 | |
| locationAuthorized | boolean | 当前快应用是否获得定位权限 | |
| microphoneAuthorized | boolean | 当前快应用是否获得麦克风权限 | |
| bluetoothEnabled | boolean | 手机蓝牙的系统权限开关 | |
| locationEnabled | boolean | 手机地理位置的系统开关 | |
| wifiEnabled | boolean | 手机Wi-Fi的系统开关 | |
## 示例代码
```js
try {
const res = qa.getSystemInfoSync()
console.log(res.model)
console.log(res.pixelRatio)
console.log(res.windowWidth)
console.log(res.windowHeight)
console.log(res.language)
console.log(res.version)
console.log(res.platform)
} catch (e) {
// Do something when catch error
}
```
# clearInterval(number intervalID)
取消由 setInterval 设置的定时器。
## 参数
### number intervalID
要取消的定时器的 ID
# clearTimeout(number timeoutID)
取消由 setTimeout 设置的定时器。
## 参数
### number timeoutID
要取消的定时器的 ID
# number setInterval(function callback, number delay, any rest)
设定一个定时器。按照指定的周期(以毫秒计)来执行注册的回调函数
## 参数
### function callback
回调函数
### number delay
执行回调函数之间的时间间隔,单位 ms。
### any rest
param1, param2, ..., paramN 等附加参数,它们会作为参数传递给回调函数。
## 返回值
### number
定时器的编号。这个值可以传递给 [clearInterval](clearInterval.html) 来取消该定时。
# number setTimeout(function callback, number delay, any rest)
设定一个定时器。在定时到期以后执行注册的回调函数
## 参数
### function callback
回调函数
### number delay
延迟的时间,函数的调用会在该延迟之后发生,单位 ms。
### any rest
param1, param2, ..., paramN 等附加参数,它们会作为参数传递给回调函数。
## 返回值
### number
定时器的编号。这个值可以传递给 [clearTimeout](clearTimeout.html) 来取消该定时。
# CanvasContext.arc(number x, number y, number r, number sAngle, number eAngle, boolean counterclockwise)
创建一条弧线。
- 创建一个圆可以指定起始弧度为 0,终止弧度为 2 \* Math.PI。
-`stroke` 或者 `fill` 方法来在 `canvas` 中画弧线。
## 参数
### number x
圆心的 x 坐标
### number y
圆心的 y 坐标
### number r
圆的半径
### number sAngle
起始弧度,单位弧度(在 3 点钟方向)
### number eAngle
终止弧度
### boolean counterclockwise
弧度的方向是否是逆时针
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// Draw coordinates
ctx.arc(100, 75, 50, 0, 2 * Math.PI)
ctx.setFillStyle('#EEEEEE')
ctx.fill()
ctx.beginPath()
ctx.moveTo(40, 75)
ctx.lineTo(160, 75)
ctx.moveTo(100, 15)
ctx.lineTo(100, 135)
ctx.setStrokeStyle('#AAAAAA')
ctx.stroke()
ctx.setFontSize(12)
ctx.setFillStyle('black')
ctx.fillText('0', 165, 78)
ctx.fillText('0.5*PI', 83, 145)
ctx.fillText('1*PI', 15, 78)
ctx.fillText('1.5*PI', 83, 10)
// Draw points
ctx.beginPath()
ctx.arc(100, 75, 2, 0, 2 * Math.PI)
ctx.setFillStyle('lightgreen')
ctx.fill()
ctx.beginPath()
ctx.arc(100, 25, 2, 0, 2 * Math.PI)
ctx.setFillStyle('blue')
ctx.fill()
ctx.beginPath()
ctx.arc(150, 75, 2, 0, 2 * Math.PI)
ctx.setFillStyle('red')
ctx.fill()
// Draw arc
ctx.beginPath()
ctx.arc(100, 75, 50, 0, 1.5 * Math.PI)
ctx.setStrokeStyle('#333333')
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUIAAACrCAYAAAATkZViAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABKQSURBVHhe7Z3ti1TVH8D9KwTDF70SoQLfZK6BSNGabUu2ZdtGlKUvEkLJfIaEpQhCM1tr3dotjCXXSNLa+ikJWlYgrZXIPlQb7avYRcEetjTd3b4/vzdGp3F27jnnPp6Zz8DgMnMe7vl8z3w8595zz50hvCAAAQjUOIEZNd5+mg8BCEBAECGdAAIQqHkCiLDmuwAAIAABREgfgAAEap4AIqz5LgAACEAAEdIHIACBmieACGu+CwAAAhBAhPQBCECg5gkYiXDGjBnCGwb0AfqAT33Axu7GIrQplLQQgAAEsiSgwrZ5GaW2LdTmAEgLAQhAIG4Cts5ChHFHwKI802CVm45UqqY0fSGtbTkWTSEpBHJFwPS3dfW3YXL0toWalFnraQpSMuEQxr/c98WflX4fVp7JMZEGAnkmYNvHGRFmGE3TYE2XrvB56b/aJESYYWCpOnMCpr8tRoSZh+q/snKZ6haEV250WTwNLi3btpPkABWHAAErArZ9nBGhFd54E9sGq/hcX7nzfsVHV6ls13rjbT2lQSA5ArZ9HBEmF4vQkm2DVSpC06kxI8LQUJCgygjY/rYQYYYdwDRYYRc7wi6WIMIMg0zVmRAw/W1xjjCT8FyrdLpzeJUujJheaa5UdvF3tp0lY2RUDwFjArZ9mxGhMVoSQgACvhBAhL5EiuOEAAQSI4AIE0NLwRCAgC8EEKEvkeI4IQCBxAggwsTQUjAEIOALAUToS6QiHOfAwID09/dHKIGsEKhuAoiwuuMbtA4R1kCQaWIkAogwEj4/MiNCP+LEUWZHABFmxz61mhFhaqipyFMCiNDTwNkcNiK0oUXaWiSACGsg6oiwBoJMEyMRQISR8PmRGRH6ESeOMjsCiDA79qnVjAhTQ01FnhJAhJ4GzvSwDx4UmTv3otxwwyXRv3lBAALXE0CEVdgr/vjjDxkZGZG+vj6ZM+d/MnNm95VnkojMm1eFjaVJEIiBACKMAWIWRVy6dEmOHj0qu3fvlmeeeUYee+wxaWhokAULFsjixYulqalJVq1aJTfdtFVmz94ZiPDmmyfl119/FRWlvsfHx+XixYuiZU1MTMg///yTRVOoEwKZE0CEmYfA/ABGR0elp6dHVq9eLXV1dbJu3TrZv3+/9Pb2yldffSVDQ0MyNjYm58+fv/ru7h6/Miq8ILNmXRL9u/i7cn//9ttv8ueffwZynJqaMj84UkLAYwKIMOfBGxwclNdff12am5tl6dKl0traGowEw4RW/P0333wjp06dsspTyK9i1FEjUsx5R+HwIhFAhJHwJZe5q6tLlixZIi0tLdLW1hac77ORX1wiLC7n999/l7///pspdHJhp+SMCCDCjMBPV213d7fcdttt0tnZKcPDw87yS0KEhTL1PCOjxJx1HA4nEgFEGAlffJkPHTokd9xxh7z44oty9uzZWARYEFeUqXHYKFTPJzJtjq8fUFI2BBBhNtyv1nrs2DFZtmyZbNmyRX7++edYBZiGCAt16AiRq84ZdyaqdyaACJ3RRcuoFy90ycvatWvlzJkziQgwTRFqXXphRa8284KAbwQQYQYR06vAGzduDJa8hE094/g+yalxuePTNYpMlzPoWFTpTAAROqNzy6iLn1977bVUBJj2iLBYinpB5fLly26QyAWBlAkgwpSA6zm0e++9Vz7++ONUJahySntEWCzEv/76KyXCVAMBdwKI0J2dcU49B7hw4cLg2SFxTHVty8hShHqsuv6QCynG3YWEGRBAhAlD/+CDD+TRRx/NRIBZTo1LZa0ynJycTJg2xUPAjQAidONmlOull16S5557LlMJZj01Lj1viAyNug6JUiaACBMCvnfv3tQvikw3Zc56aowME+pkFBsbAUQYG8prBelIsL29PfORYJ6mxsgwgY5GkbERQISxofy3ID0nmIfpcJL3GtterCmXXpfXsNYw5s5Hcc4EEKEzuusz6tXhrC+MlJNOnqbGpbvZcDU5xg5IUc4EEKEzuv9m1HWCukQmjtFS3GXkVYSFpTUxhYBiIOBMABE6o/tvxsbGxszWCYaJM88i1GNn0XVMnZBinAkgQmd01zLqbXNZ3DESJsC8Xiwpd9zcjhdDR6QIZwKI0Bndvxl1A4W07x02FaBPIuTiScSOSPZIBBBhBHy6lZbuImMrprTT531qXOChu9bwgkAWBBBhBOq6n2BaW2lFkacvItQ2MkWO0CHJ6kwAETqi052ldVPVKIJKK69PItTNXVlS49gpyeZMABE6otPt9ZPeWTouUfokQm3zhQsXHKNCNgi4EUCEDtz0QUv6jJG4RJV0Ob6JUHlw14lDxySLMwFE6IDuzjvvTOxBS0lI0UcR6tPxeEEgLQKI0JK0PndYH7mZhLCSKtNHETIqtOyYJI9EABFa4tOHr8f93OGkBOjTOsJyDDhXaNk5Se5MABFaoOvq6pLOzk6vRoMqGF9HhLrImivIFh2UpM4EEKEFuvr6ehkeHkaEV+Sa9Ci2UD7PSbbooCR1JoAIDdENDg5KS0tLagKIUzS+jgjZncawc5IsMgFEaIhQ7ylua2tDhCmOBgv/GbCUxrCTksyZACI0RNfc3Cx9fX2IMAMRctHEsJOSzJkAIjRANzo6KkuXLvVSgj5fLCmMCPW2O14QSJIAIjSg29PTI62trYgwg9Eg02ODDkqSyAQQoQHCp556So4ePYoIMxQhV48NOipJnAkgwhB0+gOsq6vzVoLVMDXWNnDLnfNvnIwGBBBhCCQdCa5btw4RZjgaVBFyntDg10wSZwKIMATd7t27Zf/+/YgwYxGqDLnLxPl3TsYQAogwBJA+mKm3txcR5kCEExMT/KAhkAgBRBiC1Zft+CvdieLznSXF7eKCSSIOoNArBBBhSDdoaGiQoaEhRoQ5GBGysBpnJUUAEYaQXbBggYyNjSHCHIhwfHw8qd8B5dY4gVyL0PTgNF3xuxDT0s9Nyyvk18dLLl682GsJVsvyGW1HHI/7LNdPatwBND/PU+NChy0XpXJCK/6s9HtbARbqHBkZkaamJkSYg9FgHCKMq19gjuojYOuIGSYIbAudrszpOm7h8+nkF1eH100WVq1ahQhzIsKoawnj6hcmvwHS+EXA1lmZilDRTje1qTTlsW1kIYSHDx+WDRs2eC3C0+dPS9dYl3Sc7RD9O859DtMsa/zKs2Imb7lF5MYbRQ4edPqVIUInbDWRydYRuRah6chS0w0MDIS+d+zYIZs3bw62uvf1vefsHtl1flfwViH62o5Ls2bp/4LB++LcuaGxMzmlYtv5a8IINdpI276QqQhLp8SVzgsWx7NcI/v7+yXsvX37dtm0aVOwD6Gv72IRdo51etsOFeHO2bOle+ZMuTBnTmjsEGGNGs2x2V6JsPhqcGl7KzXEtpHVNjVWAaoQfZ8ab5k3T45ckSBTY8dfO9mmJWDriNRGhDbLHEzOG1a6Cj0dHR0Frly50tvzar4/zrP0HKTGQmMS5WXTr6LUQ16/CORWhHnAyPKZ9J5WZ3Lh5f777xeNCS8IxE0AEVYgyoLqfIlw0aJFwt0lcSuA8pQAIgzpB9xilw8Z6nNjdINcXhBIggAiDKHKpgv5EKEud2psbEziN0CZEGBEGNYH2IYrHyI8ceKErFixIixcfA8BJwKMCEOw6Tb9H330kddXjqthP8JDhw7J+vXrnTo5mSAQRgARhhDSrfrfe+89RJjx/cb79u2T9vb2sP7M9xBwIoAIQ7Dx8KZ8TI3XrFkjx48fd+rkZIJAGAFEGELo8uXLoleOTda55TVNNUyN58+fL1NTU2H9me8h4EQAERpgW716tXz66afeytB3EeouQE8//bRBpEgCATcCiNCAmz7Os7W1FRFmdJ5w27ZtcuDAAYNIkQQCbgQQoQE3fWbJ3XffjQgzEmF9fb2cO3fOIFIkgYAbAURoyK25uVm+/vprL2Xo89T45MmT8sgjjxhGiWQQcCOACA257dmzR1599VVEmPKo8OWXX5bOzk7DKJEMAm4EEKEhN3228cMPP4wIUxbh8uXLZXh42DBKJIOAGwFEaMFNzxP++OOP3snQ16mx/uej93rzgkDSBBChBeG33npLOjo6EGFKo0K9k2Tv3r0WESIpBNwIIEJLbj5uy+XjiPCXX36R22+/3TI6JIeAGwFEaMnt3XfflRdeeMGrUaGPItR1mz09PZbRITkE3AggQgdud911l/z000/eyNA3Ef7www/Buk1eEEiLACJ0IK3bcunzjvN6b3Hpcfkmwg0bNsgnn3ziEBmyQMCNACJ04yb6IKHTp097IUOfRKjH+uCDDzpGhWwQcCOACN24yWeffRZsBODDqNAnEeoGF1988YVjVMgGATcCiNCNW5Dr8ccfly+//DL3MvRFhJ9//rk8+eSTESJCVgi4EUCEbtyCXN9++61s3LgREca0rlDPDX733XcRIkJWCLgRQIRu3K7m0nuQ29raci1DH0aEO3fu5J7iiH2R7O4EEKE7u6s5n3322Vw/4CnvIjx48GAwsuYFgawIIMKYyN93331y5syZXI4M8yxCvfLe1NQUUxQoBgJuBBChG7frcuX52SZ5FuGtt97Ks0hi6oMU404AEbqzuy7nwMBAsIlo3pbU5FWEDz30kHz//fcxRoCiIOBGABG6cZs2lz6IfOvWrbmSYR5FuGnTJunt7Y2ZPsVBwI0AInTjVjHXjh07cnUlOW8i3LVrl7zyyisJkKdICLgRQIRu3EJzdXd350aGeRKhCnDfvn2h/EgAgTQJIMIEaevzNrZs2ZL5NDkvItTpMCPBBDscRTsTQITO6Mwyfvjhh9LS0pKpDPMgQr0wwjlBsz5DqvQJIMIUmA8ODorubJ3VOsMsRajrBHWJDFeHU+hoVOFMABE6o7PLODExIcuWLRMdIaa9vCYrEeodI7pYempqyg4WqSGQMgFEmDJwvR1Pr5qmKcMsRKj3DnPbXMqdi+qcCSBCZ3TuGd944w1Zv369nDhxIhUhpilC3UpL28ZD2d37BznTJ4AI02ce1KjbTT3xxBPB5q76d5IjxDREqHXopqq6n6CeF+QFAZ8IIMKMo6UjqAceeCCYRg4PDycixCRFqA9a0n0EdXt9dpbOuDNRvTMBROiMLt6MurSkvr5enn/+eRkdHY1ViEmIUJ87rI/c1KfN8aClePsCpaVPABGmz7xijfos34ULF0pHR0ew5CSOKXOcIhwaGpL29vbg4es8dzhnnYfDcSaACJ3RJZvx7bfflnvuuUd0IbLejXHy5ElnKUYVodatd8ksX75cGhoa5J133km28ZQOgZQJIMKUgdtWp+fg3nzzzWB7ryVLlsi2bdvkyJEjVlJ0EeHhw4eDunS6rnXrVWA9h8kLAtVIABF6FNVz587J+++/H1xpnj9/vqxduzbYwEC3/tKlOLofYrnzi9OJUNNqHs2rZWhZa9asCcrWOg4cOCBaJy8IVDsBROhphCcnJ+XYsWPB+Tpdt7dixQppbGyUuro6WbRoUfAA+pUrVwbfbd68OXjr3/qZfqdpNK3m0bz6nZZ1/Phx7gTxtE9w2O4EEKE7u9zmHB8fl5GREenr6xOd4ur+iNu3bw/+1s/0O03DCwIQ+JcAIqyBnqDT3/7+/hpoKU2EgBsBROjGzatciNCrcHGwGRBAhBlAT7tKRJg2cerzjQAi9C1iDseLCB2gkaWmCCDCGgg3IqyBINPESAQQYSR8fmRGhH7EiaPMjgAizI59ajUjwtRQU5GnBBChp4GzOWxEaEOLtLVIABHWQNQRYQ0EmSZGIoAII+EjMwQgUA0EEGE1RJE2QAACkQggwkj40susgSq8w2otTmuSpzR9oXzbcsKOi+8hkFcCiDCvkSk6rtIghQXN5fviPLb1eYCQQ4RARQJhv5nSzDNMeNoWalJmLaexFdN0/Aufl/6rbBFhLfcw2m7rLESYQZ9xEeF0U2nbz0slmUHzqRICiRNAhIkjjl6BrQivG8ZfOb9Y7rxfcbpKHcG2k0RvMSVAIF0Ctn2cEWG68Qlqi0uEplPjSiLNoPlUCYHECSDCxBFHr8BWhGHpywWdEWH0OFGCvwQQoSexq3Rur1wTpktvk7a4jMLfnuDiMCFgRQARWuEiMQQgUI0EEGE1RpU2QQACVgQQoRUuEkMAAtVIABFWY1RpEwQgYEUAEVrhIjEEIFCNBBITYbkrjnx2beMEWMCCPpCvPmAjeKMF1TYFkhYCEICAbwQQoW8R43ghAIHYCSDC2JFSIAQg4BsBROhbxDheCEAgdgKIMHakFAgBCPhGABH6FjGOFwIQiJ0AIowdKQVCAAK+EUCEvkWM44UABGIngAhjR0qBEICAbwQQoW8R43ghAIHYCfwfXVj7cfNG1F8AAAAASUVORK5CYII=)
针对 arc(100, 75, 50, 0, 1.5 \* Math.PI)的三个关键坐标如下:
- 绿色: 圆心 (100, 75)
- 红色: 起始弧度 (0)
- 蓝色: 终止弧度 (1.5 \* Math.PI)
# CanvasContext.arcTo(number x1, number y1, number x2, number y2, number radius)
根据控制点和半径绘制圆弧路径。
## 参数
### number x1
第一个控制点的 x 轴坐标
### number y1
第一个控制点的 y 轴坐标
### number x2
第二个控制点的 x 轴坐标
### number y2
第二个控制点的 y 轴坐标
### number radius
圆弧的半径
# CanvasContext.beginPath()
开始创建一个路径。需要调用 `fill` 或者 `stroke` 才会使用路径进行填充或描边
- 在最开始的时候相当于调用了一次 `beginPath`
- 同一个路径内的多次 `setFillStyle``setStrokeStyle``setLineWidth`等设置,以最后一次设置为准。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// begin path
ctx.rect(10, 10, 100, 30)
ctx.setFillStyle('yellow')
ctx.fill()
// begin another path
ctx.beginPath()
ctx.rect(10, 40, 100, 30)
// only fill this rect, not in current path
ctx.setFillStyle('blue')
ctx.fillRect(10, 70, 100, 30)
ctx.rect(10, 100, 100, 30)
// it will fill current path
ctx.setFillStyle('red')
ctx.fill()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.bezierCurveTo()
创建三次方贝塞尔曲线路径。曲线的起始点为路径中前一个点。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// Draw points
ctx.beginPath()
ctx.arc(20, 20, 2, 0, 2 * Math.PI)
ctx.setFillStyle('red')
ctx.fill()
ctx.beginPath()
ctx.arc(200, 20, 2, 0, 2 * Math.PI)
ctx.setFillStyle('lightgreen')
ctx.fill()
ctx.beginPath()
ctx.arc(20, 100, 2, 0, 2 * Math.PI)
ctx.arc(200, 100, 2, 0, 2 * Math.PI)
ctx.setFillStyle('blue')
ctx.fill()
ctx.setFillStyle('black')
ctx.setFontSize(12)
// Draw guides
ctx.beginPath()
ctx.moveTo(20, 20)
ctx.lineTo(20, 100)
ctx.lineTo(150, 75)
ctx.moveTo(200, 20)
ctx.lineTo(200, 100)
ctx.lineTo(70, 75)
ctx.setStrokeStyle('#AAAAAA')
ctx.stroke()
// Draw quadratic curve
ctx.beginPath()
ctx.moveTo(20, 20)
ctx.bezierCurveTo(20, 100, 200, 100, 200, 20)
ctx.setStrokeStyle('black')
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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ddmhzKjSUGEJ6HJpO+64o+jb17LckF+WNLNpq1TyU2Rr166VpqYmueaaa7IhSCvRENBH1Zqbm+WPP/7IPCbklznSmhssnfw2ELv99ttl77335mpwzVOo+A3oXt6ee+4p+qxuqA35hSKbvt3Syk+Rffvtt+5K3siRI9MTpGahCVx99dXu5eLfffdd0DiQX1C8qRovtfw2EJs4caK7gfXVV19NBZFKxSOgudac33333bkMHvnlgjlRJ8jvf7h+/vlnueCCC9z5wLfffjsRRAoXh4Dm9phjjnG51pzntSG/vEj794P8NmH11ltvuf8cp59+unzxxRf+JClpmoDK57TTTnO5rccfN+Rnb3ogvyo5mTVrlhxwwAFy8cUXy8qVK+1ljhF5Efjll1/koosukgMPPFBefPFFrzohCiG/EFRraxP5tcNv6tSpcsIJJ8iFF14oH3zwQW20qZ0bgYULF8r555/vcvfYY4/l1m+1jpBf3VOw2QCQn2dOHn/8cTn88MPdlcGnnnrKsxbF8ibw5JNPypFHHin9+/eX6dOn59191f6Qn5lU/DsQ5JcwJ3pPmC6Zv/vuu8utt94qf/31V8IWKJ41gT///FNuueUWd/X23HPPlffeey/rLmpuD/nVjDDzBpBfSqS6vtt1113n7hMcMmSIPPvssylbolpaAs8884ycddZZcsQRR8gNN9yQ69XbpGNGfkmJhS+P/DJgrOJTAXbo0EGGDh0qs2fPzqBVmtgSgZdfftmdf91uu+3k7LPPlueee64QoJCfvTQhvwxzsm7dOnn00Udl8ODBsvPOO7vlkObPn59hD+Vsat68eXL55Ze7RSl0gVo9//r3338XCgbys5cu5BcoJ2vWrBFdCFPPQSlkfWBenydetGhRoB7jaVZXVlFWAwcOdOz0huQHH3zQLUpR1A352csc8sshJx9++KGMHz/eLYXes2dP6dKli7uJ+r777hN9DWLZN2Vw7733OibKRhkpKxWgsothQ372soj8cs6J7r189NFH7urkqaee6q4ad+rUyS23f9lll8nkyZPl66+/znlU+XWnsWmMGqvGrGvnKQNloUyUTZH38KqRRH75zTHfnpCfL6mA5fSViHp/2qhRo9xq0127dpXOnTu754yHDRsmd9xxh1t0QcsVZdOxvvLKK27sl1xyibs/Us+DamwDBgxwsWrMP/zwQ1FC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)
针对 moveTo(20, 20) bezierCurveTo(20, 100, 200, 100, 200, 20) 的三个关键坐标如下:
- 红色:起始点(20, 20)
- 蓝色:两个控制点(20, 100) (200, 100)
- 绿色:终止点(200, 20)
# CanvasContext.clearRect(number x, number y, number width, number height)
清除画布上在该矩形区域内的内容
## 参数
### number x
矩形路径左上角的横坐标
### number y
矩形路径左上角的纵坐标
### number width
矩形路径的宽度
### number height
矩形路径的高度
## 示例代码
clearRect 并非画一个白色的矩形在地址区域,而是清空,为了有直观感受,对 canvas 加了一层背景色。
```html
<canvas canvas-id="myCanvas" style="border: 1px solid; background: #123456;" />
```
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(0, 0, 150, 200)
ctx.setFillStyle('blue')
ctx.fillRect(150, 0, 150, 200)
ctx.clearRect(10, 10, 150, 75)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.clip()
从原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。可以在使用 `clip` 方法前通过使用 `save` 方法对当前画布区域进行保存,并在以后的任意时间通过`restore`方法对其进行恢复。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
qa.downloadFile({
url:
'http://is5.mzstatic.com/image/thumb/Purple128/v4/75/3b/90/753b907c-b7fb-5877-215a-759bd73691a4/source/50x50bb.jpg',
success: function(res) {
ctx.save()
ctx.beginPath()
ctx.arc(50, 50, 25, 0, 2 * Math.PI)
ctx.clip()
ctx.drawImage(res.tempFilePath, 25, 25)
ctx.restore()
ctx.draw()
}
})
```
![](data:image/png;base64,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)
# CanvasContext.closePath()
关闭一个路径。会连接起点和终点。如果关闭路径后没有调用 `fill` 或者 `stroke` 并开启了新的路径,那之前的路径将不会被渲染。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.moveTo(10, 10)
ctx.lineTo(100, 10)
ctx.lineTo(100, 100)
ctx.closePath()
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATwAAACpCAYAAAC22YFCAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAkBSURBVHhe7dtdcttIDEVhLS07c3buKWUmNfmR1SAJkujG5yo/iUSjzwVOyQ9+fPpBAAEEmhB4NLmnayKAAAKfhGcIEECgDQHCaxO1iyKAAOGZAQQQaEOA8NpE7aIIIEB4ZgABBNoQILw2UbsoAgh8KbzH4/HpFwMzYAZmmoGR0t8Kb/SyzxFAAIEqBJ5iHv0Q3oiQzxFAYAoChDdFTJpEAIEMAoSXQVENBBCYggDhTRGTJhFAIIMA4WVQVAMBBKYgQHhTxKRJBBDIIEB4GRTVQACBKQgQ3hQxaRIBBDIIXCa879+/f/o9n0HGUKiBwKoELhPe86CPjw+/JzL49u3bD75+EEDgNYHLhPc8PnKYoPYTeH6DJrz9/Ly5PoGIg1L/tSxy4PrYz7kh4Z3DVdV1CET8kyo83/TOGx7CO4+tymsQuEV4pHfO8BDeOVxVXYfAbcIjvfwhIrx8piquReBW4ZFe7jARXi5P1dYjcLvwSC9vqAgvj6VKaxIoITzSyxkuwsvhqMq6BMoIj/SODxnhHWeowtoESgmP9I4NG+Ed4+ft9QmUEx7p7R86wtvPzps9CJQUHuntGz7C28fNW30IlBUe6W0fQsLbzswbvQiUFh7pbRtGwtvGy9P9CJQXHunFh5Lw4qw82ZPAFMIjvdhwEl6Mk6f6EphGeKQ3HlLCGzPyRG8CUwmP9N4PK+H1Xma3HxOYTnik93WohDceeE/0JjCl8Ejv9dASXu9ldvsxgWmFR3p/h0t444H3RG8CUwuP9H4fXsLrvcxuPyYwvfBI7/+QCW888J7oTWAJ4ZHev0NMeL2X2e3HBJYRHukR3njcPdGdwFLC6y493/C6r7P7jwgsJ7zO0iO80bj7vDuBJYXXVXqE132d3X9EYFnhdZQe4Y3G3efdCSwtvG7SI7zu6+z+IwLLC6+T9AhvNO4+706ghfC6SI/wuq+z+48ItBFeB+kR3mjcfd6dQCvhrS49wuu+zu4/ItBOeCtLj/BG4+7z7gRaCm9V6RFe93V2/xGBtsJbUXqENxp3n3cn0Fp4q0mP8Lqvs/uPCLQX3krSI7zRuPu8OwHC+28CIiCqDwvhVU9If3cTiOz546smIy/ffcEt589+H8LbkrZnOxKI7Hgb4c3+5y3hdVxhd95CgPBe0IpA2QL5qmcJ7yrSzpmVQGS3W33D+xlkBEy10AmvWiL6qUYgstcthTfjn7eEV2299FONAOENEokAqhIq4VVJQh9VCUT2ue03vNn+vCW8qmumryoECC+YRARUsNRpjxHeaWgVXoRAZI/bf8Ob5Zse4S2yla5xGgHC24g2AmxjybTHCS8NpUKLEojsr294f4QfgXbHvBDeHdSdOROByO4S3otEI+CuHgTCu5q482YjENlbwvsi1Qi8KweC8K6k7awZCUR2lvDeJBsBeNVgEN5VpJ0zK4HIvhLeIN0IxCsGhPCuoOyMmQlEdpXwAglHQAbKHHqE8A7h83IDApE9JbzgIERgBkvteozwdmHzUiMCkR0lvA0DEQG6odymRwlvEy4PNyQQ2U/C2zgYEagbS4YeJ7wQJg81JhDZTcLbMSARsDvKvn2F8LKJqrcagcheEt7O1CNwd5Z++RrhZdJUa0UCkZ0kvAPJRwAfKP/bq4SXRVKdVQlE9pHwDqYfgXzwiB+vE14GRTVWJhDZRcJLmIAI6KPHEN5Rgt5fnUBkDwkvaQoisI8cRXhH6Hm3A4HIDhJe4iREgO89jvD2kvNeFwKR/SO85GmIQN9zJOHtoeadTgQiu0d4J0xEBPzWYwlvKzHPdyMQ2TvCO2kqIvC3HE14W2h5tiOByM4R3omTEQkgejzhRUl5riuByL4R3snTEQkh0gLhRSh5pjOByK4R3gUTEgli1AbhjQj5vDuByJ4R3kVTEgnjXSuEd1FQjpmWQGTHCO/CeCOBfNUO4V0YlKOmJBDZL8K7ONpIKK9aIryLg3LcdAQiu0V4N8QaCebPtgjvhqAcORWByF4R3k2RRsL5tTXCuykox05DILJThHdjnJGAfrZHeDcG5egpCET2ifBujjIS0rNFwrs5KMeXJxDZJcIrEGMkKMIrEJQWShOI7BHhFYlwFBbhFQlKG2UJjHbo2TjhFYrvXWCEVygorZQkQHglY3nf1FehEd6EYWr5UgKEdynuvMNeBUd4eXxVWpMA4U2c65/hEd7EYWr9EgKEdwnm8w75NUDCO4+zymsQILwFcvwZIuEtEKYrnEqA8E7Fe13xZ5CEdx1vJ81JgPDmzO1l188wPz4+FrqRqyCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkECC+Xp2oIIFCYAOEVDkdrCCCQS4DwcnmqhgAChQkQXuFwtIYAArkEDgvvWcAvBmbADMwyAyOFPkYP+BwBBBBYhQDhrZKkeyCAwJAA4Q0ReQABBFYhQHirJOkeCCAwJEB4Q0QeQACBVQgQ3ipJugcCCAwJEN4QkQcQQGAVAoS3SpLugQACQwKEN0TkAQQQWIXAPwudrO+tyZqKAAAAAElFTkSuQmCC)
```js
const ctx = qa.createCanvasContext('myCanvas')
// begin path
ctx.rect(10, 10, 100, 30)
ctx.closePath()
// begin another path
ctx.beginPath()
ctx.rect(10, 40, 100, 30)
// only fill this rect, not in current path
ctx.setFillStyle('blue')
ctx.fillRect(10, 70, 100, 30)
ctx.rect(10, 100, 100, 30)
// it will fill current path
ctx.setFillStyle('red')
ctx.fill()
ctx.draw()
```
![](data:image/png;base64,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)
# [CanvasGradient](CanvasGradient.html) CanvasContext.createCircularGradient(number x, number y, number r)
创建一个圆形的渐变颜色。起点在圆心,终点在圆环。返回的`CanvasGradient`对象需要使用 [CanvasGradient.addColorStop()](CanvasGradient.addColorStop.html) 来指定渐变点,至少要两个。
## 参数
### number x
圆心的 x 坐标
### number y
圆心的 y 坐标
### number r
圆的半径
## 返回值
### [CanvasGradient](CanvasGradient.html)
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// Create circular gradient
const grd = ctx.createCircularGradient(75, 50, 50)
grd.addColorStop(0, 'red')
grd.addColorStop(1, 'white')
// Fill with gradient
ctx.setFillStyle(grd)
ctx.fillRect(10, 10, 150, 80)
ctx.draw()
```
![](data:image/png;base64,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)
# [CanvasGradient](CanvasGradient.html) CanvasContext.createLinearGradient(number x0, number y0, number x1, number y1)
创建一个线性的渐变颜色。返回的`CanvasGradient`对象需要使用 [CanvasGradient.addColorStop()](CanvasGradient.addColorStop.html) 来指定渐变点,至少要两个。
## 参数
### number x0
起点的 x 坐标
### number y0
起点的 y 坐标
### number x1
终点的 x 坐标
### number y1
终点的 y 坐标
## 返回值
### [CanvasGradient](CanvasGradient.html)
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// Create linear gradient
const grd = ctx.createLinearGradient(0, 0, 200, 0)
grd.addColorStop(0, 'red')
grd.addColorStop(1, 'white')
// Fill with gradient
ctx.setFillStyle(grd)
ctx.fillRect(10, 10, 150, 80)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.createPattern(string image, string repetition)
对指定的图像创建模式的方法,可在指定的方向上重复元图像
## 参数
### string image
重复的图像源,仅支持包内路径和临时路径
### string repetition
如何重复图像
**repetition 的合法值**
| 值 | 说明 |
| --------- | ------------------ |
| repeat | 水平竖直方向都重复 | |
| repeat-x | 水平方向重复 | |
| repeat-y | 竖直方向重复 | |
| no-repeat | 不重复 | |
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
const pattern = ctx.createPattern('/path/to/image', 'repeat-x')
ctx.fillStyle = pattern
ctx.fillRect(0, 0, 300, 150)
ctx.draw()
```
# CanvasContext.draw(boolean reserve, function callback)
将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。
## 参数
### boolean reserve
本次绘制是否接着上一次绘制。即 reserve 参数为 false,则在本次调用绘制之前 native 层会先清空画布再继续绘制;若 reserve 参数为 true,则保留当前画布上的内容,本次调用 drawCanvas 绘制的内容覆盖在上面,默认 false。
### function callback
绘制完成后执行的回调函数
## 示例代码
第二次 draw() reserve 为 true。所以保留了上一次的绘制结果,在上下文设置的 fillStyle 'red' 也变成了默认的 'black'。
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 100)
ctx.draw()
ctx.fillRect(50, 50, 150, 100)
ctx.draw(true)
```
![](data:image/png;base64,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)
## 示例代码
第二次 draw() reserve 为 false。所以没有保留了上一次的绘制结果和在上下文设置的 fillStyle 'red'。
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 100)
ctx.draw()
ctx.fillRect(50, 50, 150, 100)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.drawImage(string imageResource, number sx, number sy, number sWidth, number sHeight, number dx, number dy, number dWidth, number dHeight)
绘制图像到画布
## 参数
### string imageResource
所要绘制的图片资源
### number sx
源图像的矩形选择框的左上角 x 坐标
### number sy
源图像的矩形选择框的左上角 y 坐标
### number sWidth
源图像的矩形选择框的宽度
### number sHeight
源图像的矩形选择框的高度
### number dx
图像的左上角在目标 canvas 上 x 轴的位置
### number dy
图像的左上角在目标 canvas 上 y 轴的位置
### number dWidth
在目标画布上绘制图像的宽度,允许对绘制的图像进行缩放
### number dHeight
在目标画布上绘制图像的高度,允许对绘制的图像进行缩放
## 示例代码
有三个版本的写法:
- drawImage(imageResource, dx, dy)
- drawImage(imageResource, dx, dy, dWidth, dHeight)
- drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
```js
const ctx = qa.createCanvasContext('myCanvas')
qa.chooseImage({
success: function(res) {
ctx.drawImage(res.tempFilePaths[0], 0, 0, 150, 100)
ctx.draw()
}
})
```
# CanvasContext.fill()
对当前路径中的内容进行填充。默认的填充色为黑色。
## 示例代码
如果当前路径没有闭合,fill() 方法会将起点和终点进行连接,然后填充。
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.moveTo(10, 10)
ctx.lineTo(100, 10)
ctx.lineTo(100, 100)
ctx.fill()
ctx.draw()
```
fill() 填充的的路径是从 beginPath() 开始计算,但是不会将 fillRect() 包含进去。
![](data:image/png;base64,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)
```js
const ctx = qa.createCanvasContext('myCanvas')
// begin path
ctx.rect(10, 10, 100, 30)
ctx.setFillStyle('yellow')
ctx.fill()
// begin another path
ctx.beginPath()
ctx.rect(10, 40, 100, 30)
// only fill this rect, not in current path
ctx.setFillStyle('blue')
ctx.fillRect(10, 70, 100, 30)
ctx.rect(10, 100, 100, 30)
// it will fill current path
ctx.setFillStyle('red')
ctx.fill()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.fillRect(number x, number y, number width, number height)
填充一个矩形。用 [`setFillStyle`](CanvasContext.setFillStyle.html) 设置矩形的填充色,如果没设置默认是黑色。
## 参数
### number x
矩形路径左上角的横坐标
### number y
矩形路径左上角的纵坐标
### number width
矩形路径的宽度
### number height
矩形路径的高度
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 75)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.fillText(string text, number x, number y, number maxWidth)
在画布上绘制被填充的文本
## 参数
### string text
在画布上输出的文本
### number x
绘制文本的左上角 x 坐标位置
### number y
绘制文本的左上角 y 坐标位置
### number maxWidth
需要绘制的最大宽度,可选
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFontSize(20)
ctx.fillText('Hello', 20, 20)
ctx.fillText('QuickApp', 100, 100)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.lineTo(number x, number y)
增加一个新点,然后创建一条从上次指定点到目标点的线。用 `stroke` 方法来画线条
## 参数
### number x
目标位置的 x 坐标
### number y
目标位置的 y 坐标
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.moveTo(10, 10)
ctx.rect(10, 10, 100, 50)
ctx.lineTo(110, 60)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAT0AAACnCAYAAABjEYsMAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAcnSURBVHhe7d3NcdtIFIVRhsAQmImYiahIqMykzDAFu2ZhlyyAVKP/7nEVV6IA9HkP33g2M6fFHwIECAQJnILO6qgECBBYRM8SECAQJSB6UeN2WAIERM8OECAQJSB6UeN2WAIERM8OECAQJSB6UeN2WAIERM8OECAQJfBt9E6n0+LDwA7YgZF2YKvgm9HbuoCfEyBAoBeBNc5bf0RvS8jPCRAYRkD0hhmVByVAoISA6JVQdA0CBIYREL1hRuVBCRAoISB6JRRdgwCBYQREb5hReVACBEoIiF4JRdcgQGAYAdEbZlQelACBEgJVo/f29ra8v7/7dGJQYoFcg8BoAtWit8bufD4vl8tlud1uy/1+92locL1ef/n7QyBNoGr01pfs4+NjeXl5WdaX7vPzM827m/Ou/xASvW7G4UEqClSP3v9nE7+KU/7iVqLX1t/d2wk0i574tRv6emfRa+vv7u0EmkdP/NoMX/TauLtre4Fuoid+dZdB9Op6u1s/At1FT/zqLIfo1XF2l/4Euo2e+B27LKJ3rK+r9yvQffTE75jlEb1jXF21f4Fhoid+ZZdJ9Mp6uto4AsNFT/zKLJfolXF0lfEEho2e+P1s2UTvZ35+e1yB4aMnfs8tn+g95+a3xheYJnri99gyit5jXr49j8B00RO/fcspevucfGs+gWmjJ37fL6vozfcyO9E+gemjJ35fL4Lo7XtBfGs+gZjoid+fyyt6873MTrRPIC564vdbQPT2vSC+NZ9AbPTS4yd6873MTrRPID56qfETvX0viG/NJyB6f8005T9jL3rzvcxOtE9A9P7hNHv8RG/fC+Jb8wmI3sZMZ42f6M33MjvRPgHR2+c03f+6UvR2Dt7XphMQvQdHOsvf/ETvwcH7+jQCovfkKEePn+g9OXi/NryA6P1whKPGT/R+OHi/PqyA6BUa3WjxE71Cg3eZ4QREr/DIRomf6BUevMsNIyB6B42q9/iJ3kGDd9nuBUTv4BH1Gj/RO3jwLt+tgOhVGk1v8RO9SoN3m+4ERK/ySHqJn+hVHrzbdSMgeo1G0Tp+otdo8G7bXED0Go+gVfxEr/Hg3b6ZgOg1o//zxrXjJ3qdDN5jVBcQverk39+wVvxEr7PBe5xqAqJXjfqxGx0dP9F7bB6+PY+A6HU+y6PiJ3qdD97jHSYgeofRlr1w6fiJXtn5uNo4AqI3zqx+PWmp+IneYIP3uMUERK8YZd0L/TR+old3Xu7Wj4Do9TOLp57k2fiJ3lPcfmkCAdGbYIjP/Guv6E0yeMd4WED0Hibr+xf2/s1P9Pqeo6c7TkD0jrNteuWt+Ile0/G4eUMB0WuIX+PW/4qf6NXQd48eBUSvx6kc8Ex/x0/0DkB2ySEEqkbver0u68vm087gdrstl8tlOZ/Py/1+H2JJPSSBkgLVorc+9PqS+fRh8Pr6WnKPXIvAMAJVozeMigclQGBaAdGbdrQORoDAVwKiZy8IEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSEL2ocTssAQKiZwcIEIgSKBK99SI+DOyAHRhlB7Yqf9r6gp8TIEBgJgHRm2mazkKAwKaA6G0S+QIBAjMJiN5M03QWAgQ2BURvk8gXCBCYSUD0ZpqmsxAgsCnwH3JY8ZI8WKJCAAAAAElFTkSuQmCC)
# CanvasContext
canvas 组件的绘图上下文
## 属性
### string fillStyle
填充颜色。用法同 [CanvasContext.setFillStyle()](CanvasContext.setFillStyle.html)
### string strokeStyle
边框颜色。用法同 [CanvasContext.setStrokeStyle()](CanvasContext.setStrokeStyle.html)
### number lineWidth
线条的宽度。用法同 [CanvasContext.setLineWidth()](CanvasContext.setLineWidth.html)
### number lineCap
线条的端点样式。用法同 [CanvasContext.setLineCap()](CanvasContext.setLineCap.html)
### number lineJoin
线条的交点样式。用法同 [CanvasContext.setLineJoin()](CanvasContext.setLineJoin.html)
### number miterLimit
最大斜接长度。用法同 [CanvasContext.setMiterLimit()](CanvasContext.setMiterLimit.html)
### number lineDashOffset
虚线偏移量,初始值为 0
### string font
当前字体样式的属性。符合 [CSS font 语法](https://developer.mozilla.org/zh-CN/docs/Web/CSS/font) 的 DOMString 字符串,至少需要提供字体大小和字体族名。默认值为 10px sans-serif。
### number globalAlpha
全局画笔透明度。范围 0-1,0 表示完全透明,1 表示完全不透明。
### string globalCompositeOperation
在绘制新形状时应用的合成操作的类型。
## 方法
### [CanvasContext.draw(boolean reserve, function callback)](CanvasContext.draw.html)
将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。
### [CanvasGradient CanvasContext.createLinearGradient(number x0, number y0, number x1, number y1)](CanvasContext.createLinearGradient.html)
创建一个线性的渐变颜色。返回的`CanvasGradient`对象需要使用 [CanvasGradient.addColorStop()](CanvasGradient.addColorStop.html) 来指定渐变点,至少要两个。
### [CanvasGradient CanvasContext.createCircularGradient(number x, number y, number r)](CanvasContext.createCircularGradient.html)
创建一个圆形的渐变颜色。起点在圆心,终点在圆环。返回的`CanvasGradient`对象需要使用 [CanvasGradient.addColorStop()](CanvasGradient.addColorStop.html) 来指定渐变点,至少要两个。
### [CanvasContext.createPattern(string image, string repetition)](CanvasContext.createPattern.html)
对指定的图像创建模式的方法,可在指定的方向上重复元图像
### [Object CanvasContext.measureText(string text)](CanvasContext.measureText.html)
测量文本尺寸信息。目前仅返回文本宽度。同步接口。
### [CanvasContext.save()](CanvasContext.save.html)
保存绘图上下文。
### [CanvasContext.restore()](CanvasContext.restore.html)
恢复之前保存的绘图上下文。
### [CanvasContext.beginPath()](CanvasContext.beginPath.html)
开始创建一个路径。需要调用 `fill` 或者 `stroke` 才会使用路径进行填充或描边
- 在最开始的时候相当于调用了一次 `beginPath`
- 同一个路径内的多次 `setFillStyle``setStrokeStyle``setLineWidth`等设置,以最后一次设置为准。
### [CanvasContext.moveTo(number x, number y)](CanvasContext.moveTo.html)
把路径移动到画布中的指定点,不创建线条。用 `stroke` 方法来画线条
### [CanvasContext.lineTo(number x, number y)](CanvasContext.lineTo.html)
增加一个新点,然后创建一条从上次指定点到目标点的线。用 `stroke` 方法来画线条
### [CanvasContext.quadraticCurveTo(number cpx, number cpy, number x, number y)](CanvasContext.quadraticCurveTo.html)
创建二次贝塞尔曲线路径。曲线的起始点为路径中前一个点。
### [CanvasContext.bezierCurveTo()](CanvasContext.bezierCurveTo.html)
创建三次方贝塞尔曲线路径。曲线的起始点为路径中前一个点。
### [CanvasContext.arc(number x, number y, number r, number sAngle, number eAngle, boolean counterclockwise)](CanvasContext.arc.html)
创建一条弧线。
- 创建一个圆可以指定起始弧度为 0,终止弧度为 2 \* Math.PI。
-`stroke` 或者 `fill` 方法来在 `canvas` 中画弧线。
### [CanvasContext.rect(number x, number y, number width, number height)](CanvasContext.rect.html)
创建一个矩形路径。需要用 [`fill`](CanvasContext.fill.html) 或者 [`stroke`](CanvasContext.stroke.html) 方法将矩形真正的画到 `canvas`
### [CanvasContext.arcTo(number x1, number y1, number x2, number y2, number radius)](CanvasContext.arcTo.html)
根据控制点和半径绘制圆弧路径。
### [CanvasContext.clip()](CanvasContext.clip.html)
从原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。可以在使用 `clip` 方法前通过使用 `save` 方法对当前画布区域进行保存,并在以后的任意时间通过`restore`方法对其进行恢复。
### [CanvasContext.fillRect(number x, number y, number width, number height)](CanvasContext.fillRect.html)
填充一个矩形。用 [`setFillStyle`](CanvasContext.setFillStyle.html) 设置矩形的填充色,如果没设置默认是黑色。
### [CanvasContext.strokeRect(number x, number y, number width, number height)](CanvasContext.strokeRect.html)
画一个矩形(非填充)。 用 [`setStrokeStyle`](CanvasContext.setStrokeStyle.html) 设置矩形线条的颜色,如果没设置默认是黑色。
### [CanvasContext.clearRect(number x, number y, number width, number height)](CanvasContext.clearRect.html)
清除画布上在该矩形区域内的内容
### [CanvasContext.fill()](CanvasContext.fill.html)
对当前路径中的内容进行填充。默认的填充色为黑色。
### [CanvasContext.stroke()](CanvasContext.stroke.html)
画出当前路径的边框。默认颜色色为黑色。
### [CanvasContext.closePath()](CanvasContext.closePath.html)
关闭一个路径。会连接起点和终点。如果关闭路径后没有调用 `fill` 或者 `stroke` 并开启了新的路径,那之前的路径将不会被渲染。
### [CanvasContext.scale(number scaleWidth, number scaleHeight)](CanvasContext.scale.html)
在调用后,之后创建的路径其横纵坐标会被缩放。多次调用倍数会相乘。
### [CanvasContext.rotate(number rotate)](CanvasContext.rotate.html)
以原点为中心顺时针旋转当前坐标轴。多次调用旋转的角度会叠加。原点可以用 `translate` 方法修改。
### [CanvasContext.translate(number x, number y)](CanvasContext.translate.html)
对当前坐标系的原点 (0, 0) 进行变换。默认的坐标系原点为页面左上角。
### [CanvasContext.drawImage(string imageResource, number sx, number sy, number sWidth, number sHeight, number dx, number dy, number dWidth, number dHeight)](CanvasContext.drawImage.html)
绘制图像到画布
### [CanvasContext.strokeText(string text, number x, number y, number maxWidth)](CanvasContext.strokeText.html)
给定的 (x, y) 位置绘制文本描边的方法
### [CanvasContext.transform(number scaleX, number scaleY, number skewX, number skewY, number translateX, number translateY)](CanvasContext.transform.html)
使用矩阵多次叠加当前变换的方法
### [CanvasContext.setTransform(number scaleX, number scaleY, number skewX, number skewY, number translateX, number translateY)](CanvasContext.setTransform.html)
使用矩阵重新设置(覆盖)当前变换的方法
### [CanvasContext.setFillStyle(Color color)](CanvasContext.setFillStyle.html)
设置填充色。
### [CanvasContext.setStrokeStyle(Color color)](CanvasContext.setStrokeStyle.html)
设置描边颜色。
### [CanvasContext.setGlobalAlpha(number alpha)](CanvasContext.setGlobalAlpha.html)
设置全局画笔透明度。
### [CanvasContext.setLineWidth(number lineWidth)](CanvasContext.setLineWidth.html)
设置线条的宽度
### [CanvasContext.setLineJoin(string lineJoin)](CanvasContext.setLineJoin.html)
设置线条的交点样式
### [CanvasContext.setLineCap(string lineCap)](CanvasContext.setLineCap.html)
设置线条的端点样式
### [CanvasContext.setLineDash(Array.\<number> pattern, number offset)](CanvasContext.setLineDash.html)
设置虚线样式。
### [CanvasContext.setMiterLimit(number miterLimit)](CanvasContext.setMiterLimit.html)
设置最大斜接长度。斜接长度指的是在两条线交汇处内角和外角之间的距离。当 [CanvasContext.setLineJoin()](CanvasContext.setLineJoin.html) 为 miter 时才有效。超过最大倾斜长度的,连接处将以 lineJoin 为 bevel 来显示。
### [CanvasContext.fillText(string text, number x, number y, number maxWidth)](CanvasContext.fillText.html)
在画布上绘制被填充的文本
### [CanvasContext.setFontSize(number fontSize)](CanvasContext.setFontSize.html)
设置字体的字号
### [CanvasContext.setTextAlign(string align)](CanvasContext.setTextAlign.html)
设置文字的对齐
### [CanvasContext.setTextBaseline(string textBaseline)](CanvasContext.setTextBaseline.html)
设置文字的竖直对齐
# Object CanvasContext.measureText(string text)
测量文本尺寸信息。目前仅返回文本宽度。同步接口。
## 参数
### string text
要测量的文本
## 返回值
### Object
| 属性 | 类型 | 说明 |
| ----- | ------ | ---------- |
| width | number | 文本的宽度 |
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.font = 'italic bold 20px cursive'
const metrics = ctx.measureText('Hello World')
console.log(metrics.width)
```
# CanvasContext.moveTo(number x, number y)
把路径移动到画布中的指定点,不创建线条。用 `stroke` 方法来画线条
## 参数
### number x
目标位置的 x 坐标
### number y
目标位置的 y 坐标
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.moveTo(10, 10)
ctx.lineTo(100, 10)
ctx.moveTo(10, 50)
ctx.lineTo(100, 50)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.quadraticCurveTo(number cpx, number cpy, number x, number y)
创建二次贝塞尔曲线路径。曲线的起始点为路径中前一个点。
## 参数
### number cpx
贝塞尔控制点的 x 坐标
### number cpy
贝塞尔控制点的 y 坐标
### number x
结束点的 x 坐标
### number y
结束点的 y 坐标
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// Draw points
ctx.beginPath()
ctx.arc(20, 20, 2, 0, 2 * Math.PI)
ctx.setFillStyle('red')
ctx.fill()
ctx.beginPath()
ctx.arc(200, 20, 2, 0, 2 * Math.PI)
ctx.setFillStyle('lightgreen')
ctx.fill()
ctx.beginPath()
ctx.arc(20, 100, 2, 0, 2 * Math.PI)
ctx.setFillStyle('blue')
ctx.fill()
ctx.setFillStyle('black')
ctx.setFontSize(12)
// Draw guides
ctx.beginPath()
ctx.moveTo(20, 20)
ctx.lineTo(20, 100)
ctx.lineTo(200, 20)
ctx.setStrokeStyle('#AAAAAA')
ctx.stroke()
// Draw quadratic curve
ctx.beginPath()
ctx.moveTo(20, 20)
ctx.quadraticCurveTo(20, 100, 200, 20)
ctx.setStrokeStyle('black')
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
针对 moveTo(20, 20) quadraticCurveTo(20, 100, 200, 20) 的三个关键坐标如下:
- 红色:起始点(20, 20)
- 蓝色:控制点(20, 100)
- 绿色:终止点(200, 20)
# CanvasContext.rect(number x, number y, number width, number height)
创建一个矩形路径。需要用 [`fill`](CanvasContext.fill.html) 或者 [`stroke`](CanvasContext.stroke.html) 方法将矩形真正的画到 `canvas`
## 参数
### number x
矩形路径左上角的横坐标
### number y
矩形路径左上角的纵坐标
### number width
矩形路径的宽度
### number height
矩形路径的高度
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.rect(10, 10, 150, 75)
ctx.setFillStyle('red')
ctx.fill()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.restore()
恢复之前保存的绘图上下文。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// save the default fill style
ctx.save()
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 100)
// restore to the previous saved state
ctx.restore()
ctx.fillRect(50, 50, 150, 100)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.rotate(number rotate)
以原点为中心顺时针旋转当前坐标轴。多次调用旋转的角度会叠加。原点可以用 `translate` 方法修改。
## 参数
### number rotate
旋转角度,以弧度计 degrees \* Math.PI/180;degrees 范围为 0-360
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.strokeRect(100, 10, 150, 100)
ctx.rotate((20 * Math.PI) / 180)
ctx.strokeRect(100, 10, 150, 100)
ctx.rotate((20 * Math.PI) / 180)
ctx.strokeRect(100, 10, 150, 100)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.save()
保存绘图上下文。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// save the default fill style
ctx.save()
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 100)
// restore to the previous saved state
ctx.restore()
ctx.fillRect(50, 50, 150, 100)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.scale(number scaleWidth, number scaleHeight)
在调用后,之后创建的路径其横纵坐标会被缩放。多次调用倍数会相乘。
## 参数
### number scaleWidth
横坐标缩放的倍数 (1 = 100%,0.5 = 50%,2 = 200%)
### number scaleHeight
纵坐标轴缩放的倍数 (1 = 100%,0.5 = 50%,2 = 200%)
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.strokeRect(10, 10, 25, 15)
ctx.scale(2, 2)
ctx.strokeRect(10, 10, 25, 15)
ctx.scale(2, 2)
ctx.strokeRect(10, 10, 25, 15)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setFillStyle([Color](Color.html) color)
设置填充色。
## 参数
### [Color](Color.html) color
填充的颜色,默认颜色为 black。
## 代码示例
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 75)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setFontSize(number fontSize)
设置字体的字号
## 参数
### number fontSize
字体的字号
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFontSize(20)
ctx.fillText('20', 20, 20)
ctx.setFontSize(30)
ctx.fillText('30', 40, 40)
ctx.setFontSize(40)
ctx.fillText('40', 60, 60)
ctx.setFontSize(50)
ctx.fillText('50', 90, 90)
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAT8AAACsCAYAAAANI6vyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABJ2SURBVHhe7Z3dyxbFG8f9BzrxrKOORDyQDkQCJeyh0KBAA+3loKzowRAJrLCSSkiIit6gAyM8MNTyoMJCjAKxMBLTDkKz0KxALXtRLHuT0vn9vgNzM8+6e+/sPbu3O7ufgQefnp2Znflcw7fZmWuumWZIEIAABHpIYFoP+0yXIQABCBjEj0EAAQj0kgDi10uz02kIQADxYwxAAAK9JID49dLsdBoCEED8GAMQgEAvCQwVv2nTphl+YMAYYAykNAZClbxU/EIrIh8EIACBy01AIh2aEL9QUuSDAARaTwDxa72JaCAEINAEAcSvCarUCQEItJ4A4td6E9FACECgCQKIXxNUqRMCEGg9AcSv9SaigRCAQBMEkhC/X3/91SxatGjgR3j11Vebr7/+OpfHU089Ncin30kQgAAE8gi0XvwkcgsXLpwidlu2bDF5AiixW7Fihfnrr7/sj35HABn4EIBAkuIn8ZLY+ckJm//3Tz755BJBlHBKJPWMBAEIQMAn0PqZn8Qvb/aWFUV/1uc6yOyPwQ4BCBQRSEL8tN6ndb+sqLkZXd5M0OXNE0WGAwQgAIHWi1+eiSR6bm1Pz92GSPbzWM/0t6x4YnYIQAACyYmfhE7C588EET8GMgQgUJVAUuKXJ3zM/KqanPwQgIAIJCN+RcKnTrDmx2CGAASqEkhC/IYJ37CNDXZ7qw4H8kOgPwRaL34SMO3Y+mt8bra3ffv2gaXw8+vPoKWnEKiDQOvF78UXX8w9yiaxy+7ucsKjjiFBHRDoB4FWi1/2TG/2boC8kxuc7e3HwKWXEIgl0Grxi+3csPIXLlwwn376qbnnnnvM9OnT7c7PggULzKZNm8wff/xR+mp9jm/YsMFcc801tqz+1X/r7yQIQKD9BHopfv/++6957rnnzJo1a8yJEyfMxYsXzfnz5817771nZs6cae68807z888/F1rv9OnTZnJy0gZc+PLLL23548eP23JlZds/JGghBPpBoJfip42SiYkJc/LkyUusrGdXXHGFWbt2rZFIZpP+tn79ejNr1izzxRdfTHksIVW9RWX7MaToJQTSINA78fv777/NypUrzXXXXZcrfr/88ou58cYbc0NmyaT79+83V111lXniiSfMf//9d4mVX331VXPllVeaffv2pTECaCUEekqgd+LnfP/U8W3btl1idv95dkNFYifRGyZumg3OmDGjUBx7Os7oNgRaR6B34qf1uTfffNOu7WkWl01O/CRg2c9afSZrxnjDDTcUrglqrVDPNXvULJIEAQi0k0DvxK/MDE7gbrnlFnPmzJkp2Q8cOGBnfX5EmSriWfZunkMAAuMjgPh5rDUr3Lx5s3V90c5vNr377rvWrWVYaHzVsW7dOpuPCNLjG8i8CQJVCSB+/ycmnz/N+OT+Mm/ePLNr1y7rvpJNOlEiYE8//fRQzs7ROi++YFUDkR8CEGiGQO/FT7Mzd3JETs4ffvhhrouL8DvxKxM1xK+ZwUqtEKiTQO/Fz8E8d+6c2bNnj1m2bJnRet/3339fOPND/OocgtQFgctDAPHLcNfRNp3ekLOynJb95GZ+ZddhMvO7PIOZt0KgCgHEL4eWHJS1q/vCCy9MWfuL3fD46quvzDPPPGOOHDlSxUbmn3/+MW+99ZZ1n9HpE/0sWbLEvPPOO/YZCQIQqE4A8cth5txdbrrppinuLs7VRSdEdFIkLzk/wdmzZxuJnUu//fabueuuuyrvAuvzW5/hOlWinWjVryN2WpucO3cuZ4mrj3lKQMAS6J34uaAG119/fe66nqC4UFq68FwXn7vkRHGYA7NzcvaFUzvHr7322mBjJdQF5tSpU2bx4sV2prdz585LdqAPHz5sj+Epj/KSIACBcAK9Ez+JmQRDHdenZF4qOsnhH2/TLDAvueNtCn7g3GWcSLld5RDxk0grQILKPPTQQ7mft6pfn+bKo8/pvEAM4UOBnBDoF4Heip+ishw6dCjX2m7NTyGvFOrKT0XrgcrjxEifqO7onD5TV61aZe6//36jT+FQ52f3nrIgCeqD+uK/s19DmN5CYDQCvRM/J0ZF53O126s1PQUn1Ywtm1xIK80es8+/++47M3/+/CmzMIXIuu2228zevXsHM86ymZ82MR544AErlEuXLjVnz54ttO7vv/9u1/2UtyjSzGhDg1IQ6DaB3omfzKn1MfnzPfzww4NgpjrlcezYMbN69Wob9ODjjz8utHw2mKkre8cdd1jhdJGg5SqjtT+Jnf+5XSZ+33777SBCtO4wKUs6cSJDFoXpKivPcwj0kUAvxU+GlkBt3bp14D4iEDrh8fzzzw+N4uwGiWZnb7zxRmEYezdD1JE5rRVWET/nUqM2aVe3LPn5h4l2WT08h0CfCPRW/Jo2smZ3+mT98ccf7auqiJ+byWXdZYrarE9q7QjLmAqmSoIABMoJIH7ljCrnUCgsrfN98MEHg7Kh4ucHUw39jPXrfuyxx3IjTFfuBAUg0HECiF/NBnY+fVn3lFDx86/rXLRo0SWXtec1V47QikYjYw6LNVhzV6kOAkkTQPxqNp92gLXJkT3CFip+zkk6ZKfXNd0XzOyplJq7R3UQ6AwBxK9GU2oTRTMvhcnPplDx8/OFzuJGmS3W2G2qgkCSBBC/Gs0m0ZNg5V16jvjVCJqqIFADAcSvBoiqQg7O+uTMXnrkqkf8agJNNRCoiQDiVwNIdw735Zdfzg1/r1eEip//CVt2uoM1vxqMRxW9JYD41WB63fkh1xZtVhSlUcQvdLf36NGjZs6cOez21mBLqugPAcQv0tYSPB1rKzuyFip++PlFGoTiEAgkgPgFgirK9sorr9gjbgpdr7BSRT+KEKMILQKuKC9+vh07dgyq96++5IRHpHEoDoEhBBC/yOGhi4+0Tlf289lnnw1CWr3//vtT8qsOP1U927tt2zYrqjriVjYDjewuxSHQGQKI35hMGfrZm90cqRLVRWG6fvjhhzH1iNdAIG0CiN+Y7FdF/Px4forVp5h9RYl4fmMyIK/pHAHEb0wmrSJ+apJCU2mNsCySswubr2jORT6GY+oir4FAUgQQvzGZq6r4+Xd46C6PvPs5FCfQhb9ycQPH1B1eA4HkCSB+YzJhVfFTs9ztbZr9yZcwmz766CN7d4d8DB999NHB7XAyapWfGTNmVJ41Sox3795tli9fbtug9+lf/bcCsHKf8JgGFq8ZmQDiNzK6agUlXs7VJXsZ+rCaFAxV637Ze3sVK1D3iOjZ8ePHbfj8KoLn5y26z6SoXbqP+Oabb7a7y4888shgk0VnmnW3sNqqu4YVaosEgbYSQPwasoxE66WXXrL+fLorxM2OnEuKHKP1THlctOeipmgWJfeYJUuWWMHRj37X3/TMd4weRQCHXcKebdPBgwcHofuLrst0M1L5Pyo/CQJtJID4NWQV7cLu2bPHfhoO+1GeYbu5Ic1z4rdly5aQ7CPncbfTadBMTk7mRq9R5XLU1jln5ZuYmLCXRJEg0DYCiF/bLDJCe1wwhCbFTzNMRafWgCnbgVYX/Bvoii5dH6GrFIFAbQQQv9pQXr6KxiF+zvVGA+buu+8unPU5CtqJ1j3CTiy5Ve7yjQ/enE8A8evAyHDi19TRtuya4ttvvx1ETbu+bg1Sl7CzAxyEjUxjIoD4jQl0k69xbjRNiZ9zpNZg0Q6z3heS/IuV5IR96NChkGLkgcBYCCB+Y8Hc7EuaFj/dBexmcGXH7fye+kfvVL7JNclmCVN7Fwkgfh2wqsRv4cKFwTOyKl3OfvKuW7euMFp1tl6t++keYSecq1evNufPn6/yevJCoDECiF9jaMdXsT53q3yOVmnZyZMnjS5PdwL2+uuvVyluFJXGleVazUroyNwwAcSvYcDjqL5J8Ttw4MDgZIoGS9VdW33qOvFrSqDHwZh3dI8A4tcBm0r8/Ps+Lly4YCRajz/+uLn22mvtiRB39vbWW281O3futKdCQpK/Y6s6qm6qSCyd+Kkde/fuDXkteSDQOAHEr3HEzb9AsysnfrpT5N577y095zt//nzz+eeflzYuduYmsfSP3FWdOZY2kAwQGJEA4jciuDYVc+InV5LFixebmTNn2rU2HUdzobD07zfffGPPGfszQZ3DHZb8nd5RPluz4seOb5tGTr/bgvh1wP4SFEVRUbAEuaIMC5QgEdy4ceNAABV84MiRI4UUdDFTzJod4teBAdbRLiB+HTCsEyjtppZFiFF3s+4rOoYmt5S8hPh1YIDQhVwCiF8HBsazzz5rZ3KK8Rea9u3bN9jF1exPgQgQv1B65OsCAcSvC1YcoQ9nzpyxn8ruk1bXZeYl+fXx2TsCYIq0ngDi13oTNdPA7OkLfd7mpbp3e6u6yjTTe2qFgLH/Uw9NQ3NWqSj0heRrloA/q1uxYkWu71+dfn6KAyj/QxIE2kCgimYhfm2wWI1t8Gd1ReJX5wmPOXPmmKNHj9bYA6qCwOgEEL/R2SVfMkT8/LBUo0Rm4Wxv8sOksx1A/BI3rTvRod3eBx98sDTCst/dEPHLhqUqWhvMw5hdV1SElyKXmsTNQPMTJID4JWg012SFh1qzZs1gN7bqmpovfsNCVfmztyrx/M6ePWuWLl06aB+nOxIebB1sOuKXsFFd+Hr/7GyRy0peN30H5mGhqvx1v3nz5gXfx6v1Pa3zqX3DfAkTNgFNT5gA4pew8bLiVyVU/J9//mnuu+++wQVDw3ZhdRm5Li0q8wnMovR3irnBLeGB1tGmI34JGzZ7TG39+vWDQAZl3fKvlgy5jU2nR1xAhJDLiPz1Pl3Yvn///rIm8RwCYyWA+I0Vd/0v2759+0CUqjgQK7iBjC9BUx1lSUK7atWqQVzAMjHzxbWKKJe1g+cQqIsA4lcXyctUjz5JV65caUVJn5kh6cSJE2ZiYsKWUVnVEZIUIktxAMvKKXKMBE/5FGLr1KlTIdWTBwJjJYD4jRV3My87ffq0FTFFdTl27NjQlyjv5OSkFaZly5ZVFqaDBw/azQvNGDdv3mwUNdpPFy9eNLt27TL61FW+w4cPN9NpaoVAJAHELxJgW4rrQvCtW7ea2bNnm7Vr1xpFbTl37tygeXI72bFjh5k7d64VLuWRD98oSY7PCoqgep588knz008/2WoULGHDhg1m+vTp9rnykSDQVgKIX1stM2K7tDanzQltYiiis9uh1e+33367DWTqxGrEV9hi+rTVGqN2jN17NNtbvny52b17d/DGS0wbKAuBGAKIXww9ykIAAskSQPySNR0NhwAEYgggfjH0KAsBCCRLAPFL1nQ0HAIQiCGA+MXQoywEIJAsAcQvWdPRcAhAIIYA4hdDj7IQgECyBBC/ZE1HwyEAgRgCiF8MPcpCAALJEkD8kjUdDYcABGIIIH4x9CgLAQgkSwDxS9Z0NBwCEIghgPjF0KMsBCCQLAHEL1nT0XAIQCCGAOIXQ4+yEIBAsgQQv2RNR8MhAIEYAohfDD3KQgACyRJA/JI1HQ2HAARiCCB+MfQoCwEIJEsA8UvWdDQcAhCIIYD4xdCjLAQgkCwBxC9Z09FwCEAghgDiF0OPshCAQLIEEL9kTUfDIQCBGAKIXww9ykIAAskSQPySNR0NhwAEYgggfjH0KAsBCCRLAPFL1nQ0HAIQiCGA+MXQoywEIJAsAcQvWdPRcAhAIIYA4hdDj7IQgECyBBC/ZE1HwyEAgRgCiF8MPcpCAALJEkD8kjUdDYcABGIIIH4x9CgLAQgkSwDxS9Z0NBwCEIghgPjF0KMsBCCQLAHEL1nT0XAIQCCGAOIXQ4+yEIBAsgQQv2RNR8MhAIEYAohfDD3KQgACyRJA/JI1HQ2HAARiCCB+MfQoCwEIJEsA8UvWdDQcAhCIIYD4xdCjLAQgkCwBxC9Z09FwCEAghgDiF0OPshCAQLIEEL9kTUfDIQCBGAKIXww9ykIAAskSQPySNR0NhwAEYgggfjH0KAsBCCRLAPFL1nQ0HAIQiCGA+MXQoywEIJAsAcQvWdPRcAhAIIYA4hdDj7IQgECyBBC/ZE1HwyEAgRgCiF8MPcpCAALJEkD8kjUdDYcABGIIIH4x9CgLAQgkSwDxS9Z0NBwCEIghgPjF0KMsBCCQLIFaxU+V8QMDxgBjIJUxEKrc00Izkg8CEIBAlwggfl2yJn2BAASCCSB+wajICAEIdIkA4tcla9IXCEAgmADiF4yKjBCAQJcIIH5dsiZ9gQAEggkgfsGoyAgBCHSJAOLXJWvSFwhAIJgA4heMiowQgECXCCB+XbImfYEABIIJIH7BqMgIAQh0iQDi1yVr0hcIQCCYAOIXjIqMEIBAlwj8Dwo+0HXAqd4uAAAAAElFTkSuQmCC)
# CanvasContext.setGlobalAlpha(number alpha)
设置全局画笔透明度。
## 参数
### number alpha
透明度。范围 0-1,0 表示完全透明,1 表示完全不透明。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 100)
ctx.setGlobalAlpha(0.2)
ctx.setFillStyle('blue')
ctx.fillRect(50, 50, 150, 100)
ctx.setFillStyle('yellow')
ctx.fillRect(100, 100, 150, 100)
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUIAAACuCAYAAABDXATRAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAjPSURBVHhe7dtBjhpLEARQ5jZe4/sfgfUcp20WlrxiVE0WFVn9RmL1oUiiyacA/G+HPwlIQAIXT+B28dfv5UtAAhI4QOhNIAEJXD4BEF7+LSAACUgAhN4DEpDA5RMA4eXfAgKQgARA6D0gAQlcPgEQXv4tIAAJSACE3gMSkMDlE3gJ4e12O9xk4D3gPdDpPXBG9R8hPHOox0hAAhJYkcAT7DN/IDyTmsdIQAKRCYAw8rIYSgIS+GQCIPxk2p5LAhKITACEkZfFUBKQwCcTAOEn0/ZcEpBAZAIgjLwshpKABD6ZAAg/mbbnkoAEIhMAYeRlMZQEJPDJBED4ybQ9lwQkEJnAegif/6LbTQbV74HIdTNUagIgrF5A52Wgnrpx5opMAITgyoCr+jpErpuhUhMAYfUCOi8D1tSNM1dkAiAEVwZc1dchct0MlZoACKsX0HkZsKZunLkiEwAhuDLgqr4OketmqNQEQFi9gM7LgDV148wVmQAIwZUBV/V1iFw3Q6UmAMLqBXReBqypG2euyARACK4MuKqvQ+S6GSo1ARBWL6DzMmBN3ThzRSYAQnBlwFV9HSLXzVCpCYCwegGdlwFr6saZKzIBEIIrA67q6xC5boZKTQCE1QvovAxYUzfOXJEJgBBcGXBVX4fIdTNUagIgrF5A52XAmrpx5opMAITgyoCr+jpErpuhUhMAYfUCOi8D1tSNM1dkAiAEVwZc1dchct0MlZoACKsX0HkZsKZunLkiEwAhuDLgqr4OketmqNQEQFi9gM7LgDV148wVmQAIwZUBV/V1iFw3Q6UmAMLqBXReBqypG2euyARACK4MuKqvQ+S6GSo1ARBWL6DzMmBN3ThzRSYAQnBlwFV9HSLXzVCpCYCwegGdlwFr6saZKzIBEIIrA67q6xC5boZKTQCE1QvovAxYUzfOXJEJgBBcGXBVX4fIdTNUagIgrF5A52XAmrpx5opMAITgyoCr+jpErpuhUhMAYfUCOi8D1tSNM1dkAiAEVwZc1dchct0MlZoACKsX0HkZsKZunLkiEwAhuDLgqr4OketmqNQEQFi9gM7LgDV148wVmQAIf4Dr8fX7eNzubt0yeBzHI/gWqcGFhwIhCPdEPhjBJ9D+shIAIQhBuADNLAZMA0IQghCEl5cQhCAEIQhB+HTgxN/LRw3pGv4rqx9Lmv5QtAC3kR9nTuych0xMYMis/+YAYbdfUa82LwgnsrHf0SD00dhH4wVo7kdJ71cEQhCCEIS9FSuYHoQgBCEICyjpfQQIQQhCEPZWrGB6EIIQhCAsoKT3ESAEIQhB2FuxgulBCEIQgrCAkt5HgBCEIARhb8UKpgchCEEIwgJKeh8BQhCCEIS9FSuYHoQgBCEICyjpfQQIQQhCEPZWrGB6EIIQhCAsoKT3ESAEIQhB2FuxgulBCEIQgrCAkt5HgBCEIARhb8UKpgchCEEIwgJKeh8BQhCCEIS9FSuYHoQgBCEICyjpfQQIQQhCEPZWrGB6EIIQhCAsoKT3ESAEIQhB2FuxgulBCEIQgrCAkt5HgBCEIARhb8UKpgchCEEIwgJKeh8BQhCCEIS9FSuYHoQgBCEICyjpfQQIQQhCEPZWrGB6EIIQhCAsoKT3ESAEIQhB2FuxgulBCEIQgrCAkt5HgBCEIARhb8UKpgchCEEIwgJKeh8BQhCCEIS9FSuYHoQgBCEICyjpfQQIQQhCEPZWrGB6EIIQhCAsoKT3ESAEIQhB2FuxgulBCEIQgrCAkt5HgBCEIARhb8UKpgchCEEIwgJKeh8BQhCCEIS9FSuYHoQgBCEICyjpfQQILwLh9/3Xcanb9+P4Dr4dx199t7j1BvDf9CAE4Z5ABiP4BHoPBJ+vY48/EIIQhAvQBGEWoCAEIQhB+EZDzQLt7DQgBCEIQQjCpwMn/l4+akjXHyA6Fv/3x9fvLX5VvdQPJc8fhhbgNvKcPhqfUGfiQ4bM+m8OEN7urYAEYdavyCCcqNqJo0Hoo7GPxgvaIwhPaDXxISAEIQhB6DtC3xH+/ZT/AkPfETb9h9gLcPMd4cTKNvno9Y1w8gt89/jHgv/9asZzjiyp+87/PtFH43c3s/bxIPwhzxkorTgTbvNxG8kYhLWQvXsaCEEY/09NRoDpcl8QvktX7eNBCEIQLvg+EYS1kL17GghBCEIQ+tV4+a/G71I++fErvs+b8ZxdPjJeZU6NcPLiDh6vEWqEGqFGqBFqhK8lnNHOVpx5labV5XVqhIOVbfLdNUKNUCPUCDVCjVAj7NKidppTI5xc8QaP1wg1Qo1QI9QINUKNcKem1eW1aISDlW3y3TVCjVAj1Ag1Qo1QI+zSonaaUyOcXPEGj9cINUKNUCPUCDVCjXCnptXltWiEg5Vt8t01Qo1QI9QINUKNUCPs0qJ2mlMjnFzxBo/XCDVCjVAj1Ag1Qo1wp6bV5bVohIOVbfLdNUKNUCPUCDVCjVAj7NKidppTI5xc8QaP1wg1Qo1QI9QINUKNcKem1eW1aISDlW3y3TVCjVAj1Ag1Qo1QI+zSonaaUyOcXPEGj9cINUKNUCPUCDVCjXCnptXltWiEg5Vt8t01Qo1QI9QINUKNUCPs0qJ2mlMjnFzxBo/XCDVCjVAj1Ag1Qo1wp6bV5bVohIOVbfLdNUKNUCPUCDVCjVAj7NKidppTI5xc8QaP1wg1Qo1QI9QINUKNcKem1eW1aISDlW3y3TVCjVAj1Ag1Qo1QI+zSonaaUyOcXPEGj9cINUKNUCPUCDVCjXCnptXltWiEg5Vt8t2nNcLnwW45Gdzvt8NNBtXvgZ12/Iy1tzMP8piVCTze+Pjjsfs0uOprufI9vf65Qbj+GphAAhJYnAAIF18ATy8BCaxPAITrr4EJJCCBxQmAcPEF8PQSkMD6BEC4/hqYQAISWJwACBdfAE8vAQmsTwCE66+BCSQggcUJgHDxBfD0EpDA+gRAuP4amEACElicAAgXXwBPLwEJrE8AhOuvgQkkIIHFCYBw8QXw9BKQwPoE/gBihLzNDuhSiAAAAABJRU5ErkJggg==)
# CanvasContext.setLineCap(string lineCap)
设置线条的端点样式
## 参数
### string lineCap
线条的结束端点样式
**lineCap 的合法值**
| 值 | 说明 |
| ------ | -------------------------------- |
| butt | 向线条的每个末端添加平直的边缘。 | |
| round | 向线条的每个末端添加圆形线帽。 | |
| square | 向线条的每个末端添加正方形线帽。 | |
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.beginPath()
ctx.moveTo(10, 10)
ctx.lineTo(150, 10)
ctx.stroke()
ctx.beginPath()
ctx.setLineCap('butt')
ctx.setLineWidth(10)
ctx.moveTo(10, 30)
ctx.lineTo(150, 30)
ctx.stroke()
ctx.beginPath()
ctx.setLineCap('round')
ctx.setLineWidth(10)
ctx.moveTo(10, 50)
ctx.lineTo(150, 50)
ctx.stroke()
ctx.beginPath()
ctx.setLineCap('square')
ctx.setLineWidth(10)
ctx.moveTo(10, 70)
ctx.lineTo(150, 70)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setLineDash(Array.\<number> pattern, number offset)
设置虚线样式。
## 参数
### Array.\<number> pattern
一组描述交替绘制线段和间距(坐标空间单位)长度的数字
### number offset
虚线偏移量
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setLineDash([10, 20], 5)
ctx.beginPath()
ctx.moveTo(0, 100)
ctx.lineTo(400, 100)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUcAAACoCAYAAABzLCyIAAAC/ElEQVR4nO3YMWrbYACGYdl41imag5Ts7dI1kFwj4BpnyDVa6Nql3UMP4pzCF3CjsfTNECw7CTzPKIO+3x5eLC0OTwYA/rF87QMAvEXiCBDEESCII0BY1cWHhz/Dt+8/hv1+f+7zALzIOI7DzfXVcHn5cdb7ZhynMG6+3g4XFx9mHQOY2273OGzv7mePYz5WT/8YhRF4D6ZWneIp1ztHgCCOAEEcAYI4AgRxBAjiCBDEESCII0AQR4AgjgBBHAGCOAIEcQQI4ggQxBEgiCNAEEeAII4AQRwBgjgCBHEECOIIEMQRIIgjQBBHgCCOAEEcAYI4AgRxBAjiCBDEESCII0AQR4AgjgBBHAGCOAIEcQQI4ggQxBEgiCNAEEeAII4AQRwBgjgCBHEECOIIEMQRIIgjQBBHgCCOAEEcAYI4AgRxBAjiCBDEESCII0AQR4AgjgBBHAGCOAIEcQQI4ggQxBEgiCNAEEeAII4AQRwBgjgCBHEECOIIEMQRIIgjQBBHgCCOAEEcAYI4AgRxBAjiCBDEESCII0AQR4AgjgBBHAGCOAIEcQQI4ggQxBEgiCNAEEeAII4AQRwBgjgCBHEECOIIEMQRIIgjQBBHgLB67oPtdvvftc1mM+t4bRS7du0et7tcLof1en323clr/c7HejaOh8Ph5OPn2LBr1+5pzvaWv+8cFodY+vT5y/D718+zHADgWKdolneOAEEcAYI4AgRxBAjiCBDEESCII0AQR4AgjgBBHAGCOAIEcQQI4ggQxBEgiCNAEEeAII4AQRwBgjgCBHEECOIIEMQRIIgjQBBHgCCOAEEcAYI4AgRxBAjiCBDEESCII0AQR4AgjgBBHAGCOAIEcQQI4ggQxBEgiCNAEEeAII4AQRwBgjgCBHEECOIIEMQRIIgjQMg4juM47HaP5z4LwItNrZqaNbdVXby5vhq2d/fDfr+ffRBgTlMYp2bNbXF4MvtdAd457xwBgjgCBHEECOIIEMQRIIgjQBBHgCCOAEEcAYI4AoS/9Pt7GTb0EWgAAAAASUVORK5CYII=)
# CanvasContext.setLineJoin(string lineJoin)
设置线条的交点样式
## 参数
### string lineJoin
线条的结束交点样式
**lineJoin 的合法值**
| 值 | 说明 |
| ----- | ---- |
| bevel | 斜角 | |
| round | 圆角 | |
| miter | 尖角 | |
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.beginPath()
ctx.moveTo(10, 10)
ctx.lineTo(100, 50)
ctx.lineTo(10, 90)
ctx.stroke()
ctx.beginPath()
ctx.setLineJoin('bevel')
ctx.setLineWidth(10)
ctx.moveTo(50, 10)
ctx.lineTo(140, 50)
ctx.lineTo(50, 90)
ctx.stroke()
ctx.beginPath()
ctx.setLineJoin('round')
ctx.setLineWidth(10)
ctx.moveTo(90, 10)
ctx.lineTo(180, 50)
ctx.lineTo(90, 90)
ctx.stroke()
ctx.beginPath()
ctx.setLineJoin('miter')
ctx.setLineWidth(10)
ctx.moveTo(130, 10)
ctx.lineTo(220, 50)
ctx.lineTo(130, 90)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setLineWidth(number lineWidth)
设置线条的宽度
## 参数
### number lineWidth
线条的宽度,单位 px
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.beginPath()
ctx.moveTo(10, 10)
ctx.lineTo(150, 10)
ctx.stroke()
ctx.beginPath()
ctx.setLineWidth(5)
ctx.moveTo(10, 30)
ctx.lineTo(150, 30)
ctx.stroke()
ctx.beginPath()
ctx.setLineWidth(10)
ctx.moveTo(10, 50)
ctx.lineTo(150, 50)
ctx.stroke()
ctx.beginPath()
ctx.setLineWidth(15)
ctx.moveTo(10, 70)
ctx.lineTo(150, 70)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setMiterLimit(number miterLimit)
设置最大斜接长度。斜接长度指的是在两条线交汇处内角和外角之间的距离。当 [CanvasContext.setLineJoin()](CanvasContext.setLineJoin.html) 为 miter 时才有效。超过最大倾斜长度的,连接处将以 lineJoin 为 bevel 来显示。
## 参数
### number miterLimit
最大斜接长度
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.beginPath()
ctx.setLineWidth(10)
ctx.setLineJoin('miter')
ctx.setMiterLimit(1)
ctx.moveTo(10, 10)
ctx.lineTo(100, 50)
ctx.lineTo(10, 90)
ctx.stroke()
ctx.beginPath()
ctx.setLineWidth(10)
ctx.setLineJoin('miter')
ctx.setMiterLimit(2)
ctx.moveTo(50, 10)
ctx.lineTo(140, 50)
ctx.lineTo(50, 90)
ctx.stroke()
ctx.beginPath()
ctx.setLineWidth(10)
ctx.setLineJoin('miter')
ctx.setMiterLimit(3)
ctx.moveTo(90, 10)
ctx.lineTo(180, 50)
ctx.lineTo(90, 90)
ctx.stroke()
ctx.beginPath()
ctx.setLineWidth(10)
ctx.setLineJoin('miter')
ctx.setMiterLimit(4)
ctx.moveTo(130, 10)
ctx.lineTo(220, 50)
ctx.lineTo(130, 90)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setStrokeStyle([Color](Color.html) color)
设置描边颜色。
## 参数
### [Color](Color.html) color
描边的颜色,默认颜色为 black。
## 代码示例
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setStrokeStyle('red')
ctx.strokeRect(10, 10, 150, 75)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.setTextAlign(string align)
设置文字的对齐
## 参数
### string align
文字的对齐方式
**align 的合法值**
| 值 | 说明 |
| ------ | -------- |
| left | 左对齐 | |
| center | 居中对齐 | |
| right | 右对齐 | |
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setStrokeStyle('red')
ctx.moveTo(150, 20)
ctx.lineTo(150, 170)
ctx.stroke()
ctx.setFontSize(15)
ctx.setTextAlign('left')
ctx.fillText('textAlign=left', 150, 60)
ctx.setTextAlign('center')
ctx.fillText('textAlign=center', 150, 80)
ctx.setTextAlign('right')
ctx.fillText('textAlign=right', 150, 100)
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATkAAACbCAYAAAAZQuygAAAYZklEQVR4Ae2dCdRN1fvHt0qzkjStBmkwRLEqQ5GSkkZJGmgQCVGaUyQ0LyVNEv3LijStpQFpQGUKqVVZRRqUChEVJSH3vz67377rvOe9753c855z7vvda113Ons4n+1+32dPz1NpzZo1CWOMSSQSZsuWLclnXm/evNkceOCBfK0kAiIgArEksE0sW61Gi4AIiECWBCRyWYLSZSIgAvEkIJGLZ7+p1SIgAlkSkMhlCUqXiYAIxJPAdpmaXalSpUyX6HsREAERiBQBFlJdyihyXOjN4DLqWQREQASiSMBvmGm4GsVeUptEQAQKRkAiVzCUKkgERCCKBCRyUewVtUkERKBgBCRyBUOpgkRABKJIQCIXxV5Rm0RABApGQCJXMJQqSAREIIoEJHJR7BW1SQREoGAEJHIFQ6mCREAEokhAIhfFXlGbREAECkZAIlcwlCpIBEQgigQkclHsFbVJBESgYAQkcgVDqYJEQASiSEAiF8VeUZtEQAQKRkAiVzCUKkgERCCKBCRyUewVtUkERKBgBCRyBUOpgkRABKJIQCIXxV5Rm0RABApGQCJXMJQqSAREIIoEJHJR7BW1SQREoGAEJHIFQ6mCciIwaJAxAwfmlEUXi0A+BCRy+VBTHhEQgdgQkMjFpqvUUBEQgXwISOTyoaY8IiACsSEgkYtNV6mhIiAC+RCQyOVDTXlEQARiQ0AiF5uuUkNFQATyISCRy4ea8oiACMSGgEQuNl2lhoqACORDQCKXDzXlEQERiA0BiVxsukoNFQERyIeARC4fasojAiIQGwISudh0lRoqAiKQDwGJXD7UlEcERCA2BCRysekqNVQERCAfAhK5fKgpjwiIQGwISORi01VqqAiIQD4EJHL5UFMeERCB2BCQyMWmq9RQERCBfAhI5PKhpjwiIAKxISCRi01XqaEiIAL5EJDI5UNNeURABGJDQCIXm65SQ0VABPIhIJHLh5ryiIAIxIaARC42XaWGioAI5ENAIpcPNeURARGIDQGJXGy6Sg0VARHIh4BELh9qyiMCIhAbAhK52HSVGlpeBP7++2/To0cPc9ddd9kq165day677DIzZMgQ8++//5ZXM0rV429XqQvK+GDdunVmwIABZs8997T3RTkVKUnkKlJv616TBKZOnWp222038/DDDyc/K+tF5cqVTa1atcwhhxxitt1227Iui+TniUTCPPPMM+aTTz4xM2fONA888IDZcccdI9nWoBolkQuKrMrNisDChQtNx44dzddff53V9dleNG3aNNOlSxezevXqUlk2btxoJk2aZM4//3wze/Zs89tvv5W6xvvBTjvtZPr372/at2/v/TgWrzds2GBg3KRJE1O3bl2z++67m02bNpmHHnrIWqaxuImtbKREbisBKvvWEVizZo358ssvzZYtW7auIF/u5cuXm2XLlvk+/e/tzz//bBYvXmy6du1qGLph5VSkxJCbPyoIYEVIErmK0MsRvce7pk83zZs3N5999pmpU6eOadiwofnqq69sa1etWmWtp4MPPtjOJfXs2dOsWLHCfoeVVr9+fTN//vzknb3++uvmpJNOsvmZT7vkkkvM22+/bapXr27atGlTwqIj/1577WWOOuoo07RpU/PGG2+Yf/75J1mW/0WquTA+GzFihC2DYS9W47vvvmtOO+205D1wL9wT7Rg0aJDhXng89dRTZvPmzf5q8npPu1944QV7H5UqVTKnnHKKtU4ZplL/cccdZ+tjTo7vH3zwwVKfubnHvBoQg0wSuRh0UrE28fqmTc3kyZPNkUceaebNm2fee+89c+ihhxoE7uqrr7bzX8wjYWntuuuu5tZbbzUsArRo0cK0bdvWPP3009YSQ/yYd7r++uvt3BnzTiNHjjStWrWyFgsisMcee1iMDE0ZqiKuVapUMS1btrRiWZbVl4o9AvXoo4+a0aNHm2HDhpklS5aYCy64wPTr16+EmLq8zPsxXPzoo4/sNQjOBx984L42s2bNsgKECPkfXuFPZvjfCywy2vHKK69YwV25cqXp3LmzueGGG8yCBQssyzfffNNcccUV5vbbbze//vqrXXjwfwa3Yk7bFfPN6d6iTWDX7be3QrPNNtvYRQAnRO+8844VtVtuucXssssu9iZ69+5tf6wMs4455hjTrVs3+4PmB/vdd99Zy+7MM8+0IsG8084772y22247K26uXAoi/9KlS63lw/vatWvburHuGL5mk7799lsrLPfee685+eSTbRasRayn2267rVQRV111lbUm+eKiiy4yM2bMsKKOCJMaNWpkBahURmMMbBDjVOmbb76xfyQee+wxU69ePXsJYssfBRZWsFS59+23394uNrC6SmLx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)
# CanvasContext.setTextBaseline(string textBaseline)
设置文字的竖直对齐
## 参数
### string textBaseline
文字的竖直对齐方式
**textBaseline 的合法值**
| 值 | 说明 |
| ------ | -------- |
| top | 顶部对齐 | |
| bottom | 底部对齐 | |
| middle | 居中对齐 | |
| normal | | |
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setStrokeStyle('red')
ctx.moveTo(5, 75)
ctx.lineTo(295, 75)
ctx.stroke()
ctx.setFontSize(20)
ctx.setTextBaseline('top')
ctx.fillText('top', 5, 75)
ctx.setTextBaseline('middle')
ctx.fillText('middle', 50, 75)
ctx.setTextBaseline('bottom')
ctx.fillText('bottom', 120, 75)
ctx.setTextBaseline('normal')
ctx.fillText('normal', 200, 75)
ctx.draw()
```
# CanvasContext.setTransform(number scaleX, number scaleY, number skewX, number skewY, number translateX, number translateY)
使用矩阵重新设置(覆盖)当前变换的方法
## 参数
### number scaleX
水平缩放
### number scaleY
垂直缩放
### number skewX
水平倾斜
### number skewY
垂直倾斜
### number translateX
水平移动
### number translateY
垂直移动
# CanvasContext.stroke()
画出当前路径的边框。默认颜色色为黑色。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.moveTo(10, 10)
ctx.lineTo(100, 10)
ctx.lineTo(100, 100)
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
stroke() 描绘的的路径是从 beginPath() 开始计算,但是不会将 strokeRect() 包含进去。
```js
const ctx = qa.createCanvasContext('myCanvas')
// begin path
ctx.rect(10, 10, 100, 30)
ctx.setStrokeStyle('yellow')
ctx.stroke()
// begin another path
ctx.beginPath()
ctx.rect(10, 40, 100, 30)
// only stoke this rect, not in current path
ctx.setStrokeStyle('blue')
ctx.strokeRect(10, 70, 100, 30)
ctx.rect(10, 100, 100, 30)
// it will stroke current path
ctx.setStrokeStyle('red')
ctx.stroke()
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.strokeRect(number x, number y, number width, number height)
画一个矩形(非填充)。 用 [`setStrokeStyle`](CanvasContext.setStrokeStyle.html) 设置矩形线条的颜色,如果没设置默认是黑色。
## 参数
### number x
矩形路径左上角的横坐标
### number y
矩形路径左上角的纵坐标
### number width
矩形路径的宽度
### number height
矩形路径的高度
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.setStrokeStyle('red')
ctx.strokeRect(10, 10, 150, 75)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasContext.strokeText(string text, number x, number y, number maxWidth)
给定的 (x, y) 位置绘制文本描边的方法
## 参数
### string text
要绘制的文本
### number x
文本起始点的 x 轴坐标
### number y
文本起始点的 y 轴坐标
### number maxWidth
需要绘制的最大宽度,可选
# CanvasContext.transform(number scaleX, number scaleY, number skewX, number skewY, number translateX, number translateY)
使用矩阵多次叠加当前变换的方法
## 参数
### number scaleX
水平缩放
### number scaleY
垂直缩放
### number skewX
水平倾斜
### number skewY
垂直倾斜
### number translateX
水平移动
### number translateY
垂直移动
# CanvasContext.translate(number x, number y)
对当前坐标系的原点 (0, 0) 进行变换。默认的坐标系原点为页面左上角。
## 参数
### number x
水平坐标平移量
### number y
竖直坐标平移量
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
ctx.strokeRect(10, 10, 150, 100)
ctx.translate(20, 20)
ctx.strokeRect(10, 10, 150, 100)
ctx.translate(20, 20)
ctx.strokeRect(10, 10, 150, 100)
ctx.draw()
```
![](data:image/png;base64,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)
# CanvasGradient.addColorStop(number stop, [Color](Color.html) color)
添加颜色的渐变点。小于最小 stop 的部分会按最小 stop 的 color 来渲染,大于最大 stop 的部分会按最大 stop 的 color 来渲染
## 参数
### number stop
表示渐变中开始与结束之间的位置,范围 0-1。
### [Color](Color.html) color
渐变点的颜色。
## 示例代码
```js
const ctx = qa.createCanvasContext('myCanvas')
// Create circular gradient
const grd = ctx.createLinearGradient(30, 10, 120, 10)
grd.addColorStop(0, 'red')
grd.addColorStop(0.16, 'orange')
grd.addColorStop(0.33, 'yellow')
grd.addColorStop(0.5, 'green')
grd.addColorStop(0.66, 'cyan')
grd.addColorStop(0.83, 'blue')
grd.addColorStop(1, 'purple')
// Fill with gradient
ctx.setFillStyle(grd)
ctx.fillRect(10, 10, 150, 80)
ctx.draw()
```
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUIAAACsCAYAAAAOlKXaAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAoNSURBVHhe7dtPqOdlFcfxZ1E5UFAQaNku0v4sikDBdsEIuolAoVwFDvRnkaBQ2SJwgoECB11M/9CUtECFGdAMFJxQKhjRUqhQtHSRI45kCx1hhCmezp17F+bq90DDuXPO68LhwvA9v+c57/O97/tZ3BnTFwIIINCcwGg+v/ERQACBSYReAgQQaE+ACNu/AgAggAARegcQQKA9ASJs/woAgAACROgdQACB9gSIsP0rAAACCGwswjHGVBh4B7wD59I7sKnil0S46Yd6DgEEEMgmsCXsTb82fnLlQzc93HMIIIDA2SKw4iwiPFtb8LkIIJBKgAhT8TscAQR2AwEi3A1bcAcEEEglQISp+B2OAAK7gQAR7oYtuAMCCKQSIMJU/A5HAIHdQIAId8MW3AEBBFIJEGEqfocjgMBuIJAvwq2/6P5/1rvj8z4Q9eGoj0V9OupzUXujvhD15ah9Ud+MujHq+1E3R/046hdR90Qdifp11MNRR6N+F3Us6k9Rf456NurvUf+IeiXqX1GvR52K+veYb50e88TJMZ9/bcwnjo959MUxDz8z5p1Pj3lLfM7+x8a8Pj573wNjXnXfmJffPeYlt4158aExz4+77DkQ/zXrwJ45Dn5ojkMfn+Pnl83xyyvmOHzNHA9+fY6j353j9z+Y448/m+Mv98zxt4fmeOnYHP98do6Tr8xx+tQcpwLrq1HPRT0Z9UjUkag7om6Nuinqhqhro66O2ht1adRFURdEnTfnu8bp+d5xcn5wvDYvHMfnR8eL85PjmfnZ8fS8bBybnx+PzSvGw/OL44H5pXHf/Mq4e3513DavG4fmt8bN83vjwNw/9qfUbvjhcodzh0A9Eb4nZPT+qAt3RPiZd4jwmh0RXhffv/M2Ef5kR4T37ojwwfj+UNRvd0T4+DtE+MKOCE/E9xDefGNHhP8Z81SI8NU3x3wu/v3Jl8d8JJ49EiK846kxbw0R3vTomDeECK+9f8yrQ4R77xrz0tvHvChEeMHBMc97uwh/9IltEf7qym0R/uYbIbUb5/jDD0NwP53jr/dui/D44/8rwrdCZieino96Iupo1OGoO6NuidofdX3Uvqiroi6PuiTq4qjzo/Zsi/B9480zIvzIeDlE+ML81BkRPhW/W7ZE+Oi88owI74/fL1sivGt+bdx+RoTfHgeJ8NzxQPub1hOhRCgRblneFwILBOqJUCLcFqFEuPBj4NHuBOqJUCKUCCXC7l5bnr+eCCVCiZAIl0XQvaGeCCVCiZAIu3ttef56IpQIJUIiXBZB94Z6IpQIJUIi7O615fnriVAilAiJcFkE3RvqiVAilAiJsLvXluevJ0KJUCIkwmURdG+oJ0KJUCIkwu5eW56/ngglQomQCJdF0L2hngglQomQCLt7bXn+eiKUCCVCIlwWQfeGeiKUCCVCIuzuteX564lQIpQIiXBZBN0b6olQIpQIibC715bnrydCiVAiJMJlEXRvqCdCiVAiJMLuXluev54IJUKJkAiXRdC9oZ4IJUKJkAi7e215/noilAglQiJcFkH3hnoilAglQiLs7rXl+euJUCKUCIlwWQTdG+qJUCKUCImwu9eW568nQolQIiTCZRF0b6gnQolQIiTC7l5bnr+eCCVCiZAIl0XQvaGeCCVCiZAIu3ttef56IpQIJUIiXBZB94Z6IpQIJUIi7O615fnriVAilAiJcFkE3RvqiVAilAiJsLvXluevJ0KJUCIkwmURdG+oJ0KJUCIkwu5eW56/ngglQomQCJdF0L2hngglQomQCLt7bXn+eiKUCCVCIlwWQfeGeiKUCCVCIuzuteX564lQIpQIiXBZBN0b6olQIpQIibC715bnrydCiVAiJMJlEXRvqCdCiVAiJMLuXluev54IJUKJkAiXRdC9oZ4IJUKJkAi7e215/noilAglQiJcFkH3hnoilAglQiLs7rXl+euJUCKUCIlwWQTdG+qJUCKUCImwu9eW568nQolQIiTCZRF0b6gnQolQIiTC7l5bnr+eCCVCiZAIl0XQvaGeCCVCiZAIu3ttef56IpQIJUIiXBZB94Z6IpQIJUIi7O615fnriVAilAiJcFkE3RvqiVAilAiJsLvXluevJ0KJUCIkwmURdG+oJ0KJUCIkwu5eW56/ngglQomQCJdF0L2hngglQomQCLt7bXn+eiKUCCVCIlwWQfeGeiKUCCVCIuzuteX564lQIpQIiXBZBN0b6olQIpQIibC715bnrydCiVAiJMJlEXRvqCdCiVAiJMLuXluev54IJUKJkAiXRdC9oZ4IJUKJkAi7e215/noilAglQiJcFkH3hnoilAglQiLs7rXl+euJUCKUCIlwWQTdG+qJUCKUCImwu9eW568nQolQIiTCZRF0b6gnQolQIiTC7l5bnr+eCCVCiZAIl0XQvaGeCCVCiZAIu3ttef56IpQIJUIiXBZB94Z8EXbfgPkRQCCdABGmr8AFEEAgmwARZm/A+QggkE6ACNNX4AIIIJBNgAizN+B8BBBIJ0CE6StwAQQQyCZAhNkbcD4CCKQTIML0FbgAAghkEyDC7A04HwEE0gkQYfoKXAABBLIJEGH2BpyPAALpBIgwfQUugAAC2QSIMHsDzkcAgXQCRJi+AhdAAIFsAkSYvQHnI4BAOgEiTF+BCyCAQDYBIszegPMRQCCdABGmr8AFEEAgmwARZm/A+QggkE6ACNNX4AIIIJBNgAizN+B8BBBIJ0CE6StwAQQQyCZAhNkbcD4CCKQTIML0FbgAAghkEyDC7A04HwEE0gkQYfoKXAABBLIJEGH2BpyPAALpBIgwfQUugAAC2QSIMHsDzkcAgXQCRJi+AhdAAIFsAkSYvQHnI4BAOgEiTF+BCyCAQDYBIszegPMRQCCdABGmr8AFEEAgmwARZm/A+QggkE6ACNNX4AIIIJBNgAizN+B8BBBIJ0CE6StwAQQQyCZAhNkbcD4CCKQTIML0FbgAAghkEyDC7A04HwEE0gkQYfoKXAABBLIJEGH2BpyPAALpBIgwfQUugAAC2QSIMHsDzkcAgXQCRJi+AhdAAIFsAkSYvQHnI4BAOgEiTF+BCyCAQDYBIszegPMRQCCdABGmr8AFEEAgmwARZm/A+QggkE6ACNNX4AIIIJBNgAizN+B8BBBIJ0CE6StwAQQQyCZAhNkbcD4CCKQTIML0FbgAAghkEyDC7A04HwEE0gkQYfoKXAABBLIJEGH2BpyPAALpBIgwfQUugAAC2QTOmgi3Plhh4B3wDpwr78CmMh6bPug5BBBAoCoBIqy6WXMhgMDGBIhwY1QeRACBqgSIsOpmzYUAAhsTIMKNUXkQAQSqEiDCqps1FwIIbEyACDdG5UEEEKhKgAirbtZcCCCwMQEi3BiVBxFAoCoBIqy6WXMhgMDGBIhwY1QeRACBqgSIsOpmzYUAAhsT+C9p7XmIHdFUtwAAAABJRU5ErkJggg==)
# CanvasGradient
渐变对象
## 方法
### [CanvasGradient.addColorStop(number stop, Color color)](CanvasGradient.addColorStop.html)
添加颜色的渐变点。小于最小 stop 的部分会按最小 stop 的 color 来渲染,大于最大 stop 的部分会按最大 stop 的 color 来渲染
# Color
颜色。可以用以下几种方式来表示 canvas 中使用的颜色:
- RGB 颜色: 如 'rgb(255, 0, 0)'
- RGBA 颜色:如 'rgba(255, 0, 0, 0.3)'
- 16 进制颜色: 如 '#FF0000'
- 预定义的颜色: 如 'red'
\ No newline at end of file
# Image
图片对象
## 属性
### string src
图片的 URL
### number width
图片的真实宽度
### number height
图片的真实高度
### function onload
图片加载完成后触发的回调函数
### function onerror
图片加载发生错误后触发的回调函数
# qa.canvasGetImageData(Object object, Object this)
获取 canvas 区域隐含的像素数据。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| canvasId | string | | 是 | 画布标识,传入 [canvas](../../component/canvas.html) 组件的 `canvas-id` 属性。 |
| x | number | | 是 | 将要被提取的图像数据矩形区域的左上角横坐标 |
| y | number | | 是 | 将要被提取的图像数据矩形区域的左上角纵坐标 |
| width | number | | 是 | 将要被提取的图像数据矩形区域的宽度 |
| height | number | | 是 | 将要被提取的图像数据矩形区域的高度 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ------ | ----------------- | ----------------------------------------------------- |
| width | number | 图像数据矩形的宽度 |
| height | number | 图像数据矩形的高度 |
| data | Uint8ClampedArray | 图像像素点数据,一维数组,每四项表示一个像素点的 rgba |
### Object this
在自定义组件下,当前组件实例的 this,以操作组件内 [canvas](../../component/canvas.html) 组件
## 示例代码
```js
qa.canvasGetImageData({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: 100,
height: 100,
success(res) {
console.log(res.width) // 100
console.log(res.height) // 100
console.log(res.data instanceof Uint8ClampedArray) // true
console.log(res.data.length) // 100 * 100 * 4
}
})
```
# qa.canvasPutImageData(Object object, Object this)
将像素数据绘制到画布。在自定义组件下,第二个参数传入自定义组件实例 this,以操作组件内 `<canvas>` 组件
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| canvasId | string | | 是 | 画布标识,传入 [canvas](../../component/canvas.html) 组件的 canvas-id 属性。 |
| data | Uint8ClampedArray | | 是 | 图像像素点数据,一维数组,每四项表示一个像素点的 rgba |
| x | number | | 是 | 源图像数据在目标画布中的位置偏移量(x 轴方向的偏移量) |
| y | number | | 是 | 源图像数据在目标画布中的位置偏移量(y 轴方向的偏移量) |
| width | number | | 是 | 源图像数据矩形区域的宽度 |
| height | number | | 是 | 源图像数据矩形区域的高度 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
### Object this
在自定义组件下,当前组件实例的 this,以操作组件内 [canvas](../../component/canvas.html) 组件
## 示例代码
```js
const data = new Uint8ClampedArray([255, 0, 0, 1])
qa.canvasPutImageData({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: 1,
data: data,
success(res) {}
})
```
# [CanvasContext](CanvasContext.html) qa.createCanvasContext(string canvasId, Object this)
创建 canvas 的绘图上下文 [CanvasContext](CanvasContext.html) 对象
## 参数
### string canvasId
要获取上下文的 [canvas](../../component/canvas.html) 组件 canvas-id 属性
### Object this
在自定义组件下,当前组件实例的 this,表示在这个自定义组件下查找拥有 canvas-id 的 [canvas](../../component/canvas.html) ,如果省略则不在任何自定义组件内查找
## 返回值
### [CanvasContext](CanvasContext.html)
# qa.onAccelerometerChange(function callback)
注册加速度数据回调监听器
需要先通过 [qa.startAccelerometer()](qa.startAccelerometer.html) 方法启动加速度计监听,并传入 interval 参数做为频率。
可以通过 [qa.stopAccelerometer()](qa.stopAccelerometer.html) 方法停止监听。
## 参数
### function callback
加速度数据的回调
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ---- | ------ | ---- |
| x | number | X 轴 |
| y | number | Y 轴 |
| z | number | Z 轴 |
## 示例代码
```js
qa.onAccelerometerChange(function(res) {
console.log(res.x)
console.log(res.y)
console.log(res.z)
})
```
# qa.startAccelerometer(Object object)
启动监听加速度计数据
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| interval | string | normal | 否 | 加速度数据的回调频率 | |
| success | function | | 否 | 接口调用成功的回调函数 | |
| fail | function | | 否 | 接口调用失败的回调函数 | |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) | |
**object.interval 的合法值**
| 值 | 说明 |
| ------ | ----------------------------------------- |
| normal | 200ms/次 左右的回调频率 | |
| ui | 60ms/次 左右的回调频率,通常用于更新UI | |
| game | 20ms/次 左右的回调频率,通常用于更新游戏 | |
## 示例代码
```js
qa.startAccelerometer({
interval: 'game'
})
```
## 注意
- `interval` 设置与 `qa.onAccelerometerChange()` 并不是完全一致,不同机型或者手机当前CPU与内存的占用情况,会有一定的差异;部分机型可能无法获得低频率回调(比如200ms/次)
# qa.stopAccelerometer(Object object)
关闭加速度计监听器
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.stopAccelerometer()
```
# qa.getBatteryInfo(Object object)
获取手机剩余电量。同步获取的 API [qa.getBatteryInfoSync](qa.getBatteryInfoSync.html)
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| level | string | 手机剩余电量,范围值: 1 - 100 |
| isCharging | boolean | 手机是否正在充电 |
# Object qa.getBatteryInfoSync()
[qa.getBatteryInfo](qa.getBatteryInfo.html) 的同步版本
## 返回值
### Object res
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| level | string | 手机剩余电量,范围值: 1 - 100 |
| isCharging | boolean | 手机是否正在充电 |
# qa.closeBLEConnection(Object object)
断开与低功耗蓝牙设备的连接。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 用于区分设备的 id |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.closeBLEConnection({
deviceId,
success(res) {
console.log(res)
}
})
```
# qa.createBLEConnection(Object object)
连接低功耗蓝牙设备。
若快应用在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需进行搜索操作。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 用于区分设备的 id |
| timeout | number | | 否 | 超时时间,单位 ms,不填表示不会超时 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 注意
- 请保证尽量成对的调用 `createBLEConnection``closeBLEConnection` 接口。如果多次调用 `createBLEConnection` 创建连接,有可能导致系统持有同一设备多个连接的实例,导致调用 `closeBLEConnection` 的时候并不能真正的断开与设备的连接。
- 蓝牙连接随时可能断开,建议监听 [qa.onBLEConnectionStateChange](qa.onBLEConnectionStateChange.html) 回调事件,当蓝牙设备断开时按需执行重连操作
- 若对未连接的设备或已断开连接的设备调用数据读写操作的接口,会返回 10006 错误,建议进行重连操作。
## 示例代码
```js
qa.createBLEConnection({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId,
success(res) {
console.log(res)
}
})
```
# qa.getBLEDeviceCharacteristics(Object object)
获取蓝牙设备某个服务中所有特征值(characteristic)。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 蓝牙设备 id |
| serviceId | string | | 是 | 蓝牙服务 uuid,需要使用 `getBLEDeviceServices` 获取 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| --------------- | --------------- | -------------- |
| characteristics | Array.\<Object> | 设备特征值列表 |
**res.characteristics 的结构**
| 属性 | 类型 | 说明 |
| ---------- | ------ | ---------------------- |
| uuid | string | 蓝牙设备特征值的 uuid |
| properties | Object | 该特征值支持的操作类型 |
**properties 的结构**
| 属性 | 类型 | 说明 |
| -------- | ------- | ------------------------------ |
| read | boolean | 该特征值是否支持 read 操作 |
| write | boolean | 该特征值是否支持 write 操作 |
| notify | boolean | 该特征值是否支持 notify 操作 |
| indicate | boolean | 该特征值是否支持 indicate 操作 |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId,
success(res) {
console.log('device getBLEDeviceCharacteristics:', res.characteristics)
}
})
```
# qa.getBLEDeviceServices(Object object)
获取蓝牙设备所有服务(service)。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 蓝牙设备 id |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| -------- | --------------- | ------------ |
| services | Array.\<Object> | 设备服务列表 |
**res.services 的结构**
| 属性 | 类型 | 说明 |
| --------- | ------- | ------------------- |
| uuid | string | 蓝牙设备服务的 uuid |
| isPrimary | boolean | 该服务是否为主服务 |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.getBLEDeviceServices({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId,
success(res) {
console.log('device services:', res.services)
}
})
```
# qa.notifyBLECharacteristicValueChange(Object object)
启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。注意:必须设备的特征值支持 notify 或者 indicate 才可以成功调用。
另外,必须先启用 `notifyBLECharacteristicValueChange` 才能监听到设备 `characteristicValueChange` 事件
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 蓝牙设备 id |
| serviceId | string | | 是 | 蓝牙特征值对应服务的 uuid |
| characteristicId | string | | 是 | 蓝牙特征值的 uuid |
| state | boolean | | 是 | 是否启用 notify |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 注意
- 订阅操作成功后需要设备主动更新特征值的 value,才会触发 [qa.onBLECharacteristicValueChange](qa.onBLECharacteristicValueChange.html) 回调。
- 在调用 `notifyBLECharacteristicValueChange` 成功后立即调用 `writeBLECharacteristicValue` 接口,在部分机型上会发生 10008 系统错误
## 示例代码
```js
qa.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId,
success(res) {
console.log('notifyBLECharacteristicValueChange success', res.errMsg)
}
})
```
# qa.onBLECharacteristicValueChange(function callback)
监听低功耗蓝牙设备的特征值变化事件。必须先启用 `notifyBLECharacteristicValueChange` 接口才能接收到设备推送的 notification。
## 参数
### function callback
低功耗蓝牙设备的特征值变化事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ---------------- | ----------- | ------------------------- |
| deviceId | string | 蓝牙设备 id |
| serviceId | string | 蓝牙特征值对应服务的 uuid |
| characteristicId | string | 蓝牙特征值的 uuid |
| value | ArrayBuffer | 特征值最新的值 |
## 示例代码
```js
// ArrayBuffer转16进制字符串示例
function ab2hex(buffer) {
let hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
return ('00' + bit.toString(16)).slice(-2)
})
return hexArr.join('')
}
qa.onBLECharacteristicValueChange(function(res) {
console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
console.log(ab2hex(res.value))
})
```
# qa.onBLEConnectionStateChange(function callback)
监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
## 参数
### function callback
低功耗蓝牙连接状态的改变事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| --------- | ------- | ------------------ |
| deviceId | string | 蓝牙设备 ID |
| connected | boolean | 是否处于已连接状态 |
## 示例代码
```js
qa.onBLEConnectionStateChange(function(res) {
// 该方法回调中可以用于处理连接意外断开等异常情况
console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
})
```
# qa.readBLECharacteristicValue(Object object)
读取低功耗蓝牙设备的特征值的二进制数据值。注意:必须设备的特征值支持 read 才可以成功调用。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 蓝牙设备 id |
| serviceId | string | | 是 | 蓝牙特征值对应服务的 uuid |
| characteristicId | string | | 是 | 蓝牙特征值的 uuid |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 注意
- 并行调用多次会存在读失败的可能性。
- 接口读取到的信息需要在 `onBLECharacteristicValueChange` 方法注册的回调中获取。
## 示例代码
```js
// 必须在这里的回调才能获取
qa.onBLECharacteristicValueChange(function(characteristic) {
console.log('characteristic value comed:', characteristic)
})
qa.readBLECharacteristicValue({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId,
success(res) {
console.log('readBLECharacteristicValue:', res.errCode)
}
})
```
# qa.writeBLECharacteristicValue(Object object)
向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| deviceId | string | | 是 | 蓝牙设备 id |
| serviceId | string | | 是 | 蓝牙特征值对应服务的 uuid |
| characteristicId | string | | 是 | 蓝牙特征值的 uuid |
| value | ArrayBuffer | | 是 | 蓝牙设备特征值对应的二进制值 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 注意
- 并行调用多次会存在写失败的可能性。
- 快应用不会对写入数据包大小做限制,但系统与蓝牙设备会限制蓝牙 4.0 单次传输的数据大小,超过最大字节数后会发生写入错误,建议每次写入不超过 20 字节。
- 在调用 `notifyBLECharacteristicValueChange` 成功后立即调用 `writeBLECharacteristicValue` 接口,在部分机型上会发生 10008 系统错误
## 示例代码
```js
// 向蓝牙设备发送一个0x00的16进制数据
let buffer = new ArrayBuffer(1)
let dataView = new DataView(buffer)
dataView.setUint8(0, 0)
qa.writeBLECharacteristicValue({
// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId,
// 这里的value是ArrayBuffer类型
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res.errMsg)
}
})
```
# qa.closeBluetoothAdapter(Object object)
关闭蓝牙模块。调用该方法将断开所有已建立的连接并释放系统资源。建议在使用蓝牙流程后,与 [qa.openBluetoothAdapter](qa.openBluetoothAdapter.html) 成对调用。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.closeBluetoothAdapter({
success(res) {
console.log(res)
}
})
```
# qa.getBluetoothAdapterState(Object object)
获取本机蓝牙适配器状态。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ----------- | ------- | ------------------ |
| discovering | boolean | 是否正在搜索设备 |
| available | boolean | 蓝牙适配器是否可用 |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.getBluetoothAdapterState({
success(res) {
console.log(res)
}
})
```
# qa.getBluetoothDevices(Object object)
获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ------- | --------------- | --------------------------- |
| devices | Array.\<Object> | uuid 对应的的已连接设备列表 |
**res.devices 的结构**
| 属性 | 类型 | 说明 |
| -------------------- | --------------- | ------------------------------------------------------ |
| name | string | 蓝牙设备名称,某些设备可能没有 |
| deviceId | string | 用于区分设备的 id |
| RSSI | number | 当前蓝牙设备的信号强度 |
| advertisData | ArrayBuffer | 当前蓝牙设备的广播数据段中的 ManufacturerData 数据段。 |
| advertisServiceUUIDs | Array.\<string> | 当前蓝牙设备的广播数据段中的 ServiceUUIDs 数据段 |
| localName | string | 当前蓝牙设备的广播数据段中的 LocalName 数据段 |
| serviceData | Object | 当前蓝牙设备的广播数据段中的 ServiceData 数据段 |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
return ('00' + bit.toString(16)).slice(-2)
})
return hexArr.join('')
}
qa.getBluetoothDevices({
success: function(res) {
console.log(res)
if (res.devices[0]) {
console.log(ab2hex(res.devices[0].advertisData))
}
}
})
```
## 注意事项
- 该接口获取到的设备列表为**蓝牙模块生效期间所有搜索到的蓝牙设备**,若在蓝牙模块使用流程结束后未及时调用 [qa.closeBluetoothAdapter](qa.closeBluetoothAdapter.html) 释放资源,会存在调用该接口会返回之前的蓝牙使用流程中搜索到的蓝牙设备,可能设备已经不在用户身边,无法连接。
- 蓝牙设备在被搜索到时,系统返回的 name 字段一般为广播包中的 LocalName 字段中的设备名称,而如果与蓝牙设备建立连接,系统返回的 name 字段会改为从蓝牙设备上获取到的 `GattName`。若需要动态改变设备名称并展示,建议使用 `localName` 字段。
# qa.getConnectedBluetoothDevices(Object object)
根据 uuid 获取处于已连接状态的设备。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| services | Array.\<string> | | 是 | 蓝牙设备主 service 的 uuid 列表 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ------- | --------------- | ---------------- |
| devices | Array.\<Object> | 搜索到的设备列表 |
**res.devices 的结构**
| 属性 | 类型 | 说明 |
| -------- | ------ | ------------------------------ |
| name | string | 蓝牙设备名称,某些设备可能没有 |
| deviceId | string | 用于区分设备的 id |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.getConnectedBluetoothDevices({
success(res) {
console.log(res)
}
})
```
# qa.onBluetoothAdapterStateChange(function callback)
监听蓝牙适配器状态变化事件
## 参数
### function callback
蓝牙适配器状态变化事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ----------- | ------- | -------------------------- |
| available | boolean | 蓝牙适配器是否可用 |
| discovering | boolean | 蓝牙适配器是否处于搜索状态 |
## 示例代码
```js
qa.onBluetoothAdapterStateChange(function(res) {
console.log('adapterState changed, now is', res)
})
```
# qa.onBluetoothDeviceFound(function callback)
监听寻找到新设备的事件
## 参数
### function callback
寻找到新设备的事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ------- | --------------- | ------------------ |
| devices | Array.\<Object> | 新搜索到的设备列表 |
**devices 的结构**
| 属性 | 类型 | 说明 |
| -------------------- | --------------- | ------------------------------------------------------ |
| name | string | 蓝牙设备名称,某些设备可能没有 |
| deviceId | string | 用于区分设备的 id |
| RSSI | number | 当前蓝牙设备的信号强度 |
| advertisData | ArrayBuffer | 当前蓝牙设备的广播数据段中的 ManufacturerData 数据段。 |
| advertisServiceUUIDs | Array.\<string> | 当前蓝牙设备的广播数据段中的 ServiceUUIDs 数据段 |
| localName | string | 当前蓝牙设备的广播数据段中的 LocalName 数据段 |
| serviceData | Object | 当前蓝牙设备的广播数据段中的 ServiceData 数据段 |
## 注意
- 若在 [qa.onBluetoothDeviceFound](qa.onBluetoothDeviceFound.html) 回调了某个设备,则此设备会添加到 [qa.getBluetoothDevices](qa.getBluetoothDevices.html) 接口获取到的数组中。
## 示例代码
```js
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
return ('00' + bit.toString(16)).slice(-2)
})
return hexArr.join('')
}
qa.onBluetoothDeviceFound(function(devices) {
console.log('new device list has founded')
console.dir(devices)
console.log(ab2hex(devices[0].advertisData))
})
```
## 注意
- 部分机型需要有位置权限才能搜索到设备,需留意是否开启了位置权限
# qa.openBluetoothAdapter(Object object)
初始化蓝牙模块
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 注意
- 其他蓝牙相关 API 必须在 [qa.openBluetoothAdapter](qa.openBluetoothAdapter.html) 调用之后使用。否则 API 会返回错误(errCode=10000)。
- 在用户蓝牙开关未开启或者手机不支持蓝牙功能的情况下,调用 [qa.openBluetoothAdapter](qa.openBluetoothAdapter.html) 会返回错误(errCode=10001),表示手机蓝牙功能不可用。此时快应用蓝牙模块已经初始化完成,可通过 [qa.onBluetoothAdapterStateChange](qa.onBluetoothAdapterStateChange.html) 监听手机蓝牙状态的改变,也可以调用蓝牙模块的所有 API。
## 示例代码
```js
qa.openBluetoothAdapter({
success(res) {
console.log(res)
}
})
```
# qa.startBluetoothDevicesDiscovery(Object object)
开始搜寻附近的蓝牙外围设备。**此操作比较耗费系统资源,请在搜索并连接到设备后调用 [qa.stopBluetoothDevicesDiscovery](qa.stopBluetoothDevicesDiscovery.html) 方法停止搜索。**
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| services | Array.\<string> | | 否 | 要搜索的蓝牙设备主 service 的 uuid 列表。某些蓝牙设备会广播自己的主 service 的 uuid。如果设置此参数,则只搜索广播包有对应 uuid 的主服务的蓝牙设备。建议主要通过该参数过滤掉周边不需要处理的其他蓝牙设备。 |
| allowDuplicatesKey | boolean | false | 否 | 是否允许重复上报同一设备。如果允许重复上报,则 [qa.onBlueToothDeviceFound](./qa.onBlueToothDeviceFound.html) 方法会多次上报同一设备,但是 RSSI 值会有不同。 |
| interval | number | 0 | 否 | 上报设备的间隔。0 表示找到新设备立即上报,其他数值根据传入的间隔上报。 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
// 以快应用硬件平台的蓝牙智能灯为例,主服务的 UUID 是 FEE7。传入这个参数,只搜索主服务 UUID 为 FEE7 的设备
qa.startBluetoothDevicesDiscovery({
services: ['FEE7'],
success(res) {
console.log(res)
}
})
```
# qa.stopBluetoothDevicesDiscovery(Object object)
停止搜寻附近的蓝牙外围设备。若已经找到需要的蓝牙设备并不需要继续搜索时,建议调用该接口停止蓝牙搜索。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | --------------------------------------------- |
| 0 | ok | 正常 |
| 10000 | not init | 未初始化蓝牙适配器 |
| 10001 | not available | 当前蓝牙适配器不可用 |
| 10002 | no device | 没有找到指定设备 |
| 10003 | connection fail | 连接失败 |
| 10004 | no service | 没有找到指定服务 |
| 10005 | no characteristic | 没有找到指定特征值 |
| 10006 | no connection | 当前连接已断开 |
| 10007 | property not support | 当前特征值不支持此操作 |
| 10008 | system error | 其余所有系统上报的异常 |
| 10009 | system not support | 系统不支持 |
| 10012 | operate time out | 连接超时 |
| 10013 | invalid_data | 连接 deviceId 为空或者是格式不正确 |
## 示例代码
```js
qa.stopBluetoothDevicesDiscovery({
success(res) {
console.log(res)
}
})
```
# qa.getClipboardData(Object object)
获取系统剪贴板保存的内容,来源于复制或剪切等
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object object
| 属性 | 类型 | 说明 |
| ---- | ------ | ------------ |
| data | string | 剪贴板的内容 |
## 示例代码
```js
qa.getClipboardData({
success(res) {
console.log(res.data)
}
})
```
# qa.setClipboardData(Object object)
设置系统剪贴板的内容,可用于粘贴在其他应用内
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| data | string | | 是 | 剪贴板的内容 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.setClipboardData({
data: 'data',
success(res) {
qa.getClipboardData({
success(res) {
console.log(res.data) // data
}
})
}
})
```
# qa.onCompassChange(function callback)
注册罗盘数据回调监听器
默认频率:200ms/次,接口调用后会自动开始监听,可以通过调用使用 qa.stopCompass 停止监听。
## 参数
### function callback
罗盘数据的回调
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| --------- | ------------- | -------------- |
| direction | number | 面对的方向度数 | |
| accuracy | number/string | 精度 | |
## 示例代码
```js
qa.onCompassChange(function(res) {
console.log(res.direction)
})
```
## accuracy 的值说明
accuracy 是一个 string 类型的枚举值。
| 值 | 说明 |
| ---------------- | -------------------------------------------------------------------------------------- |
| high | 高精度 |
| medium | 中等精度 |
| low | 低精度 |
| no-contact | 传感器失去连接,不可信 |
| unreliable | 不可信,未知原因 |
| unknow \${value} | 未知的精度值 |
# qa.startCompass(Object object)
启动监听罗盘数据
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.startCompass()
```
# qa.stopCompass(Object object)
关闭罗盘监听器
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.stopCompass()
```
# qa.addPhoneContact(Object object)
添加联系人到手机通讯录。可以选择以「新增联系人」或「添加到已有联系人」的方式写入手机系统通讯录。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| firstName | string | | 是 | 名字 |
| photoFilePath | string | | 否 | 头像本地文件路径 |
| nickName | string | | 否 | 昵称 |
| lastName | string | | 否 | 姓氏 |
| middleName | string | | 否 | 中间名 |
| remark | string | | 否 | 备注 |
| mobilePhoneNumber | string | | 否 | 手机号 |
| addressCountry | string | | 否 | 联系地址国家 |
| addressState | string | | 否 | 联系地址省份 |
| addressCity | string | | 否 | 联系地址城市 |
| addressStreet | string | | 否 | 联系地址街道 |
| addressPostalCode | string | | 否 | 联系地址邮政编码 |
| organization | string | | 否 | 公司 |
| title | string | | 否 | 职位 |
| workFaxNumber | string | | 否 | 工作传真 |
| workPhoneNumber | string | | 否 | 工作电话 |
| hostNumber | string | | 否 | 公司电话 |
| email | string | | 否 | 电子邮件 |
| url | string | | 否 | 网站 |
| workAddressCountry | string | | 否 | 工作地址国家 |
| workAddressState | string | | 否 | 工作地址省份 |
| workAddressCity | string | | 否 | 工作地址城市 |
| workAddressStreet | string | | 否 | 工作地址街道 |
| workAddressPostalCode | string | | 否 | 工作地址邮政编码 |
| homeFaxNumber | string | | 否 | 住宅传真 |
| homePhoneNumber | string | | 否 | 住宅电话 |
| homeAddressCountry | string | | 否 | 住宅地址国家 |
| homeAddressState | string | | 否 | 住宅地址省份 |
| homeAddressCity | string | | 否 | 住宅地址城市 |
| homeAddressStreet | string | | 否 | 住宅地址街道 |
| homeAddressPostalCode | string | | 否 | 住宅地址邮政编码 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
# qa.onGyroscopeChange(function callback)
注册陀螺仪数据回调监听器
需要先通过 [qa.startGyroscope()](qa.startGyroscope.html) 方法启动陀螺仪监听,并传入 interval 参数做为频率。
可以使用 [qa.stopGyroscope()](qa.stopGyroscope.html) 方法停止监听。
## 参数
### function callback
陀螺仪数据的回调
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ---- | ------ | ---- |
| res | Object | |
**res 的结构**
| 属性 | 类型 | 说明 |
| ---- | ------ | ------------ |
| x | number | x 轴的角速度 |
| y | number | y 轴的角速度 |
| z | number | z 轴的角速度 |
# qa.startGyroscope(Object object)
启动监听陀螺仪数据
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| interval | string | normal | 否 | 陀螺仪数据的回调频率 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
**object.interval 的合法值**
| 值 | 说明 |
| ------ | ----------------------------------------- |
| normal | 200ms/次 左右的回调频率 | |
| ui | 60ms/次 左右的回调频率,通常用于更新UI | |
| game | 20ms/次 左右的回调频率,通常用于更新游戏 | |
# qa.stopGyroscope(Object object)
关闭陀螺仪计监听器
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
# qa.onDeviceMotionChange(function callback)
注册设备方向变化数据回调监听器
需要先通过 [qa.startDeviceMotionListening()](qa.startDeviceMotionListening.html) 方法启动加速度计监听,并传入 interval 参数做为频率。
可以通过 [qa.stopDeviceMotionListening()](qa.stopDeviceMotionListening.html) 方法停止监听。
## 参数
### function callback
设备方向变化数据的回调
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| alpha | number | 当 手机坐标系 X/Y 和 地球坐标系 X/Y 重合时,绕着 Z 轴转动的夹角为 alpha,范围值为 \[0, 2\*PI)。逆时针转动为正。 |
| beta | number | 当手机坐标系 Y/Z 和 地球坐标系 Y/Z 重合时,绕着 X 轴转动的夹角为 beta。范围值为 \[-1\*PI, PI) 。顶部朝着地球表面转动为正。也有可能朝着用户为正。 |
| gamma | number | 当手机坐标系 X/Z 和 地球坐标系 X/Z 重合时,绕着 Y 轴转动的夹角为 gamma。范围值为 \[-1\*PI/2, PI/2)。右边朝着地球表面转动为正。 |
# qa.startDeviceMotionListening(Object object)
启动监听设备方向数据
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| interval | string | normal | 否 | 设备方向数据的回调频率 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
**object.interval 的合法值**
| 值 | 说明 |
| ------ | ----------------------------------------- |
| normal | 200ms/次 左右的回调频率 | |
| ui | 60ms/次 左右的回调频率,通常用于更新UI | |
| game | 20ms/次 左右的回调频率,通常用于更新游戏 | |
# qa.stopDeviceMotionListening(Object object)
关闭设备方向监听器
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
# qa.getNetworkType(Object object)
获取手机当前使用的网络类型
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ----------- | ------ | -------- |
| networkType | string | 当前使用的网络类型 |
**res.networkType 的合法值**
| 值 | 说明 |
| ------- | -------------------------- |
| wifi | wifi 网络 | |
| 2g | 2g 网络 | |
| 3g | 3g 网络 | |
| 4g | 4g 网络 | |
| unknown | Android 下不常见的网络类型 | |
| none | 无网络 | |
## 示例代码
```js
qa.getNetworkType({
success(res) {
const networkType = res.networkType
}
})
```
# qa.onNetworkStatusChange(function callback)
监听网络状态变化,包括当前连接状态和所连接的网络类型
## 参数
### function callback
网络状态变化事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| isConnected | boolean | 当前是否接入网络 |
| networkType | string | 当前连接的网络类型 |
**networkType 的合法值**
| 值 | 说明 |
| ------- | -------------------------- |
| wifi | wifi 网络 | |
| 2g | 2g 网络 | |
| 3g | 3g 网络 | |
| 4g | 4g 网络 | |
| unknown | Android 下不常见的网络类型 | |
| none | 无网络 | |
## 示例代码
```js
qa.onNetworkStatusChange(function(res) {
console.log(res.isConnected)
console.log(res.networkType)
})
```
# qa.onMemoryWarning(function callback)
监听系统提示的内存不足告警事件回调
当手机系统向快应用进程发出内存不足告警时,就会触发该事件回调。
系统回调该事件回调并不意味快应用会马上被杀,通常只是告警,开发者可在收到此回调之后回收一些不必要资源避免加剧手机内存紧张。
## 参数
### function callback
内存不足告警事件的回调
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ----- | ------ | ---------------------------- |
| level | number | 内存告警等级,对应Android系统中的宏定义 |
**level 的合法值**
| 值 | 说明 |
| --- | ---------------------------- |
| 5 | TRIM_MEMORY_RUNNING_MODERATE | |
| 10 | TRIM_MEMORY_RUNNING_LOW | |
| 15 | TRIM_MEMORY_RUNNING_CRITICAL | |
| 20 | TRIM_MEMORY_UI_HIDDEN | |
## 示例代码
```js
qa.onMemoryWarning(function() {
console.log('onMemoryWarning Receive')
})``
```
# qa.makePhoneCall(Object object)
拨打电话
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| phoneNumber | string | | 是 | 需要拨打的电话号码 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.makePhoneCall({
phoneNumber: '1340000' //仅为示例,并非真实的电话号码
})
```
# qa.scanCode(Object object)
调起客户端扫码界面进行扫码
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| scanType | Array.\<string> | \['barCode', 'qrCode'\] | 否 | 扫码类型 | |
| success | function | | 否 | 接口调用成功的回调函数 | |
| fail | function | | 否 | 接口调用失败的回调函数 | |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) | |
**object.scanType 的合法值**
| 值 | 说明 |
| ---------- | -------------- |
| barCode | 一维码 | |
| qrCode | 二维码 | |
| datamatrix | Data Matrix 码 | |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| -------- | ------ | ------------ |
| result | string | 所扫码的内容 |
| scanType | string | 所扫码的类型 |
**res.scanType 的合法值**
| 值 | 说明 |
| ------------ | ------ |
| QR_CODE | 二维码 | |
| CODABAR | 一维码 | |
| CODE_39 | 一维码 | |
| CODE_93 | 一维码 | |
| CODE_128 | 一维码 | |
| DATA_MATRIX | 二维码 | |
| EAN_8 | 一维码 | |
| EAN_13 | 一维码 | |
| ITF | 一维码 | |
| MAXICODE | 一维码 | |
| RSS_14 | 一维码 | |
| RSS_EXPANDED | 一维码 | |
| UPC_A | 一维码 | |
| UPC_E | 一维码 | |
## 示例代码
```js
qa.scanCode({
success(res) {
console.log(res)
}
})
```
# qa.getScreenBrightness(Object object)
获取屏幕亮度
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object object
| 属性 | 类型 | 说明 |
| ----- | ------ | -------------------------------------- |
| value | number | 屏幕亮度值,范围 0 ~ 1,0 最暗,1 最亮 |
# qa.onUserCaptureScreen(function callback)
监听用户主动截屏动作。用户使用截屏功能时触发
## 参数
### function callback
用户主动截屏动作后的回调函数
## 示例代码
```js
qa.onUserCaptureScreen(function(res) {
console.log('用户截屏了')
})
```
# qa.setKeepScreenOn(Object object)
设置是否保持常亮状态。仅在当前快应用生效,离开快应用后设置失效。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| keepScreenOn | boolean | | 是 | 是否保持屏幕常亮 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.setKeepScreenOn({
keepScreenOn: true
})
```
# qa.setScreenBrightness(Object object)
设置屏幕亮度
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| value | number | | 是 | 屏幕亮度值,范围 0 ~ 1。0 最暗,1 最亮 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
# qa.vibrateLong(Object object)
使手机产生400ms时间的振动
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数 |
# qa.vibrateShort(Object object)
使手机产生15ms时间的振动。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数 |
# WifiInfo
Wifi 信息
## 属性
### string SSID
Wi-Fi 的 SSID
### string BSSID
Wi-Fi 的 BSSID
### boolean secure
Wi-Fi 是否安全
### number signalStrength
Wi-Fi 信号强度
# qa.connectWifi(Object object)
连接 Wi-Fi。若已知 Wi-Fi 信息,可以直接利用该接口连接。
权限要求粗略设备定位
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| SSID | string | | 是 | Wi-Fi 设备 SSID |
| BSSID | string | | 否 | Wi-Fi 设备 BSSID |
| password | string | | 是 | Wi-Fi 设备密码 |
| success | function | | 否 | 接口调用成功的回调函数,此时 Wi-Fi 已经成功连接上 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ---- | ------------------------- | ---------- |
| wifi | [WifiInfo](WifiInfo.html) | Wi-Fi 信息 |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | ---------------------- |
| 0 | ok | 正常 |
| 12002 | password error Wi-Fi | 密码错误 |
| 12003 | connection timeout | 连接超时 |
| 12004 | duplicate request | 重复连接 Wi-Fi |
| 12005 | wifi not turned on | 未打开 Wi-Fi 开关 |
| 12006 | gps not turned on | 未打开 GPS 定位开关 |
| 12007 | user denied | 用户拒绝授权链接 Wi-Fi |
| 12008 | invalid SSID | 无效 SSID |
## 示例代码
```js
qa.connectWifi({
SSID: '',
password: '',
success(res) {
console.log(res.errMsg)
}
})
```
# qa.getConnectedWifi(Object object)
获取已连接的 Wi-Fi 信息。
权限要求
粗略设备定位
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ---- | ------------------------- | ---------- |
| wifi | [WifiInfo](WifiInfo.html) | Wi-Fi 信息 |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | ---------------------- |
| 0 | ok | 正常 |
| 12002 | password error Wi-Fi | 密码错误 |
| 12003 | connection timeout | 连接超时 |
| 12004 | duplicate request | 重复连接 Wi-Fi |
| 12005 | wifi not turned on | 未打开 Wi-Fi 开关 |
| 12006 | gps not turned on | 未打开 GPS 定位开关 |
| 12007 | user denied | 用户拒绝授权链接 Wi-Fi |
| 12008 | invalid SSID | 无效 SSID |
# qa.getWifiList(Object object)
请求获取 Wi-Fi 列表。在 `onGetWifiList` 注册的回调中返回 `wifiList` 数据。
权限要求
粗略设备定位
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | ---------------------- |
| 0 | ok | 正常 |
| 12002 | password error Wi-Fi | 密码错误 |
| 12003 | connection timeout | 连接超时 |
| 12004 | duplicate request | 重复连接 Wi-Fi |
| 12005 | wifi not turned on | 未打开 Wi-Fi 开关 |
| 12006 | gps not turned on | 未打开 GPS 定位开关 |
| 12007 | user denied | 用户拒绝授权链接 Wi-Fi |
| 12008 | invalid SSID | 无效 SSID |
# qa.onGetWifiList(function callback)
监听获取到 Wi-Fi 列表数据事件,在回调中将返回 wifiList
权限要求
粗略设备定位
## 参数
### function callback
获取到 Wi-Fi 列表数据事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| -------- | ---------------------------------- | -------------- |
| wifiList | Array.<[WifiInfo](WifiInfo.html)\> | Wi-Fi 列表数据 |
# qa.onWifiConnected(function callback)
监听连接上 Wi-Fi 的事件
权限要求
粗略设备定位
## 参数
### function callback
连接上 Wi-Fi 的事件的回调函数
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ---- | ------------------------- | ---------- |
| wifi | [WifiInfo](WifiInfo.html) | Wi-Fi 信息 |
# qa.startWifi(Object object)
开启 Wi-Fi 模块,使Wi-Fi 到可用状态
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | ---------------------- |
| 0 | ok | 正常 |
| 12002 | password error Wi-Fi | 密码错误 |
| 12003 | connection timeout | 连接超时 |
| 12004 | duplicate request | 重复连接 Wi-Fi |
| 12005 | wifi not turned on | 未打开 Wi-Fi 开关 |
| 12006 | gps not turned on | 未打开 GPS 定位开关 |
| 12007 | user denied | 用户拒绝授权链接 Wi-Fi |
| 12008 | invalid SSID | 无效 SSID |
## 示例代码
```js
qa.startWifi({
success(res) {
console.log(res.errMsg)
}
})
```
# qa.stopWifi(Object object)
关闭 Wi-Fi 模块,使Wi-Fi 到不可用状态
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------------------- | ---------------------- |
| 0 | ok | 正常 |
| 12002 | password error Wi-Fi | 密码错误 |
| 12003 | connection timeout | 连接超时 |
| 12004 | duplicate request | 重复连接 Wi-Fi |
| 12005 | wifi not turned on | 未打开 Wi-Fi 开关 |
| 12006 | gps not turned on | 未打开 GPS 定位开关 |
| 12007 | user denied | 用户拒绝授权链接 Wi-Fi |
| 12008 | invalid SSID | 无效 SSID |
## 示例代码
```js
qa.stopWifi({
success(res) {
console.log(res.errMsg)
}
})
```
# qa.getFileInfo(Object object)
获取指定文件信息
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| filePath | string | | 是 | 本地文件路径 |
| digestAlgorithm | string | 'md5' | 否 | 计算文件摘要的算法 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
**object.digestAlgorithm 的合法值**
| 值 | 说明 |
| ---- | --------- |
| md5 | md5 算法 | |
| sha1 | sha1 算法 | |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ------ | ------ | ----------------------------------------------- |
| size | number | 文件大小,以字节为单位 |
| digest | string | 按照传入的 digestAlgorithm 计算得出的的文件摘要 |
## 示例代码
```js
qa.getFileInfo({
success(res) {
console.log(res.size)
console.log(res.digest)
}
})
```
# qa.getSavedFileInfo(Object object)
获取本地文件的文件信息。此接口只能用于获取已保存到本地的文件,请使用 [qa.getFileInfo()](qa.getFileInfo.html) 接口来获取临时文件信息。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| filePath | string | | 是 | 文件路径 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ---------- | ------ | --------------------------------------------------------- |
| size | number | 文件大小,单位 B |
| createTime | number | 文件保存时的时间戳,从 1970/01/01 08:00:00 到该时刻的秒数 |
## 示例代码
```js
qa.getSavedFileInfo({
filePath: filePath,
success(res) {
console.log(res.size)
console.log(res.createTime)
}
})
```
# qa.getSavedFileList(Object object)
获取该快应用下已保存的本地缓存文件列表
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| -------- | --------------- | ------------------------------- |
| fileList | Array.\<Object> | 文件数组,每一项是一个 FileItem |
**res.fileList 的结构**
| 属性 | 类型 | 说明 |
| ---------- | ------ | ----------------------------------------------------------- |
| filePath | string | 本地路径 |
| size | number | 本地文件大小,以字节为单位 |
| createTime | number | 文件保存时的时间戳,从 1970/01/01 08:00:00 到当前时间的秒数 |
## 示例代码
```js
qa.getSavedFileList({
success(res) {
console.log(res.fileList)
}
})
```
# qa.openDocument(Object object)
新开页面打开文档
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| filePath | string | | 是 | 文件路径,可通过 downloadFile 获得 | |
| fileType | string | | 否 | 文件类型,指定文件类型打开文件 | |
| success | function | | 否 | 接口调用成功的回调函数 | |
| fail | function | | 否 | 接口调用失败的回调函数 | |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) | |
**object.fileType 的合法值**
| 值 | 说明 |
| ---- | --------- |
| doc | doc 格式 | |
| docx | docx 格式 | |
| xls | xls 格式 | |
| xlsx | xlsx 格式 | |
| ppt | ppt 格式 | |
| pptx | pptx 格式 | |
| pdf | pdf 格式 | |
## 示例代码
```js
qa.downloadFile({
// 示例 url,并非真实存在
url: 'http://example.com/somefile.pdf',
success: function(res) {
const filePath = res.tempFilePath
qa.openDocument({
filePath: filePath,
success: function(res) {
console.log('打开文档成功')
}
})
}
})
```
# qa.removeSavedFile(Object object)
删除本地缓存文件
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| filePath | string | | 是 | 需要删除的文件路径 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.getSavedFileList({
success(res) {
if (res.fileList.length > 0) {
qa.removeSavedFile({
filePath: res.fileList[0].filePath,
complete(res) {
console.log(res)
}
})
}
}
})
```
# qa.saveFile(Object object)
保存文件到本地。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| tempFilePath | string | | 是 | 需要保存的文件的临时路径 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ------------- | ------ | ---------------- |
| savedFilePath | string | 存储后的文件路径 |
## 示例代码
```js
qa.chooseImage({
success: function(res) {
const tempFilePaths = res.tempFilePaths
qa.saveFile({
tempFilePath: tempFilePaths[0],
success(res) {
const savedFilePath = res.savedFilePath
}
})
}
})
```
# qa.chooseLocation(Object object)
> 调用前需要 [用户授权](../../framework/open-ability/authorize.html) scope.userLocation
打开地图选择位置。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| --------- | ------ | ------------------------------------------------------------------- |
| name | string | 位置名称 |
| address | string | 详细地址 |
| latitude | string | 纬度,浮点数,范围为-90~90,负数表示南纬。使用 gcj02 国测局坐标系 |
| longitude | string | 经度,浮点数,范围为-180~180,负数表示西经。使用 gcj02 国测局坐标系 |
# qa.getLocation(Object object)
> 调用前需要 [用户授权](../../framework/open-ability/authorize.html) scope.userLocation
获取当前的地理位置、速度。当用户离开快应用后,此接口无法调用。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| type | string | wgs84 | 否 | wgs84 返回 gps 坐标,gcj02 返回可用于 qa.openLocation 的坐标 | |
| altitude | string | false | 否 | 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度 | |
| success | function | | 否 | 接口调用成功的回调函数 | |
| fail | function | | 否 | 接口调用失败的回调函数 | |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) | |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| ------------------ | ------ | ----------------------------------- |
| latitude | number | 纬度,范围为 -90~90,负数表示南纬 | |
| longitude | number | 经度,范围为 -180~180,负数表示西经 | |
| speed | number | 速度,单位 m/s | |
| accuracy | number | 位置的精确度 | |
| altitude | number | 高度,单位 m | |
| horizontalAccuracy | number | 水平精度,单位 m | |
## 示例代码
```js
qa.getLocation({
type: 'wgs84',
success(res) {
const latitude = res.latitude
const longitude = res.longitude
const speed = res.speed
const accuracy = res.accuracy
}
})
```
## 注意
::: warning
- 工具中定位模拟使用 IP 定位,可能会有一定误差。且工具目前仅支持 gcj02 坐标。
- 使用第三方服务进行逆地址解析时,请确认第三方服务默认的坐标系,正确进行坐标转换。
:::
# qa.openLocation(Object object)
使用快应用内置地图查看位置
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| latitude | number | | 是 | 纬度,范围为-90~90,负数表示南纬。使用 gcj02 国测局坐标系 |
| longitude | number | | 是 | 经度,范围为-180~180,负数表示西经。使用 gcj02 国测局坐标系 |
| scale | number | 18 | 否 | 缩放比例,范围 5~18 |
| name | string | | 否 | 位置名 |
| address | string | | 否 | 地址的详细说明 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.getLocation({
type: 'gcj02', //返回可以用于qa.openLocation的经纬度
success(res) {
const latitude = res.latitude
const longitude = res.longitude
qa.openLocation({
latitude,
longitude,
scale: 18
})
}
})
```
# InnerAudioContext.destroy()
销毁当前InnerAudioContext实例
# InnerAudioContext
InnerAudioContext 实例
可以通过 [qa.createInnerAudioContext](qa.createInnerAudioContext.html) 接口创建实例。
## 属性
### string src
用于播放的音频资源地址
### number startTime
开始播放的位置(单位:s),默认为 0
### boolean autoplay
是否自动播放,默认为 `false`
### boolean loop
是否循环播放,默认为 `false`
### number volume
播放音频的音量。范围 0~1。默认是 1
### number duration
当前音频资源的长度(单位 s)。只读属性,只在当前有合法的 src 时能返回
### number currentTime
当前音频的播放位置(单位 s)。只读属性,只有在当前有合法的 src 时返回
### boolean paused
当前是否暂停或停止状态(只读)
## 方法
### [InnerAudioContext.play()](InnerAudioContext.play.html)
播放音频
### [InnerAudioContext.pause()](InnerAudioContext.pause.html)
暂停播放音频,此时重新播放会从暂停处开始播放
### [InnerAudioContext.stop()](InnerAudioContext.stop.html)
停止播放音频,停止之后的重新播放会从头开始播放
### [InnerAudioContext.seek(number position)](InnerAudioContext.seek.html)
跳转到该音频的指定位置
### [InnerAudioContext.destroy()](InnerAudioContext.destroy.html)
销毁当前InnerAudioContext实例
### [InnerAudioContext.onCanplay(function callback)](./InnerAudioContext.onCanplay.html)
订阅**音频进入可以播放状态事件**回调,不能保证后续可以流畅播放
### [InnerAudioContext.offCanplay(function callback)](./InnerAudioContext.offCanplay.html)
取消订阅**音频进入可以播放状态事件**
### [InnerAudioContext.onPlay(function callback)](./InnerAudioContext.onPlay.html)
订阅**音频播放事件**回调
### [InnerAudioContext.offPlay(function callback)](./InnerAudioContext.offPlay.html)
取消订阅**音频播放事件**
### [InnerAudioContext.onPause(function callback)](./InnerAudioContext.onPause.html)
订阅**音频暂停事件**回调
### [InnerAudioContext.offPause(function callback)](./InnerAudioContext.offPause.html)
取消订阅**音频暂停事件**
### [InnerAudioContext.onStop(function callback)](./InnerAudioContext.onStop.html)
订阅**音频停止事件**回调
### [InnerAudioContext.offStop(function callback)](./InnerAudioContext.offStop.html)
取消订阅**音频停止事件**
### [InnerAudioContext.onEnded(function callback)](./InnerAudioContext.onEnded.html)
订阅**音频自然播放至结束的事件**回调
### [InnerAudioContext.offEnded(function callback)](./InnerAudioContext.offEnded.html)
取消订阅**音频自然播放至结束的事件**
### [InnerAudioContext.onTimeUpdate(function callback)](./InnerAudioContext.onTimeUpdate.html)
订阅**音频播放进度更新事件**回调
### [InnerAudioContext.offTimeUpdate(function callback)](./InnerAudioContext.offTimeUpdate.html)
取消订阅**音频播放进度更新事件**
### [InnerAudioContext.onError(function callback)](./InnerAudioContext.onError.html)
订阅**音频播放错误事件**回调
### [InnerAudioContext.offError(function callback)](./InnerAudioContext.offError.html)
取消订阅**音频播放错误事件**
### [InnerAudioContext.onWaiting(function callback)](./InnerAudioContext.onWaiting.html)
订阅**音频加载中事件**回调,当音频源因数据不足,需要停下来加载时会触发回调
### [InnerAudioContext.offWaiting(function callback)](./InnerAudioContext.offWaiting.html)
取消订阅**音频加载中事件**
### [InnerAudioContext.onSeeking(function callback)](./InnerAudioContext.onSeeking.html)
订阅**音频进行跳转操作的事件**回调
### [InnerAudioContext.offSeeking(function callback)](./InnerAudioContext.offSeeking.html)
取消订阅**音频进行跳转操作的事件**
### [InnerAudioContext.onSeeked(function callback)](./InnerAudioContext.onSeeked.html)
订阅**音频完成跳转操作的事件**回调
### [InnerAudioContext.offSeeked(function callback)](./InnerAudioContext.offSeeked.html)
取消订阅**音频完成跳转操作的事件**
## 支持格式
| 格式 | Android |
| ---- | ------- |
| flac | √ |
| m4a | √ |
| ogg | √ |
| ape | √ |
| amr | √ |
| wma | √ |
| wav | √ |
| mp3 | √ |
| mp4 | √ |
| aac | √ |
| aiff | x |
| caf | x |
## 示例代码
```js
const innerAudioContext = qa.createInnerAudioContext()
innerAudioContext.autoplay = true
innerAudioContext.src = 'http://xxx.quickapp.cn' // 示例地址,不存在该地址的真实音频
innerAudioContext.onPlay(() => {
console.log('开始播放')
})
innerAudioContext.onError(res => {
console.log(res.errMsg)
console.log(res.errCode)
})
```
# InnerAudioContext.offCanplay(function callback)
取消订阅**音频进入可以播放状态事件**
## 参数
### function callback
**音频进入可以播放状态的事件**的回调
# InnerAudioContext.offEnded(function callback)
取消订阅**音频自然播放至结束的事件**
## 参数
### function callback
**音频自然播放至结束的事件**的回调
# InnerAudioContext.offError(function callback)
取消订阅**音频播放错误事件**
## 参数
### function callback
**音频播放错误事件**的回调
# InnerAudioContext.offPause(function callback)
取消订阅**音频暂停事件**
## 参数
### function callback
**音频暂停事件**的回调
# InnerAudioContext.offPlay(function callback)
取消订阅**音频播放事件**
## 参数
### function callback
**音频播放事件**的回调
# InnerAudioContext.offSeeked(function callback)
取消订阅**音频完成跳转操作的事件**
## 参数
### function callback
**音频完成跳转操作的事件**的回调
# InnerAudioContext.offSeeking(function callback)
取消订阅**音频进行跳转操作的事件**
## 参数
### function callback
**音频进行跳转操作的事件**的回调
# InnerAudioContext.offStop(function callback)
取消订阅**音频停止事件**
## 参数
### function callback
**音频停止事件**的回调
# InnerAudioContext.offTimeUpdate(function callback)
取消订阅**音频播放进度更新事件**
## 参数
### function callback
**音频播放进度更新事件**的回调
# InnerAudioContext.offWaiting(function callback)
取消订阅**音频加载中事件**
## 参数
### function callback
**音频加载中事件**的回调
# InnerAudioContext.onCanplay(function callback)
订阅**音频进入可以播放状态的事件**回调,不能保证后续可以流畅播放
## 参数
### function callback
**音频进入可以播放状态的事件**的回调
# InnerAudioContext.onEnded(function callback)
订阅**音频自然播放至结束的事件**回调
## 参数
### function callback
**音频自然播放至结束的事件**的回调
# InnerAudioContext.onError(function callback)
订阅**音频播放错误事件**回调
## 参数
### function callback
**音频播放错误事件**的回调
#### 参数
##### Object res
| 属性 | 类型 | 说明 |
| ------- | ------ | ---- |
| errCode | number | |
**errCode 的合法值**
| 值 | 说明 |
| ----- | -------- |
| 10001 | 系统错误 | |
| 10002 | 网络错误 | |
| 10003 | 文件错误 | |
| 10004 | 格式错误 | |
| \-1 | 未知错误 | |
# InnerAudioContext.onPause(function callback)
订阅**音频暂停事件**回调
## 参数
### function callback
**音频暂停事件**的回调
# InnerAudioContext.onPlay(function callback)
订阅**音频播放事件**回调
## 参数
### function callback
**音频播放事件**的回调
# InnerAudioContext.onSeeked(function callback)
订阅**音频完成跳转操作的事件**回调
## 参数
### function callback
**音频完成跳转操作的事件**的回调
# InnerAudioContext.onSeeking(function callback)
订阅**音频进行跳转操作的事件**回调
## 参数
### function callback
**音频进行跳转操作的事件**的回调
# InnerAudioContext.onStop(function callback)
订阅**音频停止事件**回调
## 参数
### function callback
**音频停止事件**的回调
# InnerAudioContext.onTimeUpdate(function callback)
订阅**音频播放进度更新事件**回调
## 参数
### function callback
**音频播放进度更新事件**的回调
# InnerAudioContext.onWaiting(function callback)
订阅**音频加载中事件**回调,当音频源因数据不足,需要停下来加载时会触发回调
## 参数
### function callback
**音频加载中事件**的回调
# InnerAudioContext.pause()
暂停播放音频,此时重新播放会从暂停处开始播放
# InnerAudioContext.play()
播放音频
# InnerAudioContext.seek(number position)
跳转到该音频的指定位置
## 参数
### number position
跳转的时间,单位秒,支持精确到小数点后 3 位。即最低支持到毫秒级别精确度
# InnerAudioContext.stop()
停止播放音频,停止之后的重新播放会从头开始播放
# [InnerAudioContext](InnerAudioContext.html) qa.createInnerAudioContext()
创建用于音频播放 [audio](../../../component/audio.html) 的上下文 [InnerAudioContext](InnerAudioContext.html) 对象。
## 返回值
### [InnerAudioContext](InnerAudioContext.html)
# qa.setInnerAudioOption(Object object)
设置 [InnerAudioContext](InnerAudioContext.html) 的播放选项,目前只支持mixWithOther
设置之后对当前快应用全局生效。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| mixWithOther | boolean | true | 否 | 是否与其他音频混播,默认为true,设置为 false 之后,会暂停其他应用或快应用在播放的音乐 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
# BackgroundAudioManager
BackgroundAudioManager 实例,可通过 [qa.getBackgroundAudioManager](qa.getBackgroundAudioManager.html) 获取。
## 属性
### string src
默认为空字符串,**当设置了新的 src 时,会自动开始播放**,目前支持的格式有 m4a, aac, mp3, wav。
### number startTime
音频开始播放的位置(单位:s)。
### string title
音频标题,用于原生音频播放器音频标题(必填)。原生音频播放器中的分享功能,分享出去的卡片标题,也将使用该值。
### string epname
专辑名,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
### string singer
歌手名,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
### string coverImgUrl
封面图 URL,用于做原生音频播放器背景图。原生音频播放器中的分享功能,分享出去的卡片配图及背景也将使用该图。
### string webUrl
页面链接,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
### string protocol
音频协议。默认值为 'http',设置 'hls' 可以支持播放 HLS 协议的直播音频。
### number duration
当前音频的长度(单位:s),只有在有合法 src 时返回。(只读)
### number currentTime
当前音频的播放位置(单位:s),只有在有合法 src 时返回。(只读)
### boolean paused
当前是否暂停或停止。(只读)
### number buffered
音频已缓冲的时间,仅保证当前播放时间点到此时间点内容已缓冲。(只读)
## 方法
### [BackgroundAudioManager.play()](BackgroundAudioManager.play.html)
播放音乐
### [BackgroundAudioManager.pause()](BackgroundAudioManager.pause.html)
暂停音乐
### [BackgroundAudioManager.seek(number currentTime)](BackgroundAudioManager.seek.html)
跳转到指定位置
### [BackgroundAudioManager.stop()](BackgroundAudioManager.stop.html)
停止音乐
### [BackgroundAudioManager.onCanplay(function callback)](./BackgroundAudioManager.onCanplay.html)
监听背景音频进入可播放状态事件。 但不保证后面可以流畅播放
### [BackgroundAudioManager.onWaiting(function callback)](./BackgroundAudioManager.onWaiting.html)
监听音频加载中事件。当音频因为数据不足,需要停下来加载时会触发
### [BackgroundAudioManager.onError(function callback)](./BackgroundAudioManager.onError.html)
监听背景音频播放错误事件
### [BackgroundAudioManager.onPlay(function callback)](./BackgroundAudioManager.onPlay.html)
监听背景音频播放事件
### [BackgroundAudioManager.onPause(function callback)](./BackgroundAudioManager.onPause.html)
监听背景音频暂停事件
### [BackgroundAudioManager.onSeeking(function callback)](./BackgroundAudioManager.onSeeking.html)
监听背景音频开始跳转操作事件
### [BackgroundAudioManager.onSeeked(function callback)](./BackgroundAudioManager.onSeeked.html)
监听背景音频完成跳转操作事件
### [BackgroundAudioManager.onEnded(function callback)](./BackgroundAudioManager.onEnded.html)
监听背景音频自然播放结束事件
### [BackgroundAudioManager.onStop(function callback)](./BackgroundAudioManager.onStop.html)
监听背景音频停止事件
### [BackgroundAudioManager.onTimeUpdate(function callback)](./BackgroundAudioManager.onTimeUpdate.html)
监听背景音频播放进度更新事件,只有快应用在前台时会回调。
## 示例代码
```js
const backgroundAudioManager = qa.getBackgroundAudioManager()
backgroundAudioManager.title = '此时此刻'
backgroundAudioManager.epname = '此时此刻'
backgroundAudioManager.singer = '许巍'
backgroundAudioManager.coverImgUrl =
'http://y.gtimg.cn/music/photo_new/T002R300x300M000003rsKF44GyaSk.jpg?max_age=2592000'
// 设置了 src 之后会自动播放
backgroundAudioManager.src =
'http://ws.stream.qqmusic.qq.com/M500001VfvsJ21xFqb.mp3?guid=ffffffff82def4af4b12b3cd9337d5e7&uin=346897220&vkey=6292F51E1E384E061FF02C31F716658E5C81F5594D561F2E88B854E81CAAB7806D5E4F103E55D33C16F3FAC506D1AB172DE8600B37E43FAD&fromtag=46'
```
# BackgroundAudioManager.onCanplay(function callback)
监听背景音频进入可播放状态事件。 但不保证后面可以流畅播放
## 参数
### function callback
背景音频进入可播放状态事件的回调函数
# BackgroundAudioManager.onEnded(function callback)
监听背景音频自然播放结束事件
## 参数
### function callback
背景音频自然播放结束事件的回调函数
# BackgroundAudioManager.onError(function callback)
监听背景音频播放错误事件
## 参数
### function callback
背景音频播放错误事件的回调函数
# BackgroundAudioManager.onPause(function callback)
监听背景音频暂停事件
## 参数
### function callback
背景音频暂停事件的回调函数
# BackgroundAudioManager.onPlay(function callback)
监听背景音频播放事件
## 参数
### function callback
背景音频播放事件的回调函数
# BackgroundAudioManager.onSeeked(function callback)
监听背景音频完成跳转操作事件
## 参数
### function callback
背景音频完成跳转操作事件的回调函数
# BackgroundAudioManager.onSeeking(function callback)
监听背景音频开始跳转操作事件
## 参数
### function callback
背景音频开始跳转操作事件的回调函数
# BackgroundAudioManager.onStop(function callback)
监听背景音频停止事件
## 参数
### function callback
背景音频停止事件的回调函数
# BackgroundAudioManager.onTimeUpdate(function callback)
监听背景音频播放进度更新事件,只有快应用在前台时会回调。
## 参数
### function callback
背景音频播放进度更新事件的回调函数
# BackgroundAudioManager.onWaiting(function callback)
监听音频加载中事件。当音频因为数据不足,需要停下来加载时会触发
## 参数
### function callback
音频加载中事件的回调函数
# BackgroundAudioManager.pause()
暂停音乐
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------- | -------- |
| 10001 | | 系统错误 |
| 10002 | | 网络错误 |
| 10003 | | 文件错误 |
| 10004 | | 格式错误 |
| \-1 | | 未知错误 |
# BackgroundAudioManager.play()
播放音乐
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------- | -------- |
| 10001 | | 系统错误 |
| 10002 | | 网络错误 |
| 10003 | | 文件错误 |
| 10004 | | 格式错误 |
| \-1 | | 未知错误 |
# BackgroundAudioManager.seek(number currentTime)
跳转到指定位置
## 参数
### number currentTime
跳转的位置,单位 s。精确到小数点后 3 位,即支持 ms 级别精确度
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------- | -------- |
| 10001 | | 系统错误 |
| 10002 | | 网络错误 |
| 10003 | | 文件错误 |
| 10004 | | 格式错误 |
| \-1 | | 未知错误 |
# BackgroundAudioManager.stop()
停止音乐
## 错误
| 错误码 | 错误信息 | 说明 |
| ------ | -------- | -------- |
| 10001 | | 系统错误 |
| 10002 | | 网络错误 |
| 10003 | | 文件错误 |
| 10004 | | 格式错误 |
| \-1 | | 未知错误 |
# [BackgroundAudioManager](BackgroundAudioManager.html) qa.getBackgroundAudioManager()
获取**全局唯一**的背景音频管理器。 快应用切入后台,如果音频处于播放状态,可以继续播放。但是后台状态不能通过调用 API 操纵音频的播放状态。
若需要在快应用切后台后继续播放音频,需要在 [app.json](../../../reference/configuration/app.html) 中配置 `requiredBackgroundModes` 属性。开发版和体验版上可以直接生效,正式版还需通过审核。
## 返回值
### [BackgroundAudioManager](BackgroundAudioManager.html)
# qa.getBackgroundAudioPlayerState(Object object)
获取后台音乐播放状态。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
#### object.success 回调函数
##### 参数
###### Object res
| 属性 | 类型 | 说明 |
| --------------- | ------ | ----------------------------------------------------- |
| duration | number | 选定音频的长度(单位:s),只有在音乐播放中时返回 |
| currentPosition | number | 选定音频的播放位置(单位:s),只有在音乐播放中时返回 |
| status | number | 播放状态 |
| dataUrl | string | 歌曲数据链接,只有在音乐播放中时返回 |
**res.status 的合法值**
| 值 | 说明 |
| --- | ------------ |
| 0 | 暂停中 | |
| 1 | 播放中 | |
| 2 | 没有音乐播放 | |
## 示例代码
```js
qa.getBackgroundAudioPlayerState({
success(res) {
const status = res.status
const dataUrl = res.dataUrl
const currentPosition = res.currentPosition
const duration = res.duration
}
})
```
# qa.onBackgroundAudioPause(function callback)
监听音乐暂停事件。
## 参数
### function callback
音乐暂停事件的回调函数
# qa.onBackgroundAudioPlay(function callback)
监听音乐播放事件。
## 参数
### function callback
音乐播放事件的回调函数
# qa.onBackgroundAudioStop(function callback)
监听音乐停止事件。
## 参数
### function callback
音乐停止事件的回调函数
# qa.pauseBackgroundAudio(Object object)
暂停播放音乐。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.pauseBackgroundAudio()
```
# qa.playBackgroundAudio(Object object)
使用后台播放器播放音乐。对于快应用来说,只能同时有一个后台音乐在播放。当用户离开快应用后,音乐将暂停播放;当用户在其他快应用占用了音乐播放器,原有快应用内的音乐将停止播放。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| dataUrl | string | | 是 | 音乐链接,目前支持的格式有 m4a, aac, mp3, wav |
| title | string | | 否 | 音乐标题 |
| coverImgUrl | string | | 否 | 封面 URL |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.playBackgroundAudio({
dataUrl: '',
title: '',
coverImgUrl: ''
})
```
# qa.seekBackgroundAudio(Object object)
控制音乐播放进度。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| position | number | | 是 | 音乐位置,单位:秒 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.seekBackgroundAudio({
position: 30
})
```
# qa.stopBackgroundAudio(Object object)
停止播放音乐。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## 示例代码
```js
qa.stopBackgroundAudio()
```
# qa.chooseImage(Object object)
从本地相册选择图片或打开系统相机拍照。
## 参数
### Object object
| 属性 | 类型 | <div style="width: 50px">默认值</div> | <div style="width: 50px">必填</div> | 说明 |
| --- | --- | --- | --- | --- |
| count | number | 9 | 否 | 最多可以选择的图片张数 |
| sizeType | Array.\<string> | \['original', 'compressed'\] | 否 | 所选的图片的尺寸 |
| sourceType | Array.\<string> | \['album', 'camera'\] | 否 | 选择图片的来源 |
| success | function | | 否 | 接口调用成功的回调函数 |
| fail | function | | 否 | 接口调用失败的回调函数 |
| complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
**object.sizeType 的合法值**
| 值 | 说明 |
| ---------- | ------ |
| original | 原图 | |
| compressed | 压缩图 | |
**object.sourceType 的合法值**
| 值 | 说明 |
| ------ | ---------- |
| album | 从相册选图 | |
| camera | 使用相机 | |
#### object.success 回调函数