Skip to content

Commit

Permalink
feat(components): h5增加canvas组件
Browse files Browse the repository at this point in the history
  • Loading branch information
Littly committed Apr 2, 2019
1 parent dc5be08 commit 09d1396
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 104 deletions.
76 changes: 68 additions & 8 deletions packages/taro-components/src/components/canvas/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,74 @@
import Nerv from 'nervjs'
import Nerv, { findDOMNode } from 'nervjs'
import touchable from '../../utils/touchable'
import classnames from 'classnames'
import { isNumber } from '../../utils/index'

class Canvas extends Nerv.Component {
import './style/index.css'

// canvas-id String canvas 组件的唯一标识符
// disable-scroll Boolean false 当在 canvas 中移动时且有绑定手势事件时,禁止屏幕滚动以及下拉刷新
// bindtouchstart EventHandle 手指触摸动作开始
// bindtouchmove EventHandle 手指触摸后移动
// bindtouchend EventHandle 手指触摸动作结束
// bindtouchcancel EventHandle 手指触摸动作被打断,如来电提醒,弹窗
// bindlongtap EventHandle 手指长按 500ms 之后触发,触发了长按事件后进行移动不会触发屏幕的滚动
// binderror EventHandle 当发生错误时触发 error 事件,detail = {errMsg: 'something wrong'}

@touchable()
export default class Canvas extends Nerv.Component {
static defaultProps = {
canvasId: '',
disableScroll: false,
bindError: null
}
state = {
width: null,
height: null
}
getRef = ref => {
const dom = findDOMNode(ref)
this.canvasDom = dom
}
shouldComponentUpdate (nProps, nState) {
if (nState.width !== this.state.width
|| nState.height !== this.state.height) {
return true
}
return false
}
componentDidMount () {
console.error('H5 暂不支持 Canvas 组件!,请直接用 H5 原生 canvas')
if (!this.canvasDom) return
const { width, height } = this.canvasDom.getBoundingClientRect()
this.setState({
width,
height
})
}

render () {
const { ...reset } = this.props
return <div {...reset}>{this.props.children}</div>
const { canvasId, onTouchStart, onTouchMove, onTouchEnd, onTouchCancel, className } = this.props
const { width, height } = this.state
const props = {
canvasId,
onTouchStart,
onTouchMove,
onTouchEnd,
onTouchCancel
}
if (isNumber(width)) {
props.width = width
}
if (isNumber(height)) {
props.height = height
}
return (
<div
className={classnames(
'taro-canvas',
className
)}
ref={this.getRef}>
<canvas {...props} />
</div>
)
}
}

export default Canvas
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.taro-canvas {
position: relative;
width: 300px;
height: 150px;
}
6 changes: 4 additions & 2 deletions packages/taro-components/src/components/navigator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import Taro from '@tarojs/taro-h5'
import classNames from 'classnames'
import Nerv from 'nervjs'

import touchable from '../../utils/touchable'
import hoverable from '../../utils/hoverable'

import './navigator.css'

/* eslint-disable prefer-promise-reject-errors */

/*
*target String self 在哪个目标上发生跳转,默认当前小程序,可选值self/miniProgram
*url String 当前小程序内的跳转链接
Expand Down Expand Up @@ -103,7 +105,7 @@ class Navigator extends Taro.Component {
}
}

export default touchable({
export default hoverable({
hoverClass: 'navigator-hover',
hoverStopPropergation: false,
hoverStartTime: 50,
Expand Down
114 changes: 114 additions & 0 deletions packages/taro-components/src/utils/hoverable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import Taro from '@tarojs/taro-h5'
import Nerv from 'nervjs'
import omit from 'omit.js'

/**
* 添加touch能力
* @param {Object} Options hoverable的默认配置
* @param {String} [Options.hoverClass] 指定点击时的样式类,当hover-class="none"时,没有点击态效果
* @param {Boolean} [Options.hoverStopPropergation] 指定是否阻止本节点的祖先节点出现点击态
* @param {Number} [Options.hoverStartTime] 按住后多久出现点击态,单位毫秒
* @param {Number} [Options.hoverStayTime] 手指松开后点击态保留时间,单位毫秒
*/
const hoverable = ({
hoverClass,
hoverStopPropergation,
hoverStartTime,
hoverStayTime
}) => {
return ComponentClass => {
return class HoverableComponent extends Taro.Component {
static defaultProps = {
hoverClass,
hoverStopPropergation,
hoverStartTime,
hoverStayTime
}
constructor (props, ctx) {
super(props, ctx)
this.state = this.getInitState(this.props)
}

touchStartTimer = null
touchEndTimer = null

state = {
isHover: false,
onTouchStart: null,
onTouchEnd: null
}

getInitState = ({ hoverClass, hoverStartTime, hoverStayTime, hoverStopPropergation, onTouchStart, onTouchEnd }) => {
if (hoverClass === 'none') return
return {
onTouchStart: this.getOnTouchStart({ hoverStartTime, hoverStopPropergation, onTouchStart }),
onTouchEnd: this.getOnTouchEnd({ hoverStayTime, hoverStopPropergation, onTouchEnd })
}
}
getOnTouchStart = ({ hoverStartTime, hoverStopPropergation, onTouchStart }) => {
return e => {
onTouchStart && onTouchStart(e)
hoverStopPropergation && e.stopPropergation()
this.touchStartTimer && clearTimeout(this.touchStartTimer)
this.touchEndTimer && clearTimeout(this.touchEndTimer)
this.touchStartTimer = setTimeout(() => {
this.setState({
isHover: true
})
}, hoverStartTime)
}
}
getOnTouchEnd = ({ hoverStayTime, hoverStopPropergation, onTouchEnd }) => {
return e => {
onTouchEnd && onTouchEnd(e)
hoverStopPropergation && e.stopPropergation()
this.touchStartTimer && clearTimeout(this.touchStartTimer)
this.touchEndTimer && clearTimeout(this.touchEndTimer)
this.touchEndTimer = setTimeout(() => {
this.setState({
isHover: false
})
}, hoverStayTime)
}
}
reset = () => {
this.setState({
isHover: false
})
}
componentWillMount () {
document.body.addEventListener('touchstart', this.reset)
}
componentWillReceiveProps (nProps, nCtx) {
if (
nProps.hoverClass !== this.props.hoverClass ||
nProps.hoverStopPropergation !== this.props.hoverStopPropergation ||
nProps.hoverStartTime !== this.props.hoverStartTime ||
nProps.hoverStayTime !== this.props.hoverStayTime
) {
const stateObj = this.getInitState(nProps)
this.setState(stateObj)
}
}
componentWillUnmount () {
document.body.removeEventListener('touchstart', this.reset)
}
render () {
const { isHover, onTouchStart, onTouchEnd } = this.state
const props = {
...omit(this.props, [
'hoverStopPropergation',
'hoverStartTime',
'hoverStayTime'
]),
isHover,
onTouchStart,
onTouchEnd
}
return <ComponentClass {...props} />
}
}
}
}

export default hoverable
4 changes: 4 additions & 0 deletions packages/taro-components/src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,7 @@ export const splitUrl = _url => {

return res
}

export const isNumber = obj => {
return typeof obj === 'number'
}
133 changes: 39 additions & 94 deletions packages/taro-components/src/utils/touchable.js
Original file line number Diff line number Diff line change
@@ -1,110 +1,55 @@
import Taro from '@tarojs/taro-h5'
import Nerv from 'nervjs'
import omit from 'omit.js'
import Nerv from 'nervjs'

/**
* 添加touch能力
* @param {Object} Options touchable的默认配置
* @param {String} [Options.hoverClass] 指定点击时的样式类,当hover-class="none"时,没有点击态效果
* @param {Boolean} [Options.hoverStopPropergation] 指定是否阻止本节点的祖先节点出现点击态
* @param {Number} [Options.hoverStartTime] 按住后多久出现点击态,单位毫秒
* @param {Number} [Options.hoverStayTime] 手指松开后点击态保留时间,单位毫秒
*/
const touchable = ({
hoverClass,
hoverStopPropergation,
hoverStartTime,
hoverStayTime
const touchable = (opt = {
longTapTime: 500
}) => {
return ComponentClass => {
return class TouchableComponent extends Taro.Component {
static defaultProps = {
hoverClass,
hoverStopPropergation,
hoverStartTime,
hoverStayTime
}
constructor (props, ctx) {
super(props, ctx)
this.state = this.getInitState(this.props)
}

touchStartTimer = null
touchEndTimer = null

state = {
isHover: false,
onTouchStart: null,
onTouchEnd: null
bindTouchStart: null,
bindTouchMove: null,
bindTouchEnd: null,
bindTouchCancel: null,
bindLongTap: null
}
timer = null

getInitState = ({ hoverClass, hoverStartTime, hoverStayTime, hoverStopPropergation, onTouchStart, onTouchEnd }) => {
if (hoverClass === 'none') return
return {
onTouchStart: this.getOnTouchStart({ hoverStartTime, hoverStopPropergation, onTouchStart }),
onTouchEnd: this.getOnTouchEnd({ hoverStayTime, hoverStopPropergation, onTouchEnd })
}
}
getOnTouchStart = ({ hoverStartTime, hoverStopPropergation, onTouchStart }) => {
return e => {
onTouchStart && onTouchStart(e)
hoverStopPropergation && e.stopPropergation()
this.touchStartTimer && clearTimeout(this.touchStartTimer)
this.touchEndTimer && clearTimeout(this.touchEndTimer)
this.touchStartTimer = setTimeout(() => {
this.setState({
isHover: true
})
}, hoverStartTime)
}
}
getOnTouchEnd = ({ hoverStayTime, hoverStopPropergation, onTouchEnd }) => {
return e => {
onTouchEnd && onTouchEnd(e)
hoverStopPropergation && e.stopPropergation()
this.touchStartTimer && clearTimeout(this.touchStartTimer)
this.touchEndTimer && clearTimeout(this.touchEndTimer)
this.touchEndTimer = setTimeout(() => {
this.setState({
isHover: false
})
}, hoverStayTime)
}
}
reset = () => {
this.setState({
isHover: false
})
}
componentWillMount () {
document.body.addEventListener('touchstart', this.reset)
}
componentWillReceiveProps (nProps, nCtx) {
super.componentWillReceiveProps && super.componentWillReceiveProps(nProps, nCtx)
if (
nProps.hoverClass !== this.props.hoverClass ||
nProps.hoverStopPropergation !== this.props.hoverStopPropergation ||
nProps.hoverStartTime !== this.props.hoverStartTime ||
nProps.hoverStayTime !== this.props.hoverStayTime
) {
const stateObj = this.getInitState(nProps)
this.setState(stateObj)
}
}
componentWillUnmount () {
document.body.removeEventListener('touchstart', this.reset)
onTouchStart () {
const { bindTouchStart, bindLongTap } = this.props
bindTouchStart && bindTouchStart()
setTimeout(() => {
bindLongTap && bindLongTap()
}, opt.longTapTime)
}
onTouchMove () {
const { bindTouchMove } = this.props
bindTouchMove && bindTouchMove()
}
onTouchEnd () {
this.timer && clearTimeout(this.timer)
const { bindTouchEnd } = this.props
bindTouchEnd && bindTouchEnd()
}
onTouchCancel () {
this.timer && clearTimeout(this.timer)
const { bindTouchCancel } = this.props
bindTouchCancel && bindTouchCancel()
}
render () {
const { isHover, onTouchStart, onTouchEnd } = this.state
const props = {
onTouchStart: this.onTouchStart,
onTouchMove: this.onTouchMove,
onTouchEnd: this.onTouchEnd,
onTouchCancel: this.onTouchCancel,
...omit(this.props, [
'hoverStopPropergation',
'hoverStartTime',
'hoverStayTime'
]),
isHover,
onTouchStart,
onTouchEnd
'bindTouchStart',
'bindTouchMove',
'bindTouchEnd',
'bindTouchCancel',
'bindLongTap'
])
}
return <ComponentClass {...props} />
}
Expand Down

0 comments on commit 09d1396

Please sign in to comment.