網站首頁 編程語言 正文
前言
上一篇我們通過Listener
獲取觸控點的位置作為貝塞爾曲線的控制點,實現曲線的交互式繪制。不過,上一篇有個缺陷,控制點繪制完成后只能撤銷,沒法修改,如果要調整繪制的圖形的話會非常麻煩,這一篇我們來實現控制點的拖拽式移動,動態調整位置來調整繪制的圖形。
實現邏輯
上一篇的主要代碼我們不做更改,主要是需要實現控制點的拖拽式移動,移動過程中動態繪制新的曲線。不過由于繪制過程中不能同時移動點,因此需要有個完成繪制的控制,完成繪制后才支持拖拽控制點。拖拽控制點實現這里有兩個主要邏輯:
- 控制點的命中判斷:即拖拽開始時判斷哪個控制點被命中,需要移動。
- 監聽觸控位置的移動過程:移動過程中動態繪制新的圖形,以便直接看到對應的效果。
控制點的命中判斷在完成繪制后,首先需要監聽觸控按下事件,看看觸控點是否覆蓋了某個控制點的觸控響應范圍,同時對于距離較近的點,可能會同時命中多個點的觸控響應范圍,這個時候需要取距離最近的那個點。對于觸控范圍,我們定義為每個觸控點的周邊10個像素點。命中觸控點的實現代碼如下:
int checkPointToMove(Offset pressedPoint) { // 控制點非空才查找 if (points.isNotEmpty) { var pointsToCheck = <Offset>[]; final maxDistance = 10.0; // 查找觸控響應范圍內的控制點 for (Offset p in points) { if ((p.dx - pressedPoint.dx).abs() < maxDistance && (p.dy - pressedPoint.dy).abs() < maxDistance) { pointsToCheck.add(p); } } // 未找到 if (pointsToCheck.length == 0) { return -1; } else if (pointsToCheck.length == 1) { // 只有一個點,直接返回 return points.indexOf(pointsToCheck[0]); } else { // 有多個點命中,找到距離最近的點返回 Offset point = pointsToCheck[0]; var distance = distanceBetween(pointsToCheck[0], pressedPoint); for (int i = 1; i < pointsToCheck.length; i++) { var newDistance = distanceBetween(pointsToCheck[i], pressedPoint); if (newDistance < distance) { point = pointsToCheck[i]; distance = newDistance; } } return points.indexOf(point); } } return -1; }
移動過程的處理就比較簡單了,我們已經找到了命中的控制點,那就在觸控位置移動監聽響應方法onPointerMove
中更新控制點位置,并重新繪制即可,代碼如下,其中indexOfPointToMove
是一個狀態變量,即找到的控制點下標:
onPointerMove: ((event) { if (indexOfPointToMove != -1) { points[indexOfPointToMove] = event.localPosition; setState(() {}); } }),
應用
邏輯完成了,我們就來做一個繪制應用吧。考慮端午節快到了,我們嘗試來繪制一個粽子的線條畫看看。下面是調整前后的對比效果以及調整過程的動圖,可以看到,調整后的還是更像粽子一些。
總結
本篇介紹了如何通過拖拽調整貝塞爾曲線繪制的控制點來調整圖形的繪制,實際上很多繪圖都可能用到拖拽式的控制點位的調整,比如電子圍欄的設置。實際上主要的代碼是判斷觸控位置命中了具體哪個控制點。本篇代碼已經上傳至:繪圖相關代碼。
原文鏈接:https://juejin.cn/post/7102778749170483213
相關推薦
- 2022-10-07 C語言一個函數如何實現好幾個return返回值_C 語言
- 2022-04-20 Python?設計模式行為型解釋器模式_python
- 2022-03-30 .NET?Core使用EF生成數據庫出錯的解決方法_實用技巧
- 2022-12-21 C++?STL容器與函數謂詞示例分析講解_C 語言
- 2023-07-03 CSS 中有五種常見的定位方式--詳解
- 2022-11-23 Python?hashlib模塊與subprocess模塊使用詳細介紹_python
- 2024-03-18 sql篇-輸入數據提示[HY000][1366] Incorrect string value: ‘
- 2022-04-28 C#委托用法詳解_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支