How to draw a path with variable stroke width

后端 未结 1 1152
耶瑟儿~
耶瑟儿~ 2020-12-29 15:32

My code is basically from this example (http://corner.squareup.com/2010/07/smooth-signatures.html) and Google APIs (FingerPaint) but now I want to use the class Veloci

相关标签:
1条回答
  • 2020-12-29 16:09

    You can use split your path object every time your stroke value changes depending on velocity. In you SignatureView class add

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

    and take another ArrayList to keep stroke value for each path

    ArrayList<int> strokes = new ArrayList<int>();
    

    add a variable lastStroke along with lastTouchX and lastTouchY. I will recommend you to make lastStroke of type int.

    private int lastStroke = -1; //give an initial value
    

    now your onTouchEvent method should be something like this

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float eventX = event.getX();
        float eventY = event.getY();
        int historySize = event.getHistorySize();
        int eventStroke= //calculate stroke size with velocity and make it between 1-10 or any range you seem fit
    
        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:
    
                float dx = Math.abs(eventX - mX);
                float dy = Math.abs(eventY - mY);
    
                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                    if(lastStroke != evetnStroke){
                        mPath = new Path();
                        mPath.moveTo(mX,mY);
                        mPaths.Add(mPath);
                        mStrokes.Add(eventStroke);
                    }
                    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;
    
            default:
                Log.d(TAG, "Ignored touch event: " + event.toString());
            return false;
        }
        // Include half the stroke width to avoid clipping.
        invalidate(     (int) (dirtyRect.left - HALF_STROKE_WIDTH),
                        (int) (dirtyRect.top - HALF_STROKE_WIDTH),
                        (int) (dirtyRect.right + HALF_STROKE_WIDTH),
                        (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
    
        lastTouchX = eventX;
        lastTouchY = eventY;
        lastStroke = eventStroke;
        return true;
    }
    

    and your ondraw method would be

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

    this is the basic idea. you need to modify it to make it work.

    0 讨论(0)
提交回复
热议问题