Автор: Пэн Вейцзе
Бингдун нельзя купить, Железный Бингдун недоступен, вязать Бингдун из шерсти не умею, лепить из пластилина тоже, но мы сможем нарисовать его программно.
"Дайте человеку рыбу", лучше "учите его ловить рыбу". Сегодня мы покажем вам, как нарисовать Бингдуна.
Хороший инструмент необходим для выполнения задачи. Наличие хорошего инструмента позволяет нам рисовать не только Бингдуна, но и самолёты, танки и пушки.
Вычисление центральной точки важно для красоты рисунка. Здесь ключевой момент — выравнивание осей с помощью вспомогательных линий.
@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;
}
```Инициализация координатной системы:
```java
private Point mCoo; // Координатная система
private Picture mPicture; // Канва для координатной сетки
/**
* Инициализация координатной сетки при запуске
*/
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 OnClickListener 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);
// Установка пунктирного эффекта new float[]{видимая длина, невидимая длина}, смещение
paint.setPathEffect(new DashPathEffect(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);
// Установка пунктирного эффекта new float[]{видимая длина, невидимая длина}, смещение
paint.setPathEffect(null);
}```markdown
/**
* Отрисовка текста в координатной системе
*
* @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, String.valueOf(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);
}
}
for (int i = 1; i < coo.getPointX() / 50; i++) {
paint.setStrokeWidth(2);
canvas.drawText(paint, "-" + String.valueOf(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);
}
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%.

Подготовка кисти
```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);
Определите начальную точку, конечную точку и выберите произвольную контрольную точку.
// Начальная точка
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);
}
Метод поиска контрольной точки, который позволяет найти начальную точку, конечную точку и контрольную точку.```java @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; }
Отображение координат касания

Эффект и практическое применение
|  |  |
| --------------------------- | ------------- |
### 4. Анимация процесса отрисовки Реализация анимационного эффекта в начале
> Вначале использовали `AnimatorValue`, но выяснилось, что это возможно только начиная с API7, и у нас много отрезков; позже перешли на использование `EventHandler` для пошагового рисования;
```java
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);
Подтверждение центральной точки, создание координатной системы, обеспечивает быстрое развитие проекта;
В данной статье используется второго порядка Безье-кривая для рисования; На основе первого этапа, затем находятся относительные координаты при событии touch.
bindingwonder: HarmonyOS JAVA - Пошаговая инструкция по рисованию Bing Dwen Dwen (gitee.com)
От базовых знаний до продвинутых навыков, от приемов до примеров, систематическое представление технологий разработки HarmonyOS, приветствуем ваши статьи и подписки, вместе мы будем строить экосистему HarmonyOS.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )