Prechádzať zdrojové kódy

********************************** *********************
添加矩阵

zhangweixin 3 rokov pred
rodič
commit
ab8276c8ad

+ 50 - 13
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyItem.kt

@@ -24,12 +24,13 @@
 package com.sybotan.android.graphy
 
 import android.graphics.Canvas
+import android.graphics.Matrix
 import android.graphics.PointF
 import android.graphics.RectF
 import android.util.Log
-import android.view.MotionEvent
 import com.sybotan.android.graphy.enums.SGraphyItemFlag
 import com.sybotan.android.graphy.listeners.SGraphyItemPosListener
+import com.sybotan.android.graphy.utils.MatrixTools
 import org.jetbrains.anko.doAsync
 import java.util.*
 
@@ -57,10 +58,20 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
          * @param   e       事件参数
          * @return  子对象MotionEvent
          */
-        fun toChildMotionEvent(child: SGraphyItem, e: MotionEvent): MotionEvent {
-            val se = MotionEvent.obtain(e)
-            se.setLocation((e.x - child.pos.x) / child.scale.x, (e.y - child.pos.y) / child.scale.y)
-            return se
+        fun toChildMotionEvent(child: SGraphyItem, e: SMotionEvent): SMotionEvent {
+            val ce = SMotionEvent(e)
+            ce.matrix.postTranslate(child.pos.x, child.pos.y);
+            ce.matrix.postScale(child.scale.x, child.scale.y);
+            ce.matrix.postRotate(child.rotate,0f, 0f);
+            // 不跟随缩放
+            if (!child.isTransform) {
+                ce.matrix.postScale(child._inverseScale, child._inverseScale);
+            }
+//            se.setLocation((e.x - child.pos.x) / child.scale.x, (e.y - child.pos.y) / child.scale.y)
+            val matrixTransform = MatrixTools.matrixTransform(ce.matrix, e.x, e.y)
+            ce.x = matrixTransform.x
+            ce.y = matrixTransform.y
+            return ce
         } // Function toSceneMotionEvent()
     } // companion object
 
@@ -124,7 +135,12 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
         }
     /** 缩放比例 */
     var scale = PointF(1f, 1f)
-
+    /** 旋转 */
+    var rotate = 0.0f
+    /** 是否进行变形 */
+   var isTransform = true;
+    /** 放缩反比例 */
+    var _inverseScale = 1f;
     /** item标志 */
     var flags: EnumSet<SGraphyItemFlag> = EnumSet.noneOf(SGraphyItemFlag::class.java)
 
@@ -362,7 +378,6 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
             if (!item.isVisible) {      // 如果对象不可见
                 continue
             }
-
             try {
                 // 保存画布状态
                 canvas.save()
@@ -403,7 +418,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   e       按下手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onDown(e: MotionEvent): Boolean {
+    open fun onDown(e: SMotionEvent): Boolean {
         for (item in children) {
             if (!item.isVisible) {      // 如果对象不可见
                 continue
@@ -429,7 +444,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   e       释放手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onSingleTapUp(e: MotionEvent): Boolean {
+    open fun onSingleTapUp(e: SMotionEvent): Boolean {
         Log.d(TAG, "onSingleTapUp: releaseItem")
         releaseItem()
 
@@ -453,7 +468,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   e       手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onShowPress(e: MotionEvent): Boolean {
+    open fun onShowPress(e: SMotionEvent): Boolean {
         Log.d(TAG, "onShowPress: releaseItem")
         for (item in children) {
             if (!item.isVisible) {      // 如果对象不可见
@@ -475,7 +490,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   e       长按手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onLongPress(e: MotionEvent): Boolean {
+    open fun onLongPress(e: SMotionEvent): Boolean {
         Log.d(TAG, "onLongPress: releaseItem")
         releaseItem()
 
@@ -502,7 +517,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   distanceY   Y轴上的移动距离,单位:像素
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
+    open fun onScroll(e1: SMotionEvent, e2: SMotionEvent, distanceX: Float, distanceY: Float): Boolean {
         if (flags.contains(SGraphyItemFlag.ItemIsMovable) && currentMoveItem === this) {
             moveTo(pos.x - distanceX * scale.x, pos.y - distanceY * scale.y)
             return true
@@ -539,7 +554,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   velocityY   Y轴上的移动速度,像素/秒
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-     open fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
+     open fun onFling(e1: SMotionEvent, e2: SMotionEvent, velocityX: Float, velocityY: Float): Boolean {
         Log.d(TAG, "onFling: releaseItem")
         releaseItem()
 
@@ -581,4 +596,26 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
         scene!!.grabItem = null
         return
     } // Function grabItem
+
+    /**
+     * 场景对象到 item 对象的转换矩阵
+     *
+     * @return 转换矩阵
+     */
+    fun scene2itemMattrix() : Matrix{
+        val m = Matrix()
+        val list = this.itemPath()
+        for ( item in list) {
+            m.postTranslate(item.pos.x, item.pos.y);
+            m.postScale(item.scale.x, item.scale.y);
+            m.postRotate(item.rotate)
+            // 如果不进行变形处理,则取消 painter 的变型操作
+            if (!item.isTransform){
+                m.postScale(item._inverseScale, item._inverseScale);
+            }
+        }
+        return m
+    }
+
+
 } // Class SGraphyItem

+ 21 - 12
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyScene.kt

@@ -25,13 +25,13 @@ package com.sybotan.android.graphy
 
 import android.graphics.*
 import android.util.Log
-import android.view.MotionEvent
 import com.sybotan.android.base.extensions.adjusted
 import com.sybotan.android.graphy.data.SLineF
 import com.sybotan.android.graphy.enums.SGraphyItemFlag
 import com.sybotan.android.graphy.items.SGraphyImageItem
 import com.sybotan.android.graphy.items.SGraphyLineItem
 import com.sybotan.android.graphy.items.SGraphyRectItem
+import com.sybotan.android.graphy.utils.MatrixTools
 
 /**
  * SGraphy图形引擎场景类
@@ -208,7 +208,7 @@ open class SGraphyScene {
      * @param   e       按下手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onDown(e: MotionEvent): Boolean {
+    open fun onDown(e: SMotionEvent): Boolean {
         if (null != grabItem) {     // 如果当前锁定item不为空
             return true
         }
@@ -222,7 +222,7 @@ open class SGraphyScene {
      * @param   e       释放手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onSingleTapUp(e: MotionEvent): Boolean {
+    open fun onSingleTapUp(e: SMotionEvent): Boolean {
         if (null != grabItem) {     // 如果当前锁定item不为空
             val ie = toGrabItemMotionEvent(grabItem!!, e)
             return grabItem!!.onSingleTapUp(ie)
@@ -236,7 +236,7 @@ open class SGraphyScene {
      * @param   e       手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    fun onShowPress(e: MotionEvent): Boolean {
+    fun onShowPress(e: SMotionEvent): Boolean {
         if (null != grabItem) {     // 如果当前锁定item不为空
             val ie = toGrabItemMotionEvent(grabItem!!, e)
             grabItem!!.onShowPress(ie)
@@ -252,7 +252,7 @@ open class SGraphyScene {
      * @param   e       长按手势事件。
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onLongPress(e: MotionEvent): Boolean {
+    open fun onLongPress(e: SMotionEvent): Boolean {
         if (null != grabItem) {     // 如果当前锁定item不为空
             val ie = toGrabItemMotionEvent(grabItem!!, e)
             return grabItem!!.onLongPress(ie)
@@ -269,7 +269,7 @@ open class SGraphyScene {
      * @param   distanceY   Y轴上的移动距离,单位:像素
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
+    open fun onScroll(e1: SMotionEvent, e2: SMotionEvent, distanceX: Float, distanceY: Float): Boolean {
         if (null != grabItem) {     // 如果当前锁定item不为空
             val ie1 = toGrabItemMotionEvent(grabItem!!, e1)
             val ie2 = toGrabItemMotionEvent(grabItem!!, e2)
@@ -289,7 +289,7 @@ open class SGraphyScene {
      * @param   velocityY   Y轴上的移动速度,像素/秒
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    open fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
+    open fun onFling(e1: SMotionEvent, e2: SMotionEvent, velocityX: Float, velocityY: Float): Boolean {
         if (null != grabItem) {     // 如果当前锁定item不为空
             val ie1 = toGrabItemMotionEvent(grabItem!!, e1)
             val ie2 = toGrabItemMotionEvent(grabItem!!, e2)
@@ -307,10 +307,20 @@ open class SGraphyScene {
      * @param   e           场景事件
      * @return  item事件
      */
-    private fun toGrabItemMotionEvent(item: SGraphyItem, e: MotionEvent): MotionEvent {
-        val se = MotionEvent.obtain(e)
-        val p = item.mapFromScene(e.x, e.y)
-        se.setLocation(p.x, p.y)
+    private fun toGrabItemMotionEvent(item: SGraphyItem, e: SMotionEvent): SMotionEvent {
+        val se = SMotionEvent(e)
+        se.matrix = Matrix()
+        if (this.view != null ){
+            se.matrix.postTranslate(this.view!!.pos.x, this.view!!.pos.y);
+            se.matrix.postScale(this.view!!.scale, this.view!!.scale)
+            se.matrix.postRotate(this.view!!.rotate)
+        }
+        se.matrix.postConcat(item.scene2itemMattrix())
+        val matrixTransform = MatrixTools.matrixTransform(se.matrix, se.x, se.y)
+        se.x = matrixTransform.x
+        se.y = matrixTransform.y
+//        val p = item.mapFromScene(e.x, e.y)
+//        se.setLocation(p.x, p.y)
         return se
     } // Function toItemMotionEvent()
 
@@ -329,7 +339,6 @@ open class SGraphyScene {
             p.x = p.x / child.scale.x
             p.y = p.y / child.scale.y
         }
-
         return p
     } // Function toGrabItemDistance()
 

+ 17 - 4
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyView.kt

@@ -32,6 +32,7 @@ import android.view.MotionEvent
 import com.sybotan.android.graphy.enums.SGraphyViewTouchState
 import com.sybotan.android.graphy.events.SGraphyViewMoveEvent
 import com.sybotan.android.graphy.events.SGraphyViewZoomEvent
+import com.sybotan.android.graphy.utils.MatrixTools
 import org.greenrobot.eventbus.EventBus
 import kotlin.math.max
 import kotlin.math.min
@@ -63,7 +64,8 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             // 保存场景
             field = value
         }
-
+    /** 旋转 */
+    var rotate = 0.0f
     /** 是否支持二指缩放操作 */
     var canZoom = true
     /** 缩放比例 */
@@ -539,9 +541,20 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
      * @param   e       MotionEvent
      * @return  子对象MotionEvent
      */
-    private fun toSceneMotionEvent(e: MotionEvent): MotionEvent {
-        val se = MotionEvent.obtain(e)
-        se.setLocation((e.x - pos.x) / scale, (e.y - pos.y) / scale)
+    private fun toSceneMotionEvent(e: MotionEvent): SMotionEvent {
+        val se = SMotionEvent(e)
+        se.matrix.postTranslate(pos.x,pos.y)
+        se.matrix.postScale(this.scale, this.scale);
+        se.matrix.postRotate(this.rotate)
+        val matrixMat = Matrix()
+        matrixMat.invert(se.matrix)
+        val matrixTransform = MatrixTools.matrixTransform(matrixMat, e.x, e.y)
+        se.x = matrixTransform.x
+        se.y = matrixTransform.y
+//        se.setLocation((e.x - pos.x) / scale, (e.y - pos.y) / scale)
         return se
     } // Function toSceneMotionEvent()
+
+
+
 } // Class SGraphyView

+ 9 - 7
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SMotionEvent.kt

@@ -8,22 +8,23 @@ import android.view.MotionEvent
 class SMotionEvent() {
 
     /** x 坐标 */
-    var y: Double = 0.0
+    var y  = 0.0f
     /** y 坐标 */
-    var x: Double = 0.0
+    var x = 0.0f
     /** 事件类型 */
-    var type: String? = null
+    var action: Int = 0
     /** 图坐标 X */
-    var viewX: Double? = 0.0
+    var viewX = 0.0f
     /** 图坐标 Y */
-    var viewY: Double? = 0.0
+    var viewY = 0.0f
     /** 矩阵 */
     var matrix = Matrix()
 
 
     constructor(e: MotionEvent){
-        this.viewX = e.x.toDouble()
-        this.viewY = e.y.toDouble()
+        this.viewX = e.x
+        this.viewY = e.y
+        this.action = e.action
     }
 
     constructor(e: SMotionEvent){
@@ -31,6 +32,7 @@ class SMotionEvent() {
         this.y = e.y
         this.viewX = e.viewX
         this.viewY = e.viewY
+        this.action = e.action
         matrix.set(e.matrix)
 
     }

+ 21 - 0
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/utils/MatrixTools.kt

@@ -0,0 +1,21 @@
+package com.sybotan.android.graphy.utils
+
+import android.graphics.Matrix
+import android.graphics.PointF
+
+object MatrixTools {
+
+    /**
+     *
+     */
+    fun matrixTransform(mat: Matrix,x : Float, y : Float ) : PointF {
+        val pointF = PointF()
+        val src = kotlin.floatArrayOf(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)
+        mat.getValues(src)
+        pointF.x = x * src[0] + y * src[1] + src[3];
+        pointF.y = x * src[3] + y * src[4] + src[5];
+        return pointF;
+    }
+
+
+}