Flutter中手势触控点在画布上的使用分析

649 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 7 天,点击查看活动详情

前言

Flutter自定义组件绘制中,尤其一些跟手势有着交互的组件,本篇文章将带你详解在画布上如何获取手势触控点坐标的一些常规操作。

手势在移动设备中的点坐标

首先我们要了解,当我们点击屏幕上任一一个点,系统会返回一个坐标,那么这个坐标就是相对于屏幕左上角而来的,也就是说屏幕左上角即为系统坐标轴原点。并且我们在屏幕上绘制的组件的相对坐标都是基于组件的左上角,并不是组件的中心点。也就是一个组件距离原点的位置。
image.png image.png
当然这是系统默认的,那我们在自定义绘制当中可不可以把原点放到屏幕中心来操作,这样对于人看起来来说可能更加符合我们上学的坐标轴,这里只需将画布向右、下平移操作,即可将画布原点设置为屏幕中心,size即是我们画布的大小。

// 平移画布 中心点
canvas.translate(size.width / 2, size.height / 2);

注意:,这里只是临时将画布平移方便我们绘制操作,并不是将系统真正的原点给平移了,真正的原点还是屏幕左上角。

有了以上概念,接下来我们就可以在屏幕上绘制我们所需要的组件了。

绘制正方形区域

比如我们在屏幕上画一个边长为100的正方形,当手指在正方形内点击移动返回以正方形左上角坐标为原点的新坐标该怎么做呢? 我们知道手指触控屏幕的坐标是相对于屏幕左上角的, 如下代码,手势类在点击、移动、取消等事件时都会返回localPositionglobalPosition两个坐标点,从字面上理解为本地坐标和全局坐标,实际上这两个坐标的区别就是渲染区域的区别就是相对原点的区别,
localPosition: 当前组件范围左上角为原点。
globalPosition:始终为设备屏幕左上角为原点。

我们其实最关心的的还是localPosition这个属性。当前组件的的坐标系。
那我们获取上方正方形区域的的坐标就只需返回localPosition即可。

GestureDetector(
  child: Container(
  width: 100,
  height: 100,
),
  // 按下
  onPanDown:(DragDownDetails details) {
  final offset = details.localPosition;
  final offset2 = details.globalPosition;
  print("down本地 x轴${offset.dx} y轴${offset.dy}");
  print("down全局 x轴${offset2.dx} y轴${offset2.dy}");
},
));

上面默认是以左上角的,那如果我们想把中心点设置为正方形的中心该怎么做呢,坐标点Offset直接添加偏移量即可,比如在以下正方形区域内,将左上角原点移到正方形中心,只需要将获取的当前坐标点各减去宽高一半不就行了么。这样就能得到以正方形为原点的坐标点。
image.png
Flutter平移坐标点到原点:

// 平移坐标点
offset.translate(-size.width / 2, -size.height / 2);
/// 源码
Offset translate(double translateX, double translateY) => Offset(dx + translateX, dy + translateY);

画布区域

在绘制过程中我们如何确定绘制区域,其实很简单,只需设置CustomPaintsize属性即可,只设置size属性的话,会发现我们的绘制区域超出了画布范围也可以绘制,如果不想超出区域显示,只需将画布裁剪即可。这样我们的绘制区域就会强制控制在我们的设置的大小内。

/// 裁剪画布为Size大小
canvas.clipRect(Offset.zero & size);
///源码
Rect operator &(Size other) => Rect.fromLTWH(dx, dy, other.width, other.height);
CustomPaint(
/// 设置画布大小
  size: Size(
   100,
   100,
  ),
  painter: PaperPainter(),
),

小结

有了这些坐标点,其实我们就可以做很多事情,比如手机中的手势识别密码、手游中的操纵杆都是非常典型的手势识别自定义组件,实战项目中还需要通过坐标点进行一些数学计算,本篇主要分析如何在画布上拿到我们想要的坐标点,希望对你有所帮助 ~