Android 如何沿着手指画一条平滑的线
http://marakana.com/tutorials/android/2d-graphics-example.html
我我正在使用下面这个例子。但当我在屏幕上移动手指太快时,线条就会变成单独的点。
我不确定是否可以加快绘图速度。或者我应该用直线连接最后两个点。这两个解决方案中的第二个似乎是一个不错的选择,除非当您快速移动手指时,您将看到很长的直线部分,然后是尖锐的曲线。
如果还有其他解决方案,很高兴听到它们。
感谢您提前提供的任何帮助。
http://marakana.com/tutorials/android/2d-graphics-example.html
I am using this example below. But when I move my fingers too fast across the screen the line turns to individual dots.
I am not sure whether I can speed up the drawing. Or I should connect the two last points with a straight line. The second of these two solutions seems like a good option, except when moving your finger very fast you will have long sections of a straight line then sharp curves.
If there are any other solutions it would be great to hear them.
Thanks for any help in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
正如您提到的,一个简单的解决方案就是简单地用直线连接这些点。以下是执行此操作的代码:
确保将绘画从填充更改为描边:
另一个选项是使用quadTo方法通过迭代连接点:
这仍然会产生一些尖锐的边缘。
如果您真的雄心勃勃,您可以开始计算三次样条,如下所示:
另外,我发现您需要更改以下内容以避免重复的运动事件:
并添加 dx 和 dx 。 dy 值传递给 Point 类:
这会产生平滑的线条,但有时必须使用循环连接点。
此外,对于长时间的绘图会话,这会变得计算量很大。
编辑
我整理了一个快速项目来演示这些不同的技术,包括 Square 建议的签名实现。享受:https://github.com/johncarl81/androiddraw
An easy solution, as you mentioned, is to simply connect the points with a straight line. Here's the code to do so:
make sure you change your paint from fill to stroke:
Another option is to connect the points with iterpolation using the quadTo method:
This still results in some sharp edges.
If you're really ambitious, you can start to calculate the cubic splines as follows:
Also, I found that you needed to change the following to avoid duplicate motion events:
and add the dx & dy values to the Point class:
This produces smooth lines, but sometimes has to connect the dots using a loop.
Also, for long drawing sessions, this becomes computationally intensive to calculate.
Edit
I threw together a quick project demonstrating these different techniques, including Square's suggessted signature implementation. Enjoy: https://github.com/johncarl81/androiddraw
这对你来说可能不再重要,但我花了很多功夫才解决它,我想分享,可能对其他人有用。
@johncarl 提供的解决方案教程非常适合绘图,但它们对我的目的提供了限制。如果您将手指从屏幕上移开并放回去,此解决方案将在上次单击和新单击之间画一条线,使整个绘图始终连接。所以我试图找到一个解决方案,最后我得到了它!(抱歉,如果听起来很明显,我是图形初学者)
我用手指绘制了android示例,并对其进行了一些修改以存储每个路径仅最后一个!希望它能帮助别人!
干杯。
This might be not important anymore for you but I struggled a lot to solve it and I want to share, might be useful to someone else.
The tutorial with the solution @johncarl offered are great to drawing but they offered a limitation for my purposes. If you take your finger out of the screen and put it back, this solution will draw a line between the last click and your new click, making the whole drawing connected always. So I was trying to find a solution for that, and finally I got it!( sorry if sounds obvious, I am a beginner with graphics)
I took the android sample for drawing with your finger and modified it a little to store every path instead of just the last one! Hope it helps someone!
Cheers.
我尝试了几种方法来渲染运动事件的累积点。
最后,我通过计算两点之间的中点并将列表中的点视为二次贝塞尔曲线的锚点(除了第一个和最后一个点,它们通过简单的线连接到下一个中点)得到了最好的结果)。
这给出了没有任何拐角的平滑曲线。绘制的路径不会接触列表中的实际点,而是经过每个中点。
I have experimented with several ways to render the accumulated points of the motion events.
In the end I had the best results by calculating the mid-points between two points and treating the points in the list as anchor points of quadratic Bezier curves (except the first and last point which are connected by simple lines to the next mid-point).
This gives a smooth curve without any corners. The drawn path will not touch the actual points in the list but go through every mid-point.
如果您想要简单一点:
在活动中只需:
结果:
要删除所有绘图,只需旋转屏幕即可。
If you want it simple:
In the activity just:
Result:
To erase all drawings just rotate the screen.
我有非常类似的问题。当您调用 onTouch 方法时,您还应该使用方法(在 onTouch(MotionEvent event) 内部)
和
类似的东西
I had very similar problem. When you're calling onTouch method, you should also use method (inside onTouch(MotionEvent event))
and
something like that
具有
ACTION_MOVE
的运动事件可以将单个对象内的多个运动样本批量处理在一起。使用 getX(int) 和 getY(int) 可以获得最新的指针坐标。使用 getHistoricalX(int, int) 和 getHistoricalY(int, int) 访问批次中较早的坐标。使用它们来构建路径使其更加平滑:这是来自 Square 的一个很好的教程:http://corner.squareup.com/2010/07/smooth-signatures.html
Motion events with
ACTION_MOVE
may batch together multiple movement samples within a single object. The most current pointer coordinates are available using getX(int) and getY(int). Earlier coordinates within the batch are accessed usinggetHistoricalX(int, int)
andgetHistoricalY(int, int)
. Using them for building path makes it much smoother :Here is a good tutorial on this from Square : http://corner.squareup.com/2010/07/smooth-signatures.html
我最近不得不对此进行一些修改,现在已经开发出我认为是最好的解决方案,因为它做了三件事:
canvas.drawPath()
方法位于 for 循环外部,因此不会多次调用它。这也有效,只是不太好
它可以让你很好地绘制线条,唯一的问题是如果你使线条变粗,这会使绘制的线条看起来有点奇怪,而且实际上,我还是建议使用第一个。
I had to make some modifications to this recently, and have now developed what I believe to be the best solution here because it does three things:
canvas.drawPath()
method is outside the for loop, so it is not called multiple times.This also works, just not quite as well
It lets you draw lines reasonably well, the only problem is if you make the line thicker, which makes the lines drawn look a little odd, and really, I would recommend using the first one anyways.
您的
MotionEvent
中的可用信息可能比您意识到的多得多,可以在中间提供一些数据。您链接中的示例忽略了事件中包含的历史接触点。请参阅
MotionEvent
文档顶部附近的“批处理”部分:http://developer.android.com/reference/android/view/MotionEvent.html 除此之外,用线连接点可能不是一个坏主意。You may have a lot more information available in your
MotionEvent
than you realize that can provide some data inbetween.The example in your link ignores the historical touch points included within the event. See the 'Batching' section near the top of
MotionEvent
's documentation: http://developer.android.com/reference/android/view/MotionEvent.html Beyond that connecting the points with lines may not be a bad idea.这是一个简化的解决方案,可以沿着手指画一条线并且始终是直的:
https://stackoverflow.com/a/68076519/ 15463816
Here is a simplified solution that draws a line that follows your finger and is always straight:
https://stackoverflow.com/a/68076519/15463816
我遇到了这个问题,我画的是点而不是线。您应该首先创建一条路径来保持阵地。仅在第一次触摸事件时调用 path.moveto 。然后在画布上绘制路径,然后在完成后重置或倒带路径(path.reset)...
I had this issue, i was drawing a point instead of a line. You should create a path first to hold your line. call path.moveto on your first touch event only. Then on your canvas draw the path and then reset or rewind the path after your done (path.reset)...
这是一个平滑 Path 绘制的点的简单方法。行至
Here is a simple method for smoothing points drawn with Path.lineTo