#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

炒沙作縻终不饱,缕冰文章费工巧。这篇文章主要讲述#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩相关的知识,希望能为你提供帮助。
春节不停更,此文正在参加「星光计划-春节更帖活动」
作者:彭为杰
简介冰墩墩买不到,金墩墩买不起,毛线墩墩不会勾,橡皮泥墩墩不会捏,雪墩墩不会堆,但我们会用程序绘制一个冰墩墩;
授人以鱼,不如授人以渔。今天手把手教大家来一个冰墩墩!
效果演示

#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片

实现思路 1 建立坐标系
工欲善其事,必先利其器,有的好的工具,冰墩墩也好,飞机坦克大炮都能绘制出来;
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片

计算出中心点的问题,这里细节在于中线点和辅助线对齐保证美观
@Override public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) int componentWidth = EstimateSpec.getSize(widthEstimateConfig); int componentHeight = EstimateSpec.getSize(heightEstimateConfig); this.width = componentWidth; this.height = componentHeight; centerX = this.width / 2; centerY = this.height / 2; // 保证辅助线取整 centerX = ((int) (centerX / 50)) * 50; centerY = ((int) (centerY / 50)) * 50; Logger.d("width:" + width); Logger.d("height:" + height); Logger.d("centerX:" + centerX); Logger.d("centerY:" + centerY); recordBg(); //初始化时录制坐标系和网格setEstimatedSize( EstimateSpec.getChildSizeWithMode(componentWidth, componentWidth, EstimateSpec.PRECISE), EstimateSpec.getChildSizeWithMode(componentHeight, componentHeight, EstimateSpec.PRECISE) ); return true;

初始化坐标系
private Point mCoo; //坐标系 private Picture mPicture; //坐标系和网格的Canvas元件/** * 初始化时录制坐标系和网格 */ private void recordBg() //准备屏幕尺寸 Point winSize = new Point(width, height); mCoo = new Point(centerX, centerY); Paint gridPaint = new Paint(); mPicture = new Picture(); Canvas recordCanvas = mPicture.beginRecording(winSize.getPointXToInt(), winSize.getPointYToInt()); //绘制辅助网格 HelpDraw2.drawGrid(recordCanvas, winSize, gridPaint); //绘制坐标系 HelpDraw2.drawCoo(recordCanvas, mCoo, winSize, gridPaint); mPicture.endRecording();

onDraw方法中绘制坐标系
canvas.drawPicture(mPicture);

画布辅助类
/** * 辅助画布 * * @since 2022-02-09 */ public class HelpDraw2 /** * 绘制网格 */ public static void drawGrid(Canvas recordCanvas, Point winSize, Paint paint) //初始化网格画笔 paint.setStrokeWidth(2); paint.setColor(Color.GRAY); paint.setStyle(Paint.Style.STROKE_STYLE); //设置虚线效果new float[]可见长度, 不可见长度,偏移值 paint.setPathEffect(new PathEffect(new float[]10, 5, 0)); recordCanvas.drawPath(HelpPath.gridPath(50, winSize), paint); /** *绘制坐标系 * @param recording 画布 * @param coo 坐标系原点 * @param winSize 屏幕尺寸 * @param paint 画笔 */ public static void drawCoo(Canvas recording, Point coo, Point winSize, Paint paint) //初始化网格画笔 paint.setStrokeWidth(4); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.STROKE_STYLE); //设置虚线效果new float[]可见长度, 不可见长度,偏移值 paint.setPathEffect(null); //绘制直线 recording.drawPath(HelpPath.cooPath(coo, winSize), paint); //左箭头 recording.drawLine(winSize.getPointX(), coo.getPointY(), winSize.getPointX() - 40, coo.getPointY() - 20, paint); recording.drawLine(winSize.getPointX(), coo.getPointY(), winSize.getPointX() - 40, coo.getPointY() + 20, paint); //下箭头 recording.drawLine(coo.getPointX(), winSize.getPointY(), coo.getPointX() - 20, winSize.getPointY() - 40, paint); recording.drawLine(coo.getPointX(), winSize.getPointY(), coo.getPointX() + 20, winSize.getPointY() - 40, paint); //为坐标系绘制文字 drawText4Coo(recording, coo, winSize, paint); /** * 为坐标系绘制文字 * * @param canvas 画布 * @param coo 坐标系原点 * @param winSize 屏幕尺寸 * @param paint 画笔 */ private static void drawText4Coo(Canvas canvas, Point coo, Point winSize, Paint paint) //绘制文字 paint.setTextSize(50); canvas.drawText(paint, "x", winSize.getPointX() - 60, coo.getPointY() - 40); canvas.drawText(paint, "y", coo.getPointX() - 40, winSize.getPointY() - 60); paint.setTextSize(25); //X正轴文字 for (int i = 1; i < (winSize.getPointX() - coo.getPointX()) / 50; i++) paint.setStrokeWidth(2); canvas.drawText(paint, 100 * i + "", coo.getPointX() - 20 + 100 * i, coo.getPointY() + 40); paint.setStrokeWidth(5); canvas.drawLine(coo.getPointX() + 100 * i, coo.getPointY(), coo.getPointX() + 100 * i, coo.getPointY() - 10, paint); //X负轴文字 for (int i = 1; i < coo.getPointX() / 50; i++) paint.setStrokeWidth(2); canvas.drawText(paint, -100 * i + "", coo.getPointX() - 20 - 100 * i, coo.getPointY() + 40); paint.setStrokeWidth(5); canvas.drawLine(coo.getPointX() - 100 * i, coo.getPointY(), coo.getPointX() - 100 * i, coo.getPointY() - 10, paint); //y正轴文字 for (int i = 1; i < (winSize.getPointY() - coo.getPointY()) / 50; i++) paint.setStrokeWidth(2); canvas.drawText(paint, 100 * i + "", coo.getPointX() + 20, coo.getPointY() + 10 + 100 * i); paint.setStrokeWidth(5); canvas.drawLine(coo.getPointX(), coo.getPointY() + 100 * i, coo.getPointX() + 10, coo.getPointY() + 100 * i, paint); //y负轴文字 for (int i = 1; i < coo.getPointY() / 50; i++) paint.setStrokeWidth(2); canvas.drawText(paint, -100 * i + "", coo.getPointX() + 20, coo.getPointY() + 10 - 100 * i); paint.setStrokeWidth(5); canvas.drawLine(coo.getPointX(), coo.getPointY() - 100 * i, coo.getPointX() + 10, coo.getPointY() - 100 * i, paint);

2 绘制底图
我们选一张喜欢的冰墩墩作为底图,画笔设置透明度50%;
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片

准备画笔
mPixelMapPaint = new Paint(); mPixelMapPaint.setAlpha(0.5f);

绘制图片方法
private void drawPixelMap(Canvas canvas) Optional< PixelMap> image = PixelMapUtil.getPixelMapFromResource(getContext(), ResourceTable.Media_bdd); if (image.isPresent()) PixelMap pixelMap = image.get(); int pw = pixelMap.getImageInfo().size.width; int ph = pixelMap.getImageInfo().size.height; int offX = centerX - pw / 2; int offY = centerY - ph / 2; Logger.d("pw:" + pw + " ; ph:" + ph); RectFloat pixelRectFloat = new RectFloat(offX, offY, pw + offX, ph + offY); canvas.drawPixelMapHolderRect(new PixelMapHolder(pixelMap), pixelRectFloat, mPixelMapPaint);

onDraw方法中绘制图片
drawPixelMap(canvas);

3 绘制冰墩墩轮廓
贝塞尔曲线的了解和认识 1.简单认识:(图来源网络)
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片

2.二阶贝塞尔曲线控制点寻找示例:确定起点,终点,和任意选一个控制点
//起点 private Point start = new Point(0, 0); //终点 private Point end = new Point(400, 0); //控制点 private Point control = new Point(200, 200);

贝塞尔曲线
@Override public void onDraw(Component component, Canvas canvas) canvas.save(); canvas.translate(mCoo.getPointX(), mCoo.getPointY()); drawHelpElement(canvas); //绘制辅助工具--控制点和基准选 // 绘制贝塞尔曲线 mBezierPath.moveTo(start.getPointX(), start.getPointY()); mBezierPath.quadTo(control.getPointX(), control.getPointY(), end.getPointX(), end.getPointY()); canvas.drawPath(mBezierPath, mPaint); mBezierPath.reset(); //清空mBezierPath canvas.restore(); canvas.drawPicture(mPicture); //绘制辅助工具--控制点和基准选 private void drawHelpElement(Canvas canvas) // 绘制数据点和控制点 mHelpPaint.setColor(new Color(0x8820ECE2)); mHelpPaint.setStrokeWidth(20); canvas.drawPoint(start.getPointX(), start.getPointY(), mHelpPaint); canvas.drawPoint(end.getPointX(), end.getPointY(), mHelpPaint); canvas.drawPoint(control.getPointX(), control.getPointY(), mHelpPaint); // 绘制辅助线 resetHelpPaint(); canvas.drawLine(start.getPointX(), start.getPointY(), control.getPointX(), control.getPointY(), mHelpPaint); canvas.drawLine(end.getPointX(), end.getPointY(), control.getPointX(), control.getPointY(), mHelpPaint);

寻找控制点方法,这个可以找起点,终点,控制点
@Override public boolean onTouchEvent(Component component, TouchEvent touchEvent) // 根据触摸位置更新控制点,并提示重绘 MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex()); control.modify(point.getX() -mCoo.getPointX(),point.getY() -mCoo.getPointY()); Logger.d("touch control x:" + control.getPointX() + " y:" + control.getPointY()); invalidate(); return true;

触摸点打印
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片

效果和实际应用
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片
4,绘制过程动效
开头部分动效的实现
EventRunner runnerA = EventRunner.getMainEventRunner(); EventHandler handlerA = new EventHandler(runnerA) @Override protected void processEvent(InnerEvent event) super.processEvent(event); if (drawStep == 0) drawStep = 1; invalidate(); if (!drawLast) handlerA.sendEvent(1, 10); ; public void startDraw() Logger.d(":"); if (drawLast) drawStep = 0; handlerA.sendEvent(1); drawLast = false;

绘制分段式
不断改变childStep的步长即可改变每次绘制的效果PathMeasure pathMeasure = new PathMeasure(mBezierPath, false); childStep = pathMeasure.getLength(); //使用画笔虚线效果+偏移 PathEffect effect = new PathEffect( new float[]pathMeasure.getLength(), pathMeasure.getLength(), childStep); mPaint.setPathEffect(effect); canvas.drawPath(mBezierPath, mPaint);

总结1,中心的点的确认,坐标系的建立,可以达到快速开发的效果;
2,本文主要采用二阶贝塞尔曲线绘制;根据第一步的基础,然后再touch事件中找到相对坐标点;
代码地址bdd: HarmonyOS JAVA之手把手教你绘制冰墩墩 (gitee.com)
更多原创内容请关注:深开鸿技术团队入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
想了解更多关于鸿蒙的内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com/#bkwz
::: hljs-center
#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩

文章图片

【#过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩】:::

    推荐阅读