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

OSCHINA-MIRROR/guangdong-wangduoyu-bdd

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

HarmonyOS JAVA: пошаговое руководство по рисованию Бингдуна

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

Введение

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

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

Демонстрация результата

bindwendwen

Реализация

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 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 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);
        // Установка пунктирного стиля new float[]{видимая длина, невидимая длина}, смещение
        paint.setPathEffect(null);
    }```java
        // Рисование прямых линий
        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);
    }
}
```java
    /**
     * Отрисовка текста для координатной системы
     *
     * @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("x", winSize.getPointX() - 60, coo.getPointY() - 40, paint);
        canvas.drawText("y", coo.getPointX() - 40, winSize.getPointY() - 60, paint);
        paint.setTextSize(25);
        // Текст для положительной оси X
        for (int i = 1; i < (winSize.getPointX() - coo.getPointX()) / 50; i++) {
            paint.setStrokeWidth(2);
            canvas.drawText(100 * i + "", coo.getPointX() - 20 + 100 * i, coo.getPointY() + 40, paint);
            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(-100 * i + "", coo.getPointX() - 20 - 100 * i, coo.getPointY() + 40, paint);
            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%;

фон

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

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, но выяснилось, что это возможно только начиная с API 7, и у нас много отрезков. Позже был использован 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 находятся относительные координаты.

## Адрес кода

[bingdwendwen: HarmonyOS JAVA  пошаговое руководство по рисованию Bing Dwen Dwen (gitee.com)](https://gitee.com/guangdong-wangduoyu/bingdwendwen)

## Больше оригинальных материалов смотрите на: [HarmonyOS Academy](https://harmonyos.51cto.com/column/59)

От базы до мастерства, от техник до примеров, систематическое представление технологий разработки 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