HarmonyOS APP实战指南:画图APP之画笔属性调节

 更新时间:2026年07月13日 10:08:51   作者:不羁的木木  
本篇教你用颜色选择器、粗细滑块和透明度滑块,实时调节画笔效果,告别单调黑线,从预设色板轻松选色,滑动控制笔触粗细与透明度,跟着步骤集成PenSettings属性管理器,让每笔绘画都自定义,实现灵活涂鸦体验

1. 开篇

上一篇我们实现了触摸手绘功能,核心产出了 PenManager 模块和 PaintComponent 页面。PenManager 通过 touchEvent 回调收集触摸点,构建 Path 对象,再利用 CanvasRenderingContext2D.drawPath() 将其绘制到画布上。读者跟随步骤,已经可以让手指在屏幕上自由涂鸦了。

然而手绘功能还有一个关键短板:绘制出的线条颜色固定为黑色、粗细固定为3px、透明度固定为100%。这样的笔触过于单调,无法满足实际绘画需求。本篇将聚焦于画笔属性调节,通过颜色选择器、粗细滑块和透明度滑块三个UI组件,让用户能够实时调整画笔效果。我们将把这些属性绑定到 Pen 对象上,确保每次绘制都使用最新的参数。

2. 核心实现

实现画笔属性调节需要三个步骤:首先,创建一个画笔属性配置管理器 PenSettings,用于存储和更新颜色、粗细、透明度;其次,设计颜色选择器 ColorPicker 组件,让用户可以从预设色板中选色;最后,实现粗细和透明度的滑块组件 Slider。所有修改都会立即反应在下一笔绘制中。

2.1 基础配置:导入模块与状态管理

在画图APP中,我们需要导入 @ohos.graphics.drawing 模块中的 Pen 类,以及状态管理接口用于跨组件通信。

// utils/PenSettings.ets
// 画笔属性管理器,采用单例模式,全局共享同一份配置
import { Pen } from '@ohos.graphics.drawing';
class PenSettings {
  private static instance: PenSettings = new PenSettings();
  // 当前选中的颜色,十六进制格式,默认黑色
  public currentColor: string = '#FF000000';
  // 当前画笔粗细,单位px,默认3
  public currentWidth: number = 3;
  // 当前透明度,范围0-255,默认255(完全不透明)
  public currentAlpha: number = 255;
  private constructor() { }
  static getInstance(): PenSettings {
    return PenSettings.instance;
  }
  // 应用当前设置到传入的Pen对象
  applyToPen(pen: Pen): void {
    // 解析颜色字符串为整数,例如'#FF0000' -> 0xFF0000
    const colorInt = parseInt(this.currentColor.substring(1), 16);
    // 透明度与颜色合并,完成ARGB组合
    const argbColor = (this.currentAlpha << 24) | (colorInt & 0x00FFFFFF);
    pen.setColor(argbColor);
    pen.setStrokeWidth(this.currentWidth);
    pen.setAlpha(this.currentAlpha);
  }
  // 更新颜色,并触发画布重绘(通过回调)
  setColor(color: string): void {
    this.currentColor = color;
    this.onSettingsChanged?.();
  }
  setWidth(width: number): void {
    this.currentWidth = width;
    this.onSettingsChanged?.();
  }
  setAlpha(alpha: number): void {
    this.currentAlpha = alpha;
    this.onSettingsChanged?.();
  }
  // 设置变更回调,用于通知画布重新绘制
  onSettingsChanged: (() => void) | null = null;
}
export default PenSettings;

关键点说明

  • 使用单例模式确保整个APP共享同一份画笔配置,避免重复创建。
  • applyToPen 方法接收一个 Pen 实例,将当前颜色、粗细、透明度一次性应用到该笔上。颜色处理时需要注意透明度要与颜色值合并为ARGB格式。
  • setColor 等方法通过回调机制通知外部(如画布组件)重新绘制,这样才能在调整滑块后立即看到预览效果。
  • API参考自 @ohos.graphics.drawing.Pen,其中 setColor / setStrokeWidth / setAlpha 是官方提供的标准方法。

2.2 色彩选择组件 ColorPicker

ColorPicker 组件提供一个预设颜色网格,用户点击某个色块后,更新 PenSettings 中的颜色值。

