canvas 拖动中的奇怪行为

Strange behaviour in canvas dragging

我正在构建一个应用程序,它将在 canvas 上合并图像拖动(位图)。我想实施它以使其运行良好,任何人都可以帮助我吗? 这是代码:

    public boolean onTouchEvent(MotionEvent event) {
    mScaleDetector.onTouchEvent(event);

    final int action = event.getAction();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN & MotionEvent.ACTION_MASK: {
            final float xScale = event.getX();
            final float yScale = event.getY();

            mLastTouchX = xScale;
            mLastTouchY = yScale;
            mActivePointerId = event.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            final int pointerIndex = event.findPointerIndex(mActivePointerId);
            final float xScale = event.getX(pointerIndex);
            final float yScale = event.getY(pointerIndex);
            if (!mScaleDetector.isInProgress()) {
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;
                mPosX += dx;
                mPosY += dy;

                invalidate();
            }
            mLastTouchX = x;
            mLastTouchY = y;
            if (event.getX() < overlay.getHeight()) {
                x = (int) event.getX();
            }
            if (event.getY() < overlay.getWidth()) {
                y = (int) event.getY();
            }
            invalidate();


            break;
        }
        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {
            final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = event.getPointerId(pointerIndex);
            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = event.getX(newPointerIndex);
                mLastTouchY = event.getY(newPointerIndex);
                mActivePointerId = event.getPointerId(newPointerIndex);
            }
            break;
        }
    }

    return true;
}

void init(Context context) {
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    serverResult = Bitmap.createBitmap(mask.getWidth(),mask.getHeight(), Bitmap.Config.ARGB_8888);
    result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
    width = mask.getWidth();
    height = mask.getHeight();
    int overlayHeight = overlay.getHeight();
    int overlayWidth = overlay.getWidth();
    int imgHeight = originalImg.getHeight();
    int imgWidth = originalImg.getWidth();

    int heightFactor = imgHeight / overlayHeight;
    int widthFactor = imgWidth / overlayWidth;
    if (overlayHeight > imgHeight) {
        heightFactor = overlayHeight / imgHeight;
    }
    if (overlayWidth > imgWidth) {
        widthFactor = overlayWidth / imgWidth;
    }
    int newWidth;
    int newHeight;
    if (widthFactor != 0) {
        newWidth = imgWidth / widthFactor;
    } else {
        newWidth = imgWidth / heightFactor;
    }
    if (heightFactor != 0) {
        newHeight = imgHeight / widthFactor;
    } else {
        newHeight = imgHeight / heightFactor;
    }


    config = Bitmap.Config.ARGB_8888;
    DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    scaledImg = Bitmap.createScaledBitmap(originalImg, newWidth, newHeight, false);
    scaledImgFilterd = Bitmap.createScaledBitmap(originalImg, newWidth, newHeight, false);
    tempCanvas = new Canvas(result);
    imageCanvas = new Canvas(result);
    image = new GPUImage(context);




}

@Override
public void onDraw(Canvas canvas) {

    if (FILTER_APPLIED == 100) {
    if (filter != null) {
        image.setImage(scaledImg);
        image.setFilter(filter);
        scaledImgFilterd = image.getBitmapWithFilterApplied();
        FILTER_APPLIED = 0;
    }
    }

    paint.setXfermode(DST_IN);
    if(color == 0) {
        imageCanvas.drawColor(Color.WHITE);
    } else {
        imageCanvas.drawColor(color);

    }
    imageCanvas.scale(mScaleFactor, mScaleFactor);
    imageCanvas.drawBitmap(scaledImgFilterd, mLastTouchX, mLastTouchY, null);
    tempCanvas.drawBitmap(mask, 0, 0, paint);
    paint.setXfermode(null);
    canvas.drawBitmap(result, 0, 0, null);
    canvas.drawBitmap(overlay, 0, 0, null);

}

public void setColor(int color) {
    this.color = color;
    invalidate();
}

public void setFilter(GPUImageFilter filter) {
    this.filter = filter;
    FILTER_APPLIED = 100;
    invalidate();
}


private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();

        // Don't let the object get too small or too large.
        mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));

        invalidate();
        return true;
    }
}

按左上角拖动时有点卡顿,请问有人能帮帮我吗?

我不明白为什么它会很慢(说实话,代码太多了)但下面是对左上角拖动的解释

为了抵消左上角的拖动,您需要添加一些偏移变量,具体取决于您在图像上单击(触摸)的位置。

假设您触摸了 (touchX,touchY),您需要检查距离图像的左上角有多远。

  1. 您首先需要声明两个新变量,例如touchOffsetXtouchOffsetY
  2. 然后在触摸屏幕时定义新变量。

    touchOffsetX = touchX - image.x;

    touchOffsetY = touchY - image.y;

  3. 现在当你移动图像时,你设置它的 x 和 y 坐标是根据下面的设置

    image.x = touchX - touchOffsetX;

    image.y = touchY - touchOffsetX;

您当然需要更改代码中的变量名称。

下面是 HTML5 canvas 中的一个工作示例,以进一步解释这个想法。

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
c.width = 300;
c.height = 200;

var myRectangle = {
    x: 50,
    y: 130,
    w: 100,
    h: 50,
    drag: false
}

var mouseX = 0;
var mouseY = 0;
var mouseOffset = {x: 0, y:0}; // How far from the rectangle corner are we clicking?
var background = "#0099CC"; 

c.addEventListener("mousemove",mouseMove,false);
c.addEventListener("mousedown",mouseDown,false);
c.addEventListener("mouseup",mouseUp,false);

//Getting the 
function getMouseCoordinates() {
    event = event || window.event;
    mouseX = event.pageX - c.offsetLeft,
        mouseY = event.pageY - c.offsetTop;  
}

//This is what should be done while moving the mouse
function mouseMove(event) {
    getMouseCoordinates();
    if (myRectangle.drag) {
        myRectangle.x = mouseX-mouseOffset.x;
        myRectangle.y = mouseY-mouseOffset.y;
    }
}

// This is what should happen when mouse button is pressed down
function mouseDown() {
    if (mouseX > myRectangle.x &&
        mouseX < myRectangle.x+myRectangle.w &&
        mouseY > myRectangle.y &&
        mouseY < myRectangle.y + myRectangle.h) {
        if (document.getElementById("offset").checked) {
            mouseOffset.x = mouseX-myRectangle.x;
            mouseOffset.y = mouseY-myRectangle.y;
        }
        else {
            mouseOffset.x = 0;
            mouseOffset.y = 0;
        }
        
        myRectangle.drag = true;
        background = "#66FF99";
    }
}

// This is what should happen when mouse button is released back up
function mouseUp() {
    myRectangle.drag = false;
    background = "#0099CC"; 
}

function draw() {
    // Clear the canvas before painting.
    ctx.fillStyle="#F0F0F0";
    ctx.fillRect(0,0,c.width,c.height);
    
    //Drawing the rectangle
    ctx.fillStyle=background;
    ctx.fillRect(myRectangle.x,myRectangle.y,myRectangle.w,myRectangle.h); 
    ctx.strokeRect(myRectangle.x,myRectangle.y,myRectangle.w,myRectangle.h);
    
    // Loop the drawing
    requestAnimationFrame(draw);
}

draw(); //we need to initiate the drawing to start it.
<canvas id="canvas"></canvas><br />
<input type="checkbox" id="offset">Check to use offset values.