HarmonyOS 使用画布 (Canvas)绘制自定义时间轴,放缩重绘闪烁跳动,导致放缩时间轴功能难以使用
自定义绘制时间轴,要求可以自由放缩和上下拖动,目前采用的方案是:使用画布Canvas绘制自定义时间轴,通过添加拖动手势实现时间轴的上下拖动,通过添加捏合手势实现时间轴高度的放缩,监听状态变量放缩比例实时重新绘制时间轴刻度线,重绘时间轴和刻度线的过程跳动频繁,导致时间轴放缩功能无法正常使用。
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.backgroundColor($r('app.color.uni_color_f7f7f7'))
.onReady(() => {
this.drawTimeline();
})
.width(LayoutConstant.MATCH_PARENT)
.height(this.timeLineHeight * this.scaleValue)// 在组件上绑定缩放比例,可以通过修改缩放比例来实现组件的缩小或者放大
.translate({ x: 0, y: this.offsetY, z: 0 })// 以组件左上角为坐标原点进行移动
.priorityGesture(
GestureGroup(GestureMode.Exclusive,
PanGesture(this.panOption)
.onActionStart((event: GestureEvent) => {
console.info('Pan start')
this.onScrolling?.(true)
})
.onActionUpdate((event: GestureEvent) => {
this.isScrollPanGestureActioning = true;
if (event) {
let tempOffsetY = this.positionY + event.offsetY;
let oneSecondHeight: number =
(this.timeLineHeight * this.scaleValue - this.blankHeight) / (24 * 3600); //每秒的高度
let maxOffsetY = oneSecondHeight * 12 * 3600;
let minOffsetY = -(oneSecondHeight * 12 * 3600);
if (tempOffsetY > maxOffsetY) {
this.offsetX = this.positionX + event.offsetX
this.offsetY = maxOffsetY
} else if (tempOffsetY < minOffsetY) {
this.offsetX = this.positionX + event.offsetX
this.offsetY = minOffsetY
} else {
this.offsetX = this.positionX + event.offsetX
this.offsetY = tempOffsetY
}
this.calculateCurrentBaseLineTime();
}
})
.onActionEnd(() => {
this.isScrollPanGestureActioning = false;
this.positionX = this.offsetX
this.positionY = this.offsetY
console.info('Pan end')
if (this.onSelectTimeSecond != null) {
this.onSelectTimeSecond(this.currentSecond);
}
// 延迟 300 ms回调
setTimeout(() => {
this.onScrolling?.(false)
}, 300)
}),
// 在组件上绑定三指触发的捏合手势
PinchGesture({ fingers: 2, distance: 2 })
.onActionStart((event: GestureEvent | undefined) => {
console.info('Pinch start');
hjqlog.debug2(`Pinch start:${this.scaleValue}`)
this.onScrolling?.(true)
})// 当捏合手势触发时,可以通过回调函数获取缩放比例,从而修改组件的缩放比例
.onActionUpdate((event: GestureEvent | undefined) => {
console.info('Pinch update');
if (event) {
let temp = this.pinchValue * event.scale;
if (temp > MAX_SCALE || temp < MIN_SCALE) {
if (temp < MIN_SCALE) {
this.scaleValue = MIN_SCALE;
} else if (temp > MAX_SCALE) {
this.scaleValue = MAX_SCALE;
}
this.pinchX = event.pinchCenterX;
this.pinchY = event.pinchCenterY;
} else {
this.scaleValue = this.pinchValue * event.scale;
this.pinchX = event.pinchCenterX;
this.pinchY = event.pinchCenterY;
}
hjqlog.debug2(`Pinch update:${this.scaleValue},event.scale(${event.scale})`)
}
})
.onActionEnd(() => {
this.pinchValue = this.scaleValue;
hjqlog.debug2(`Pinch end:${this.scaleValue}`)
console.info('Pinch end');
let currentSelectTime = this.calculateCurrentBaseLineTime();
// 延迟 300 ms回调
setTimeout(() => {
this.onScrolling?.(false)
}, 300)
})
)
)
}
.width(this.timeLineWidth)
.height(this.timeLineHeight * this.scaleValue)
.zIndex(0)
// 绘制时间轴和时间段矩形
private drawTimeline(): void {
this.offCanvas.height = this.timeLineHeight * this.scaleValue;
let offContext = this.offCanvas.getContext("2d", this.settings)
offContext.clearRect(0, 0, this.offCanvas.width, this.offCanvas.height);
this.hoursPerPixel = (this.offCanvas.height - this.blankHeight) / this.totalSeconds; // 24小时对应canvas宽度
// 绘制时间轴
offContext.beginPath();
offContext.moveTo(this.offCanvas.width, this.offCanvas.height);
offContext.lineTo(this.offCanvas.width, 0);
offContext.lineWidth = 1;
offContext.strokeStyle = '#000000';
offContext.stroke();
// 绘制刻度
for (let second = 0; second <= this.totalSeconds; second++) {
const y = this.offCanvas.height - second * this.hoursPerPixel - this.blankHeight / 2;
//根据不同放缩比例绘制时间轴刻度(业务代码比较长,没有放上)
}
// 将离屏绘制的内容画到canvas组件上
let image = this.offCanvas.transferToImageBitmap();
this.context.transferFromImageBitmap(image);
}
HarmonyOS
赞
收藏 0
回答 1
待解决
相关问题
#鸿蒙通关秘籍#如何实现HarmonyOS NEXT中的时间轴效果?
103浏览 • 1回复 待解决
#鸿蒙通关秘籍# 如何在HarmonyOS中设计一个带有时间轴显示的下拉刷新效果?
60浏览 • 0回复 待解决
解决Canvas画布缩放时闪烁
1455浏览 • 1回复 待解决
Image如何在X轴和Y轴两个方向同事绘制重复样式的图片?
356浏览 • 1回复 待解决
HarmonyOS使用Canvas自定义绘制内容后,如何根据onTouch事件动态更新绘制的内容?
400浏览 • 1回复 待解决
HarmonyOS 自定义时间控件和日期控件
325浏览 • 1回复 待解决
如何使用canvas绘制图形?环境是API6,java编写自定义组件
2439浏览 • 1回复 待解决
鸿蒙自定义组件,如何在Ondraw()方法中使用canvas绘制一张资源图片?
6037浏览 • 1回复 待解决
HarmonyOS 如何实现Y轴旋转?
261浏览 • 1回复 待解决
HarmonyOS 使用自定义字体
236浏览 • 1回复 待解决
#鸿蒙通关秘籍#通过自定义组件冻结功能如何优化鸿蒙应用的页面渲染时间?
116浏览 • 1回复 待解决
#鸿蒙通关秘籍# 在HarmonyOS中绘制模拟时钟时,如何处理画布旋转,以避免绘制状态混乱和时间错乱问题?
67浏览 • 0回复 待解决
如何使用canvas绘制圆角矩形
540浏览 • 1回复 待解决
HarmonyOS如何实现一个多时间段的自定义控件界面?
266浏览 • 1回复 待解决
HarmonyOS 自定义接口如何使用?
146浏览 • 1回复 待解决
HarmonyOS 有没有自定义视图绘制的案例, 绘制渐变曲线?
244浏览 • 1回复 待解决
#鸿蒙通关秘籍#如何在绘制组件中使用自定义样式进行修改?
119浏览 • 1回复 待解决
#鸿蒙学习大百科#如何自定义时间显示哪些信息?
248浏览 • 1回复 待解决
HarmonyOS 自定义弹窗CustomDialog会导致键盘收起
414浏览 • 1回复 待解决
HarmonyOS 有没有类似Canvas的自定义view
274浏览 • 1回复 待解决
画布绘制文字,垂直居中
353浏览 • 1回复 待解决
如何使用EGL绘制自定义动画?请提供一个简单示例
1979浏览 • 1回复 待解决
#鸿蒙通关秘籍#如何使用CanvasRenderingContext2D对象绘制自定义矩形?
101浏览 • 1回复 待解决
自定义弹窗使用相关问题
922浏览 • 1回复 待解决
自定义弹窗如何嵌套使用
1676浏览 • 1回复 待解决
Demo参考: