gpt4 book ai didi

android - 如何在 Canvas 中绘制可变宽度的路径

转载 作者:行者123 更新时间:2023-11-29 21:22:34 30 4
gpt4 key购买 nike

我正在使用以下代码行在 Canvas 上绘制路径。到目前为止一切正常,我可以使用这段代码轻松绘制路径。

但是现在我们的要求是绘制一条宽度可变的路径,意味着用户绘制的路径是基于用户施加的压力,我的意思是说如果用户施加轻压力路径会很细,如果用户施加压力施加高压路径会变厚等。到目前为止,我也成功地绘制了一条可变宽度的路径,但绘制的线条并不平滑。为什么会这样?我的代码中有什么遗漏吗?

帮我解决这个问题。

我用一个宽度绘制路径的代码

 public class FingerPaint extends GraphicsActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}

public void colorChanged(int color)
{

}

public class MyView extends View
{
private static final float STROKE_WIDTH = 5f;

private Paint paint = new Paint();

private Path mPath = new Path();
ArrayList<Path> mPaths = new ArrayList<Path>();

ArrayList<Integer> mStrokes = new ArrayList<Integer>();

private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();

private int lastStroke = -1;
int variableWidthDelta = 0;

private float mX, mY;

private static final float TOUCH_TOLERANCE = 4;

public MyView(Context context)
{
super(context);

paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}

public void clear()
{
mPath.reset();
// Repaints the entire view.
invalidate();
}

@Override
protected void onDraw(Canvas canvas)
{
for(int i=0; i<mPaths.size();i++)
{
paint.setStrokeWidth(mStrokes.get(i));
canvas.drawPath(mPaths.get(i), paint);
}
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
int historySize = event.getHistorySize();

switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
resetDirtyRect(eventX, eventY);
mPath.reset();
mPath.moveTo(eventX, eventY);
mX = eventX;
mY = eventY;
break;
}
case MotionEvent.ACTION_MOVE:
{
if (event.getPressure()>=0.00 && event.getPressure()<0.05)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.05 && event.getPressure()<0.10)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.10 && event.getPressure()<0.15)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.15 && event.getPressure()<0.20)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.20 && event.getPressure()<0.25)
{
variableWidthDelta = -2;
}
else if (event.getPressure() >= 0.25 && event.getPressure()<0.30)
{
variableWidthDelta = 1;
}
else if (event.getPressure() >= 0.30 && event.getPressure()<0.35)
{
variableWidthDelta = 2;
}
else if (event.getPressure() >= 0.35 && event.getPressure()<0.40)
{
variableWidthDelta = 3;
}
else if (event.getPressure() >= 0.40 && event.getPressure()<0.45)
{
variableWidthDelta = 4;
}
else if (event.getPressure() >= 0.45 && event.getPressure()<0.60)
{
variableWidthDelta = 5;
}

float dx = Math.abs(eventX - mX);
float dy = Math.abs(eventY - mY);

if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
if(lastStroke != variableWidthDelta)
{
mPath.lineTo(mX, mY);

mPath = new Path();
mPath.moveTo(mX,mY);
mPaths.add(mPath);
mStrokes.add(variableWidthDelta);
}

mPath.quadTo(mX, mY, (eventX + mX)/2, (eventY + mY)/2);
mX = eventX;
mY = eventY;
}

for (int i = 0; i < historySize; i++)
{
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
}

break;
}
case MotionEvent.ACTION_UP:
{
for (int i = 0; i < historySize; i++)
{
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
}

mPath.lineTo(mX, mY);
break;
}
}

// Include half the stroke width to avoid clipping.
invalidate();

lastTouchX = eventX;
lastTouchY = eventY;
lastStroke = variableWidthDelta;

return true;
}

private void expandDirtyRect(float historicalX, float historicalY)
{
if (historicalX < dirtyRect.left)
{
dirtyRect.left = historicalX;
}
else if (historicalX > dirtyRect.right)
{
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top)
{
dirtyRect.top = historicalY;
}
else if (historicalY > dirtyRect.bottom)
{
dirtyRect.bottom = historicalY;
}
}

/**
* Resets the dirty region when the motion event occurs.
*/
private void resetDirtyRect(float eventX, float eventY)
{
// The lastTouchX and lastTouchY were set when the ACTION_DOWN
// motion event occurred.
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
}
}

enter image description here

最佳答案

路径不支持可变宽度绘图。

您可以使用 MotionEvent.getPressure() 获取触摸压力和速度和 VelocityTracker.computeCurrentVelocity()方法。

接下来,您需要创建一个函数来将特定速度或压力映射到特定宽度。

假设您已准备好这些,绘制可变宽度路径的一种方法是将一条路径分成多条路径,每条路径具有不同的宽度。例如,如果宽度需要在一条路径的过程中从 10 增加到 50,您可以有 10 条路径而不是宽度 5、10、15、20...等等。您将不得不进行大量优化,因为创建大量 Path 对象会导致内存消耗。

另一种方法是使用 quad-curvesbezier curves .

关于android - 如何在 Canvas 中绘制可变宽度的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20560322/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com