欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android利用控制點(diǎn)的拖拽畫(huà)一個(gè)粽子

 更新時(shí)間:2022年05月30日 09:37:53   作者:島上碼農(nóng)  
端午節(jié)就要到了,本文我們將利用控制點(diǎn)的拖拽式移動(dòng),動(dòng)態(tài)調(diào)整位置來(lái)調(diào)整繪制一個(gè)簡(jiǎn)單的粽子圖形,感興趣的小伙伴可以跟隨小編一起動(dòng)手嘗試一下

前言

上一篇我們通過(guò)Listener獲取觸控點(diǎn)的位置作為貝塞爾曲線(xiàn)的控制點(diǎn),實(shí)現(xiàn)曲線(xiàn)的交互式繪制。不過(guò),上一篇有個(gè)缺陷,控制點(diǎn)繪制完成后只能撤銷(xiāo),沒(méi)法修改,如果要調(diào)整繪制的圖形的話(huà)會(huì)非常麻煩,這一篇我們來(lái)實(shí)現(xiàn)控制點(diǎn)的拖拽式移動(dòng),動(dòng)態(tài)調(diào)整位置來(lái)調(diào)整繪制的圖形。

實(shí)現(xiàn)邏輯

上一篇的主要代碼我們不做更改,主要是需要實(shí)現(xiàn)控制點(diǎn)的拖拽式移動(dòng),移動(dòng)過(guò)程中動(dòng)態(tài)繪制新的曲線(xiàn)。不過(guò)由于繪制過(guò)程中不能同時(shí)移動(dòng)點(diǎn),因此需要有個(gè)完成繪制的控制,完成繪制后才支持拖拽控制點(diǎn)。拖拽控制點(diǎn)實(shí)現(xiàn)這里有兩個(gè)主要邏輯:

  • 控制點(diǎn)的命中判斷:即拖拽開(kāi)始時(shí)判斷哪個(gè)控制點(diǎn)被命中,需要移動(dòng)。
  • 監(jiān)聽(tīng)觸控位置的移動(dòng)過(guò)程:移動(dòng)過(guò)程中動(dòng)態(tài)繪制新的圖形,以便直接看到對(duì)應(yīng)的效果。

控制點(diǎn)的命中判斷在完成繪制后,首先需要監(jiān)聽(tīng)觸控按下事件,看看觸控點(diǎn)是否覆蓋了某個(gè)控制點(diǎn)的觸控響應(yīng)范圍,同時(shí)對(duì)于距離較近的點(diǎn),可能會(huì)同時(shí)命中多個(gè)點(diǎn)的觸控響應(yīng)范圍,這個(gè)時(shí)候需要取距離最近的那個(gè)點(diǎn)。對(duì)于觸控范圍,我們定義為每個(gè)觸控點(diǎn)的周邊10個(gè)像素點(diǎn)。命中觸控點(diǎn)的實(shí)現(xiàn)代碼如下:

int checkPointToMove(Offset pressedPoint) {
    // 控制點(diǎn)非空才查找
    if (points.isNotEmpty) {
      var pointsToCheck = <Offset>[];
      final maxDistance = 10.0;
      // 查找觸控響應(yīng)范圍內(nèi)的控制點(diǎn)
      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) {
        // 只有一個(gè)點(diǎn),直接返回
        return points.indexOf(pointsToCheck[0]);
      } else {
        // 有多個(gè)點(diǎn)命中,找到距離最近的點(diǎn)返回
        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;
  }

移動(dòng)過(guò)程的處理就比較簡(jiǎn)單了,我們已經(jīng)找到了命中的控制點(diǎn),那就在觸控位置移動(dòng)監(jiān)聽(tīng)響應(yīng)方法onPointerMove中更新控制點(diǎn)位置,并重新繪制即可,代碼如下,其中indexOfPointToMove是一個(gè)狀態(tài)變量,即找到的控制點(diǎn)下標(biāo):

onPointerMove: ((event) {
  if (indexOfPointToMove != -1) {
    points[indexOfPointToMove] = event.localPosition;
    setState(() {});
  }
}),

應(yīng)用

邏輯完成了,我們就來(lái)做一個(gè)繪制應(yīng)用吧??紤]端午節(jié)快到了,我們嘗試來(lái)繪制一個(gè)粽子的線(xiàn)條畫(huà)看看。下面是調(diào)整前后的對(duì)比效果以及調(diào)整過(guò)程的動(dòng)圖,可以看到,調(diào)整后的還是更像粽子一些。

總結(jié)

本篇介紹了如何通過(guò)拖拽調(diào)整貝塞爾曲線(xiàn)繪制的控制點(diǎn)來(lái)調(diào)整圖形的繪制,實(shí)際上很多繪圖都可能用到拖拽式的控制點(diǎn)位的調(diào)整,比如電子圍欄的設(shè)置。實(shí)際上主要的代碼是判斷觸控位置命中了具體哪個(gè)控制點(diǎn)。本篇代碼已經(jīng)上傳至:繪圖相關(guān)代碼。

以上就是Android利用控制點(diǎn)的拖拽畫(huà)一個(gè)粽子的詳細(xì)內(nèi)容,更多關(guān)于Android粽子的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論