--

Monday 26 December 2016

SVG Line drawing

If you are looking for an Animated line drawing in sequence, you are at the right place. We have to download SVG Android library (i.e. Add jar to lib folder svg-android-1.1.jar) to use SVG image in application.




Working Logic

I elucidate the working logic step by step. We have to load the svg from the resources and render the svg to canvas and catch all the paths while rendering.




public List<SvgPath> getPathsForViewport(final int width, final int height) {
    final float strokeWidth = mSourcePaint.getStrokeWidth();
    Canvas canvas = new Canvas() {
        private final Matrix mMatrix = new Matrix();

        @Override        public int getWidth() {
            return width;
        }

        @Override        public int getHeight() {
            return height;
        }

        @Override        public void drawPath(Path path, Paint paint) {
            Path dst = new Path();

            //noinspection deprecation            getMatrix(mMatrix);
            path.transform(mMatrix, dst);
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(strokeWidth);
            mPaths.add(new SvgPath(dst, paint));
        }
    };

    rescaleCanvas(width, height, strokeWidth, canvas);

    return mPaths;
} 
then rescale the canvas with specific width and height.

private void rescaleCanvas(int width, int height, float strokeWidth, Canvas canvas) {
    if (mSvg == null) 
        return;
    final RectF viewBox = mSvg.getDocumentViewBox();

    final float scale = Math.min(width
                    / (viewBox.width() + strokeWidth),
            height / (viewBox.height() + strokeWidth));

    canvas.translate((width - viewBox.width() * scale) / 2.0f,
            (height - viewBox.height() * scale) / 2.0f);
    canvas.scale(scale, scale);

    mSvg.renderToCanvas(canvas);
} 

The line path is drawn on Canvas at onDraw() method. We pick either natural SVG image 
color or custom color. 
  
 
@Overrideprotected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if(mTempBitmap==null || (mTempBitmap.getWidth()!=canvas.getWidth()
            ||mTempBitmap.getHeight()!=canvas.getHeight()) )
    {
        mTempBitmap = Bitmap.createBitmap(canvas.getWidth(), 
                canvas.getHeight(), Bitmap.Config.ARGB_8888);
        mTempCanvas = new Canvas(mTempBitmap);
    }

    mTempBitmap.eraseColor(0);
    synchronized (mSvgLock) {
        mTempCanvas.save();
        mTempCanvas.translate(getPaddingLeft(), getPaddingTop());
        fill(mTempCanvas);
        final int count = paths.size();
        for (int i = 0; i < count; i++) {
            final SvgUtils.SvgPath svgPath = paths.get(i);
            final Path path = svgPath.path;
            final Paint paint1 = naturalColors ? svgPath.paint : paint;
            mTempCanvas.drawPath(path, paint1);
        }

        fillAfter(mTempCanvas);

        mTempCanvas.restore();

        applySolidColor(mTempBitmap);

        canvas.drawBitmap(mTempBitmap,0,0,null);
    }
}

 
 
If fillColor had value before then we replace untransparent pixels of bitmap by solid color. 
 
private void applySolidColor(final Bitmap bitmap) {
    if(fill && fillColor!= Color.argb(0,0,0,0) )
        if (bitmap != null) {
            for(int x=0;x<bitmap.getWidth();x++)
            {
                for(int y=0;y<bitmap.getHeight();y++)
                {
                    int argb = bitmap.getPixel(x,y);
                    int alpha = Color.alpha(argb);
                    if(alpha!=0)
                    {
                        int red = Color.red(fillColor);
                        int green = Color.green(fillColor);
                        int blue =  Color.blue(fillColor);
                        argb = Color.argb(alpha,red,green,blue);
                        bitmap.setPixel(x,y,argb);
                    }
                }
            }
        }
}
 
Then sets the duration of the animation. Since the AnimatorSet sets the duration for 
each Animator, we have to divide it by the number of paths.


 
public AnimatorSetBuilder(final SVGPathView pathView) {
    paths = pathView.paths;
    for (SvgUtils.SvgPath path : paths) {
        path.setAnimationStepListener(pathView);
        ObjectAnimator animation = ObjectAnimator.ofFloat(path, "length", 0.0f, path.getLength());
        animators.add(animation);
    }
    animatorSet.playSequentially(animators);
} 
 


 

How to use?

Add SVGPathView class in xml layout.
 
<com.truedreamz.svglinedrawing.LineDrawing.SVGPathView
    android:id="@+id/pathView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="30dp"
    android:paddingRight="30dp"
    android:layout_marginTop="80dp"
    android:paddingBottom="30dp"
    app:svg="@raw/ironman"
    app:pathColor="@android:color/holo_blue_dark"
    app:naturalColors="true"
    app:pathWidth="2dp"/>
  
Use the animator for parallel animation
 
 pathView.getPathAnimator().
        delay(100).
        duration(8000).
        interpolator(new AccelerateDecelerateInterpolator()).
        listenerEnd(new SVGPathView.AnimatorBuilder.ListenerEnd() {
            @Override            public void onAnimationEnd() {
                txtViewLoading.setText("Line drawing completed.");
                Toast.makeText(SVGDrawingActivity.this,"Line drawing is done.",Toast.LENGTH_LONG).show();
            }
        }).start();
 
Use the animator for sequential animation

pathView.getSequentialPathAnimator().
        delay(100).
        duration(8000).
        interpolator(new AccelerateDecelerateInterpolator()).
        listenerEnd(new SVGPathView.AnimatorBuilder.ListenerEnd() {
            @Override            public void onAnimationEnd() {
                txtViewLoading.setText("Line drawing completed.");
                Toast.makeText(SVGDrawingActivity.this,"Line drawing is done.",Toast.LENGTH_LONG).show();
            }
        }).start(); 

I have uploaded complete source code in Github, 
https://github.com/JayaprakashR-Zealot/SVGLineDrawing 
 
Kindly raise your queries in the command section. 
Happy coding !!!
Thanks. 

No comments:

Post a Comment