// components/ColorPicker.ets
// 颜色选择器组件,展示预设色板供用户点击选择
import PenSettings from '../utils/PenSettings';
@Component
export struct ColorPicker {
  @State private selectedColor: string = '#FF000000';
  // 预设颜色数组,涵盖常见绘画色彩
  private colors: string[] = [
    '#FF000000', '#FFFFFFFF', '#FFFF0000', '#FF00FF00',
    '#FF0000FF', '#FFFFFF00', '#FFFF00FF', '#FF00FFFF',
    '#FF808080', '#FFC0C0C0', '#FF800000', '#FF008000',
    '#FF000080', '#FF808000', '#FF800080', '#FF008080',
    '#FFE0B0FF', '#FFFFC0CB', '#FFA52A2A', '#FF000000'
  ];
  build() {
    Column() {
      // 标题
      Text('颜色选择')
        .fontSize(14)
        .fontWeight(FontWeight.Bold)
        .width('100%')
        .textAlign(TextAlign.Start)
        .margin({ bottom: 6 });
      // 颜色网格,每行5个
      Grid() {
        ForEach(this.colors, (color: string) => {
          GridItem() {
            Stack() {
              // 色块方块
              Rect()
                .width(36)
                .height(36)
                .borderRadius(6)
                .fill(color)
                .border({
                  width: this.selectedColor === color ? 3 : 1,
                  color: this.selectedColor === color ? '#FF007AFF' : '#FFCCCCCC'
                })
                .onClick(() => {
                  this.selectedColor = color;
                  PenSettings.getInstance().setColor(color);
                });
              // 如果是当前选中颜色,显示选中标记
              if (this.selectedColor === color) {
                Text('✓')
                  .fontSize(18)
                  .fontColor('#FF007AFF')
                  .fontWeight(FontWeight.Bold);
              }
            }
            .justifyContent(FlexAlign.Center)
            .alignItems(VerticalAlign.Center)
            .width(40)
            .height(40)
          }
        })
      }
      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
      .rowsTemplate('1fr 1fr 1fr 1fr')
      .width('100%')
      .maxHeight(200)
      .columnsGap(8)
      .rowsGap(8)
    }
    .padding(12)
    .backgroundColor('#FFF8F8F8')
    .borderRadius(12)
  }
}

关键点说明

  • 颜色值采用 '#AARRGGBB' 格式,其中 AA 部分在预设颜色中固定为 FF(不透明),实际透明度由 PenSettings 中的 currentAlpha 控制。
  • 选中颜色的色块会有蓝色边框和勾选标记,提供清晰的视觉反馈。
  • 点击色块时调用 PenSettings.getInstance().setColor(color),该操作会触发回调,通知画布应用新颜色。
  • 色板只是预设颜色,后续我们可以扩展为自定义色盘,例如使用色相环选择。

2.3 粗细与透明度调节滑块 Slider

使用原生 Slider 组件,分别控制画笔粗细(1-20px)和透明度(0-255)。

// components/BrushSlider.ets
// 画笔粗细和透明度滑块组件,支持滑动调节
import PenSettings from '../utils/PenSettings';
@Component
export struct BrushSlider {
  // 当前画笔粗细
  @State private brushWidth: number = 3;
  // 当前透明度
  @State private brushAlpha: number = 255;
  build() {
    Column({ space: 16 }) {
      // 粗细调节
      Column() {
        Row() {
          Text('粗细')
            .fontSize(14)
            .fontWeight(FontWeight.Medium);
          Text(`${this.brushWidth}px`)
            .fontSize(12)
            .fontColor('#FF666666')
            .margin({ left: 8 });
        }
        .width('100%')
        .justifyContent(FlexAlign.Start);
        Slider({
          value: this.brushWidth,
          min: 1,
          max: 20,
          step: 1,
          style: SliderStyle.OutSet
        })
          .width('100%')
          .showTips(true)
          .showSteps(false)
          .onChange((value: number) => {
            this.brushWidth = value;
            PenSettings.getInstance().setWidth(value);
          });
      }
      // 透明度调节
      Column() {
        Row() {
          Text('透明度')
            .fontSize(14)
            .fontWeight(FontWeight.Medium);
          Text(`${Math.round(this.brushAlpha / 255 * 100)}%`)
            .fontSize(12)
            .fontColor('#FF666666')
            .margin({ left: 8 });
        }
        .width('100%')
        .justifyContent(FlexAlign.Start);
        Slider({
          value: this.brushAlpha,
          min: 0,
          max: 255,
          step: 1,
          style: SliderStyle.OutSet
        })
          .width('100%')
          .showTips(true)
          .showSteps(false)
          .onChange((value: number) => {
            this.brushAlpha = value;
            PenSettings.getInstance().setAlpha(value);
          });
      }
    }
    .padding(12)
    .backgroundColor('#FFF8F8F8')
    .borderRadius(12)
  }
}

关键点说明

  • 粗细范围设置为1-20px,步长1px,可以满足从细线到粗笔的绘画需求。
  • 透明度范围0-255,对应0%-100%不透明,右侧显示百分比以便用户理解。
  • SlidershowTips 属性设为 true,滑动时会显示当前数值的工具提示。
  • 每次滑动都调用 PenSettings 的 setWidth / setAlpha 方法,同时传递给其绑定的回调。

2.4 将设置组件集成到主画布页面

最后,将上述组件组合到画图APP的主页面中,并确保每次绘制时使用 PenSettings 中的最新配置。

// pages/PaintPage.ets
// 画图APP主页面,集成颜色选择器、滑块和画布区域
import PenSettings from '../utils/PenSettings';
import { ColorPicker } from '../components/ColorPicker';
import { BrushSlider } from '../components/BrushSlider';
import drawing from '@ohos.graphics.drawing';
@Entry
@Component
struct PaintPage {
  private canvasContext: CanvasRenderingContext2D;
  private settings: PenSettings = PenSettings.getInstance();
  @State private currentTool: string = 'pen'; // 'pen' | 'rect' | 'circle'
  // 当前正在使用的Pen对象
  private drawingPen: drawing.Pen = new drawing.Pen();
  aboutToAppear(): void {
    // 注册设置变更回调:每次颜色/粗细/透明度变化时,更新当前Pen
    this.settings.onSettingsChanged = () => {
      this.settings.applyToPen(this.drawingPen);
    };
    // 初始化时应用默认设置
    this.settings.applyToPen(this.drawingPen);
  }
  build() {
    Column() {
      // 顶部工具栏
      Row() {
        Button('画笔')
          .onClick(() => { this.currentTool = 'pen'; })
        Button('矩形')
          .onClick(() => { this.currentTool = 'rect'; })
        Button('圆形')
          .onClick(() => { this.currentTool = 'circle'; })
      }
      .padding(8)
      .width('100%')
      .justifyContent(FlexAlign.SpaceEvenly)
      // 中间画布区域
      Canvas(this.canvasContext)
        .width('100%')
        .layoutWeight(1)
        .backgroundColor('#FFFFFFFF')
      // 底部设置区:颜色选择 + 粗细/透明度
      Column({ space: 12 }) {
        ColorPicker()
        BrushSlider()
      }
      .padding(8)
      .width('100%')
      .backgroundColor('#FFF0F0F0')
    }
    .width('100%')
    .height('100%')
  }
}

关键点说明

  • aboutToAppear 中注册了 PenSettings 的回调 onSettingsChanged,当颜色、粗细或透明度改变时,自动调用 applyToPen 更新 this.drawingPen
  • 在实际绘制场景中(如触摸移动的回调),需要确保使用的是 this.drawingPen,而不是临时创建的 Pen 对象,这样才能应用最新的设置。
  • 底部布局同时包含 ColorPicker 和 BrushSlider,用户可以在绘画过程中随时调整参数。

3. 运行验证

完成上述代码后,运行APP,应观察到以下效果:

  1. 底部出现颜色选择器网格,默认选中第一个黑色色块。点击其他颜色(如红色 #FFFF0000),画布的下一笔线条会变为红色。
  2. 粗细滑块滑动时,数值显示从1px到20px,释放后下一笔线条会使用新粗细。
  3. 透明度滑块从0%到100%,滑动时工具提示显示百分比,笔画会呈现不同程度的半透明效果。
  4. 所有调节即时生效,不需要重启或重新初始化画布。

立即调出画笔的隐藏功能!本篇教你用颜色选择器、粗细滑块和透明度滑块,实时调节画笔效果,告别单调黑线,从预设色板轻松选色,滑动控制笔触粗细与透明度,跟着步骤集成PenSettings属性管理器,让每笔绘画都自定义,实现灵活涂鸦体验

4. 小结与预告

本篇产出了三个核心模块:PenSettings 画笔属性管理器、ColorPicker 颜色选择器、BrushSlider 粗细与透明度滑块。这些组件被集成到主画布页面中,实现了画笔参数的实时调节,让用户能画出不同颜色、粗细和透明度的线条。这个功能是画图APP用户体验的关键提升点,也是后续实现形状绘制、文字添加等功能的基础。

下一篇「切换绘制模式与交互反馈」将实现矩形、圆形和自由画笔三种绘制模式的切换,优化UI反馈,让用户清晰知道当前处于哪种绘制状态,为后续的图形绘制做铺垫。

到此这篇关于HarmonyOS APP实战指南:画图APP之画笔属性调节的文章就介绍到这了,更多相关HarmonyOS 绘图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论