文章目录
概要
使用Canvas可以绘制图形,但是如果要实现图形的缩放和滑动效果,则需要我们自己通过拦截手势事件来实现了。
整体架构流程
实现思路:
1、通过给Canvas组件添加捏合手势来计算图形显示比例、通过添加拖拽手势来计算图形移动的距离。
2、触发Canvas重新绘制,绘制时通过上一步计算出来的显示比例和移动距离,来控制图形的绘制区域。
技术名词解释
- Canvas 画图,用来显示绘制的图形
技术细节
添加捏合手势和拖拽手势
kotlin
.gesture(
// 组合手势模式
GestureGroup(GestureMode.Parallel,
// 捏合手势
PinchGesture({ fingers: 2 })
.onActionStart((event: GestureEvent) => {
})
.onActionUpdate((event: GestureEvent) => {
// 计算缩放比例
if (Math.round(event.scale * 10) % 2 == 0) {
this.dataCursor.setScale(this.pinchValue * event.scale)
this.redrawTimes++
}
})
.onActionEnd(() => {
this.pinchValue = this.dataCursor.scale
}),
// 拖拽手势
PanGesture(new PanGestureOptions({ direction: this.chartGestureEvent.isLongPress ? PanDirection.All : PanDirection.Horizontal }))
.onActionStart((event: GestureEvent) => {
if (!event.fingerList[0] || event.fingerList.length > 1) return
// 记录按下时的坐标点
this.chartGestureEvent.downX = event.fingerList[0].globalX
this.chartGestureEvent.downTime = new Date().getTime()
this.redrawTimes++
})
.onActionUpdate((event: GestureEvent) => {
if (!event.fingerList[0] || event.fingerList.length > 1) return
// 计算移动距离
let moveX = event.fingerList[0].globalX
this.chartGestureEvent.moveY = event.fingerList[0].globalY
this.chartGestureEvent.moveX = moveX
// 手指往右滑
if (event.offsetX > 0) {
this.panDirection = PanDirection.Right
}
// 手指往左滑
else if (event.offsetX < 0) {
this.panDirection = PanDirection.Left
}
else {
this.panDirection = PanDirection.None
}
if (Math.abs(event.offsetX) > 20) {
let startIndex = Math.round(this.panValue - event.offsetX / 20)
this.dataCursor.setStartIndex(startIndex)
this.redrawTimes++
}
})
.onActionEnd(() => {
if (!this.chartGestureEvent || this.chartGestureEvent.isLongPress) return
this.panValue = this.dataCursor.startIndex
// 判断是否为快速滑动
let exeDuration = new Date().getTime() - this.chartGestureEvent.downTime
let speed = Math.abs((this.chartGestureEvent.moveX - this.chartGestureEvent.downX) / exeDuration)
if (speed < 0.5) return
this.chartGestureEvent.downX = this.chartGestureEvent.moveX
this.chartGestureEvent.downY = this.chartGestureEvent.moveY
this.chartGestureEvent.downTime = new Date().getTime()
// 实现惯性滑动效果
this.animationUtil.interceptor(Math.round(160 * speed), (count) => {
let offsetCount = Math.round(1 / this.dataCursor.scale * count)
if (offsetCount > 20) {
offsetCount = 20
}
if (this.panDirection == PanDirection.Right) {
let startIndex = this.dataCursor.startIndex - offsetCount
if (startIndex < 0) startIndex = 0
this.dataCursor.setStartIndex(startIndex)
} else if (this.panDirection == PanDirection.Left) {
let startIndex = this.dataCursor.startIndex + offsetCount
if (startIndex >= this.dataCursor.totalCount) startIndex = this.dataCursor.totalCount - offsetCount
this.dataCursor.setStartIndex(startIndex)
}
this.panValue = this.dataCursor.startIndex
this.redrawTimes++
})
})
))
为了实现惯性滑动效果,我们将滑动距离拆分成多段,并通过setTimeout函数在滑动过程中不断重新绘制,来实现惯性滑动效果