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
---
This diff is collapsed.
# 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,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)
针对 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,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)
```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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)
This diff is collapsed.
# [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,iVBORw0KGgoAAAANSUhEUgAAAT4AAACpCAYAAACyLFF/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAaUSURBVHhe7dVBbhtJFETBvv+lZXBr2IsClPZTdRjQjkh8vuLEPF/+KaCAAi8r8Lzs+/q6CiigwBf4/AgUUOB1BcD3uif3hRVQAHx+Awoo8LoC4Hvdk/vCCigAPr8BBRR4XYE/wvc8z5c/DfwG/AZ+0m/gRO+/wncy4rMKKKDA/yzwAfrkH/hOavmsAgokC4Av+SyOUkCBZQHwLevaVkCBZAHwJZ/FUQoosCwAvmVd2wookCwAvuSzOEoBBZYFwLesa1sBBZIFwJd8FkcpoMCyAPiWdW0roECyAPiSz+IoBRRYFgDfsq5tBRRIFgBf8lkcpYACywLgW9a1rYACyQLgSz6LoxRQYFkAfMu6thVQIFkAfMlncZQCCiwLgG9Z17YCCiQLgC/5LI5SQIFlAfAt69pWQIFkAfAln8VRCiiwLAC+ZV3bCiiQLAC+5LM4SgEFlgXAt6xrWwEFkgXAl3wWRymgwLIA+JZ1bSugQLIA+JLP4igFFFgWAN+yrm0FFEgWAF/yWRylgALLAuBb1rWtgALJAuBLPoujFFBgWQB8y7q2FVAgWQB8yWdxlAIKLAuAb1nXtgIKJAuAL/ksjlJAgWUB8C3r2lZAgWQB8CWfxVEKKLAsAL5lXdsKKJAsAL7kszhKAQWWBcC3rGtbAQWSBcCXfBZHKaDAsgD4lnVtK6BAsgD4ks/iKAUUWBYA37KubQUUSBYAX/JZHKWAAssC4FvWta2AAskC4Es+i6MUUGBZAHzLurYVUCBZAHzJZ3GUAgosC4BvWde2AgokC4Dvt2f5BPGnwXf/BpL/9b/4KPCBD/T/4H92LzYm+dXBBz7wgS+J0/Io8IEPfOBbGpPcBh/4wAe+JE7Lo8AHPvCBb2lMcht84AMf+JI4LY8CH/jAB76lMclt8IEPfOBL4rQ8CnzgAx/4lsYkt8EHPvCBL4nT8ijwgQ984Fsak9wGH/jAB74kTsujwAc+8IFvaUxyG3zgAx/4kjgtjwIf+MAHvqUxyW3wgQ984EvitDwKfOADH/iWxiS3wQc+8IEvidPyKPCBD3zgWxqT3AYf+MAHviROy6PABz7wgW9pTHIbfOADH/iSOC2PAh/4wAe+pTHJbfCBD3zgS+K0PAp84AMf+JbGJLfBBz7wgS+J0/Io8IEPfOBbGpPcBh/4wAe+JE7Lo8AHPvCBb2lMcht84AMf+JI4LY8CH/jAB76lMclt8IEPfOBL4rQ8CnzgAx/4lsYkt8EHPvCBL4nT8ijwgQ984Fsak9wGH/jAB74kTsujwAc+8IFvaUxyG3zgAx/4kjgtjwIf+MAHvqUxyW3wgQ984EvitDwKfOADH/iWxiS3wQc+8IEvidPyKPCBD3zgWxqT3AYf+MAHviROy6PABz7wgW9pTHIbfOADH/iSOC2PAh/4wAe+pTHJbfCBD3zgS+K0PAp84AMf+JbGJLfBBz7wgS+J0/Io8IEPfOBbGpPcBh/4wAe+JE7Lo8AHPvCBb2lMcht84AMf+JI4LY8CH/jAB76lMclt8IEPfOBL4rQ8CnzgAx/4lsYkt8EHPvCBL4nT8ijwgQ984Fsak9wGH/jAB74kTsujwAc+8IFvaUxyG3zgAx/4kjgtjwIf+MAHvqUxyW3wgQ984EvitDwKfOADH/iWxiS3wQc+8IEvidPyKPCBD3zgWxqT3AYf+MAHviROy6PABz7wgW9pTHIbfOADH/iSOC2PAh/4wAe+pTHJbfCBD3zgS+K0PAp84AMf+JbGJLfBBz7wgS+J0/Io8IEPfOBbGpPcBh/4wAe+JE7Lo8AHPvCBb2lMcht84AMf+JI4LY8CH/jAB76lMclt8IEPfOBL4rQ8CnzgAx/4lsYkt8EHPvCBL4nT8ijwgQ984Fsak9wGH/jAB74kTsujwAc+8IFvaUxyG3zgAx/4kjgtjwIf+MAHvqUxyW3wgQ984EvitDwKfOADH/iWxiS3wQc+8IEvidPyKPCBD3zgWxqT3AYf+MAHviROy6PABz7wgW9pTHIbfOADH/iSOC2PAh/4wAe+pTHJbfCBD3zgS+K0PAp84AMf+JbGJLfBBz7wgS+J0/Io8IEPfOBbGpPc/jb4PkP+NPAb8Bv4Kb+BE5Gfkw/7rAIKKHBDAfDd8Iq+gwIKHBUA31EuH1ZAgRsKgO+GV/QdFFDgqAD4jnL5sAIK3FAAfDe8ou+ggAJHBcB3lMuHFVDghgLgu+EVfQcFFDgqAL6jXD6sgAI3FADfDa/oOyigwFGBX6Fk8L8eRTvUAAAAAElFTkSuQmCC)
# 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,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)
# 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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)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment