1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/guangdong-wangduoyu-bdd

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
README.md 15 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 04.03.2025 12:19 8d9c694

ОС HarmonyOS Java: шаг за шагом научимся рисовать Бингдуна

Автор: Пэн Вейцзе

Введение

Бингдун нельзя купить, Железный Бингдун недоступен, вязать Бингдун из шерсти не умею, лепить из пластилина тоже, но мы сможем нарисовать его программно.

"Дайте человеку рыбу", лучше "учите его ловить рыбу". Сегодня мы покажем вам, как нарисовать Бингдуна.

Демонстрация эффекта

бингдун

Реализация идеи

1. Создание координатной системы

Хороший инструмент необходим для выполнения задачи. Наличие хорошего инструмента позволяет нам рисовать не только Бингдуна, но и самолёты, танки и пушки.

координатная система

Вычисление центральной точки важно для красоты рисунка. Здесь ключевой момент — выравнивание осей с помощью вспомогательных линий.

@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%.

![Основное изображение](ditu.jpg)

Подготовка кисти

```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. Простое понимание: (Изображение взято из сети)bse

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);

}

Метод поиска контрольной точки, который позволяет найти начальную точку, конечную точку и контрольную точку.```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; }


Отображение координат касания

![touch](touch.jpg)

Эффект и практическое применение

| ![ketiaojie](ketiaojie.gif) | ![qx](qx.gif) |
| --------------------------- | ------------- |

### 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);

Заключение

  1. Подтверждение центральной точки, создание координатной системы, обеспечивает быстрое развитие проекта;

  2. В данной статье используется второго порядка Безье-кривая для рисования; На основе первого этапа, затем находятся относительные координаты при событии touch.

Адрес кода

bindingwonder: HarmonyOS JAVA - Пошаговая инструкция по рисованию Bing Dwen Dwen (gitee.com)

Больше оригинальных материалов читайте здесь: Открытый мир HarmonyOS академия

От базовых знаний до продвинутых навыков, от приемов до примеров, систематическое представление технологий разработки HarmonyOS, приветствуем ваши статьи и подписки, вместе мы будем строить экосистему HarmonyOS.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/guangdong-wangduoyu-bdd.git
git@api.gitlife.ru:oschina-mirror/guangdong-wangduoyu-bdd.git
oschina-mirror
guangdong-wangduoyu-bdd
guangdong-wangduoyu-bdd
master