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),您需要检查距离图像的左上角有多远。
- 您首先需要声明两个新变量,例如
touchOffsetX
和touchOffsetY
。
然后在触摸屏幕时定义新变量。
touchOffsetX = touchX - image.x;
touchOffsetY = touchY - image.y;
现在当你移动图像时,你设置它的 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.
我正在构建一个应用程序,它将在 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),您需要检查距离图像的左上角有多远。
- 您首先需要声明两个新变量,例如
touchOffsetX
和touchOffsetY
。 然后在触摸屏幕时定义新变量。
touchOffsetX = touchX - image.x;
touchOffsetY = touchY - image.y;
现在当你移动图像时,你设置它的 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.