前面都介绍过解码,布局等
现在介绍手势.桌面端
目录
手势
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.Transparent)
.pointerInput(Unit) {
awaitEachGesture {
var zooming = false
var dragging = false
// pan惯性
val panVelocityTracker = VelocityTracker()
var pan: Offset
var totalDrag = Offset.Zero
val down = awaitFirstDown(requireUnconsumed = false)
val wasFlingActive = flingJob?.isActive == true // 记录按下时是否有fling动画
try {
pan = Offset.Zero
totalDrag = Offset.Zero
panVelocityTracker.resetTracking()
flingJob?.cancel()
isFlingActive = false
do {
val event = awaitPointerEvent()
val pointerCount = event.changes.size
val zoomChange = event.calculateZoom()
val panChange = event.calculatePan()
val centroid = event.calculateCentroid()
// 采集pan速度
val uptime =
event.changes.maxByOrNull { it.uptimeMillis }?.uptimeMillis
?: 0L
pan += panChange
totalDrag += panChange
panVelocityTracker.addPosition(uptime, pan)
// 检测是否开始拖拽
if (totalDrag.getDistance() > 10f) {
dragging = true
}
if (pointerCount > 1) {
zooming = true
val newZoom = (zoomChange * vZoom).coerceIn(1f, 10f)
val zoomFactor = newZoom / vZoom
// 计算缩放中心点:手势中心相对于内容的位置
// centroid 是手势中心在视图中的位置
// 需要将其转换为相对于内容的位置
val contentCenterX = centroid.x - offset.x
val contentCenterY = centroid.y - offset.y
// 计算新的偏移量,保持内容中心点不变
val newOffsetX = centroid.x - contentCenterX * zoomFactor
val newOffsetY = centroid.y - contentCenterY * zoomFactor
vZoom = newZoom
offset = Offset(newOffsetX, newOffsetY)
// 边界检查
if (orientation == Vertical) {
val scaledWidth = viewSize.width * vZoom
// 在缩放过程中,需要根据当前缩放比例调整总高度
val scaleRatio = vZoom / pdfViewState.vZoom
val scaledHeight = pdfViewState.totalHeight * scaleRatio
val minX = minOf(0f, viewSize.width - scaledWidth)
val maxX = 0f
val minY =
if (scaledHeight > viewSize.height) viewSize.height - scaledHeight else 0f
val maxY = 0f
offset = Offset(
offset.x.coerceIn(minX, maxX),
offset.y.coerceIn(minY, maxY)
)
} else {
val scaledHeight = viewSize.height * vZoom
val scaleRatio = vZoom / pdfViewState.vZoom
val scaledWidth = pdfViewState.totalWidth * scaleRatio
val minY = minOf(0f, viewSize.height - scaledHeight)
val maxY = 0f
val minX =
if (scaledWidth > viewSize.width) viewSize.width - scaledWidth else 0f
val maxX = 0f
offset = Offset(
offset.x.coerceIn(minX, maxX),
offset.y.coerceIn(minY, maxY)
)
}
pdfViewState.updateOffset(offset)
event.changes.fastForEach { if (it.positionChanged()) it.consume() }
} else {
// 单指拖动
if (!zooming) {
offset += panChange
if (orientation == Vertical) {