上一篇我们学了 Canvas Brush Pen 的基础用法——画矩形、画圆、填颜色、描边。但如果你真的在做一个绘画 APP光有这些是不够的。你还需要渐变色、半透明、抗锯齿、阴影……今天我们来深入看看 Brush 和 Pen 的进阶功能。下面是 Brush 和 Pen 进阶功能的整体结构Brush / Pen 进阶功能抗锯齿 setAntiAlias透明度 setAlpha渐变色 setShaderEffect阴影 setShadowLayer混合模式 setBlendMode颜色滤波 setColorFilter图像滤波 setImageFilter线性渐变径向渐变扫描渐变抗锯齿让边缘更平滑你有没有注意过画一个圆的时候边缘可能会有锯齿感——就像一排阶梯一样。这是因为屏幕是由像素点组成的斜线和曲线在像素网格上不可能完美平滑。抗锯齿Anti-Aliasing的原理很简单在边缘处用半透明的像素做过渡让阶梯感变弱。Brush 和 Pen 都支持开启抗锯齿constbrushnewdrawing.Brush();brush.setAntiAlias(true);// 开启抗锯齿constpennewdrawing.Pen();pen.setAntiAlias(true);// 开启抗锯齿开启后图形的边缘会更平滑但可能会稍微模糊一点。一般情况下建议开启除非你在做像素画那种需要锐利边缘的风格。透明度做出层次感brush.setAlpha(128);// 半透明pen.setAlpha(64);// 更透明取值范围[0, 255]0 完全透明看不见255 完全不透明。透明度能做什么很多效果都离不开它半透明的色块叠加做出磨砂玻璃效果多层半透明图形叠加做出深度感淡入淡出动画通过动态改变 alpha 值渐变色不只是纯色纯色太平淡了用ShaderEffect可以做出渐变效果。ShaderEffect 支持三种渐变线性渐变从一个点到另一个点颜色平滑过渡constshaderEffectdrawing.ShaderEffect.createLinearGradient({x:0,y:0},// 起点{x:300,y:0},// 终点[0xFFFF0000,0xFF0000FF],// 红色到蓝色drawing.TileMode.CLAMP// 平铺模式);brush.setShaderEffect(shaderEffect);canvas.attachBrush(brush);canvas.drawRect(0,0,300,200);canvas.detachBrush();这段代码画了一个从左到右、红到蓝渐变的矩形。colors数组里放的是 32 位 ARGB 颜色值。格式是0xAARRGGBB比如0xFFFF0000是不透明的红色0xFF0000FF是不透明的蓝色。TileMode控制渐变超出范围后怎么处理CLAMP用边缘颜色填充剩余区域REPEAT重复渐变MIRROR镜像重复DECAL只在原始范围内渲染径向渐变从圆心向外扩散的渐变constshaderEffectdrawing.ShaderEffect.createRadialGradient({x:150,y:100},// 圆心100,// 半径[0xFFFF0000,0xFF00FF00],// 红色到绿色drawing.TileMode.CLAMP);brush.setShaderEffect(shaderEffect);这种渐变就像阳光从中心向外扩散中心是红色边缘是绿色。适合做按钮的发光效果或者背景的聚光灯效果。扫描渐变像雷达扫描一样绕着圆心旋转的渐变constshaderEffectdrawing.ShaderEffect.createSweepGradient({x:150,y:100},// 圆心[0xFFFF0000,0xFF0000FF,0xFF00FF00],// 红→蓝→绿drawing.TileMode.CLAMP,0,// 起始角度360// 结束角度);brush.setShaderEffect(shaderEffect);适合做圆形进度条、色轮选择器之类的 UI。面对三种渐变类型如何选择可以参考下面的流程单方向过渡从中心向外扩散绕中心旋转需要渐变效果渐变方向是什么?线性渐变 createLinearGradient径向渐变 createRadialGradient扫描渐变 createSweepGradient适合: 背景渐变、按钮适合: 发光效果、聚光灯适合: 圆形进度条、色轮渐变也能用在 Pen 上不只是 BrushPen 也支持 ShaderEffectconstpennewdrawing.Pen();pen.setStrokeWidth(10);pen.setShaderEffect(shaderEffect);canvas.attachPen(pen);canvas.drawLine(0,0,300,200);// 渐变色的线条canvas.detachPen();一条从红到蓝渐变的线是不是很酷阴影给文字加立体感ShadowLayer可以给绘制内容加阴影。不过目前只在绘制文字时生效图形暂时不支持。import{common2D,drawing}fromkit.ArkGraphics2D;// 创建阴影层模糊半径、x偏移、y偏移、颜色letcolor:common2D.Color{alpha:0xFF,red:0x00,green:0x00,blue:0x00};letshadowLayerdrawing.ShadowLayer.create(3,-3,3,color);constbrushnewdrawing.Brush();brush.setShadowLayer(shadowLayer);canvas.attachBrush(brush);// 在这里绘制文字...canvas.detachBrush();create的四个参数blurRadius阴影的模糊半径值越大阴影越散x阴影在 x 方向的偏移正值向右负值向左y阴影在 y 方向的偏移正值向下负值向上color阴影的颜色比如你想做一个文字投影效果create(5, 2, 2, 黑色)就是向右下方偏移 2 像素、模糊半径 5 的黑色阴影。混合模式颜色叠加的魔法当两个图形重叠时重叠区域的颜色怎么算这就是混合模式BlendMode决定的。brush.setBlendMode(drawing.BlendMode.SRC_OVER);// 默认模式SRC_OVER是默认模式——后画的盖在先画的上面。其他常见的混合模式还有SRC只显示后画的忽略先画的DST_OVER后画的在先画的下面SRC_IN只显示后画的和先画的重叠部分用后画的颜色DST_IN只显示重叠部分用先画的颜色MULTIPLY正片叠底颜色相乘重叠区域变暗SCREEN滤色重叠区域变亮混合模式在做图层特效时很有用。比如你想做一个叠加效果就用MULTIPLY想做发光效果就用SCREEN。颜色滤波器调整颜色ColorFilter可以对颜色做变换比如转灰度、调色相等letcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();brush.setColorFilter(colorFilter);ColorFilter提供了多种创建方式createSRGBGammaToLinear()sRGB gamma 转线性createLinearToSRGBGamma()线性转 sRGB gammacreateFromMatrix(colorMatrix)自定义颜色矩阵和 effectKit 的 setColorMatrix 类似颜色滤波器会作用在所有绘制的颜色上相当于给整个画面加了一层颜色滤镜。图像滤波器模糊和锐化ImageFilter可以对绘制结果做图像处理比如模糊letimageFilterdrawing.ImageFilter.createBlur(5,5,drawing.TileMode.CLAMP,null);brush.setImageFilter(imageFilter);和effectKit的 blur 不同这里的模糊是实时的——每次绘制都会应用。适合做毛玻璃效果的 UI 元素。Pen 也支持 ImageFilterletcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();letimgFilterdrawing.ImageFilter.createFromColorFilter(colorFilter);pen.setImageFilter(imgFilter);完整示例渐变色卡片来一个实际的例子——画一个带渐变背景和圆角的卡片import{RenderNode}fromkit.ArkUI;import{common2D,drawing}fromkit.ArkGraphics2D;classCardRenderNodeextendsRenderNode{draw(context:DrawContext){constcanvascontext.canvas;// 渐变背景从左上到右下的蓝紫渐变constbrushnewdrawing.Brush();constgradientdrawing.ShaderEffect.createLinearGradient({x:0,y:0},{x:300,y:200},[0xFF6200EE,0xFFBB86FC],drawing.TileMode.CLAMP);brush.setShaderEffect(gradient);brush.setAntiAlias(true);canvas.attachBrush(brush);// 画圆角矩形constroundRectnewdrawing.RoundRect({left:20,top:20,right:320,bottom:220},16,16);canvas.drawRoundRect(roundRect);canvas.detachBrush();}}这段代码画了一个从深紫到浅紫渐变的圆角卡片。渐变 圆角 抗锯齿三者组合起来就已经很好看了。几个实用技巧1. ShaderEffect 设为 null 可以清除brush.setShaderEffect(null);// 清除渐变回到纯色模式Brush 和 Pen 的所有设置方法都支持传null来清除效果setShaderEffect、setColorFilter、setImageFilter、setShadowLayer、setPathEffect。2. 拷贝构造可以复用样式如果你要画很多相同样式的图形可以用拷贝构造函数避免重复设置constbrushnewdrawing.Brush();brush.setColor(255,255,0,0);brush.setAntiAlias(true);// 拷贝一份两个 Brush 样式一样constbrush2newdrawing.Brush(brush);Pen 也一样new drawing.Pen(pen)。3. 渐变坐标是绝对像素createLinearGradient的起点和终点用的是画布上的绝对坐标不是相对坐标。如果你画了一个矩形从 (100, 100) 到 (400, 300)渐变的起点终点也要在这个范围内才有意义。小结Brush 和 Pen 的进阶功能功能BrushPen说明抗锯齿setAntiAliassetAntiAlias让边缘更平滑透明度setAlphasetAlpha0-255渐变色setShaderEffectsetShaderEffect线性/径向/扫描阴影setShadowLayersetShadowLayer仅文字生效混合模式setBlendMode-颜色叠加方式颜色滤波setColorFiltersetColorFilter颜色变换图像滤波setImageFiltersetImageFilter模糊等效果路径效果-setPathEffect虚线等下一篇我们来看 Path路径——怎么画直线、曲线、贝塞尔曲线做出各种复杂的形状。
鸿蒙开发-想让绘制更好看?渐变、阴影和混合模式
上一篇我们学了 Canvas Brush Pen 的基础用法——画矩形、画圆、填颜色、描边。但如果你真的在做一个绘画 APP光有这些是不够的。你还需要渐变色、半透明、抗锯齿、阴影……今天我们来深入看看 Brush 和 Pen 的进阶功能。下面是 Brush 和 Pen 进阶功能的整体结构Brush / Pen 进阶功能抗锯齿 setAntiAlias透明度 setAlpha渐变色 setShaderEffect阴影 setShadowLayer混合模式 setBlendMode颜色滤波 setColorFilter图像滤波 setImageFilter线性渐变径向渐变扫描渐变抗锯齿让边缘更平滑你有没有注意过画一个圆的时候边缘可能会有锯齿感——就像一排阶梯一样。这是因为屏幕是由像素点组成的斜线和曲线在像素网格上不可能完美平滑。抗锯齿Anti-Aliasing的原理很简单在边缘处用半透明的像素做过渡让阶梯感变弱。Brush 和 Pen 都支持开启抗锯齿constbrushnewdrawing.Brush();brush.setAntiAlias(true);// 开启抗锯齿constpennewdrawing.Pen();pen.setAntiAlias(true);// 开启抗锯齿开启后图形的边缘会更平滑但可能会稍微模糊一点。一般情况下建议开启除非你在做像素画那种需要锐利边缘的风格。透明度做出层次感brush.setAlpha(128);// 半透明pen.setAlpha(64);// 更透明取值范围[0, 255]0 完全透明看不见255 完全不透明。透明度能做什么很多效果都离不开它半透明的色块叠加做出磨砂玻璃效果多层半透明图形叠加做出深度感淡入淡出动画通过动态改变 alpha 值渐变色不只是纯色纯色太平淡了用ShaderEffect可以做出渐变效果。ShaderEffect 支持三种渐变线性渐变从一个点到另一个点颜色平滑过渡constshaderEffectdrawing.ShaderEffect.createLinearGradient({x:0,y:0},// 起点{x:300,y:0},// 终点[0xFFFF0000,0xFF0000FF],// 红色到蓝色drawing.TileMode.CLAMP// 平铺模式);brush.setShaderEffect(shaderEffect);canvas.attachBrush(brush);canvas.drawRect(0,0,300,200);canvas.detachBrush();这段代码画了一个从左到右、红到蓝渐变的矩形。colors数组里放的是 32 位 ARGB 颜色值。格式是0xAARRGGBB比如0xFFFF0000是不透明的红色0xFF0000FF是不透明的蓝色。TileMode控制渐变超出范围后怎么处理CLAMP用边缘颜色填充剩余区域REPEAT重复渐变MIRROR镜像重复DECAL只在原始范围内渲染径向渐变从圆心向外扩散的渐变constshaderEffectdrawing.ShaderEffect.createRadialGradient({x:150,y:100},// 圆心100,// 半径[0xFFFF0000,0xFF00FF00],// 红色到绿色drawing.TileMode.CLAMP);brush.setShaderEffect(shaderEffect);这种渐变就像阳光从中心向外扩散中心是红色边缘是绿色。适合做按钮的发光效果或者背景的聚光灯效果。扫描渐变像雷达扫描一样绕着圆心旋转的渐变constshaderEffectdrawing.ShaderEffect.createSweepGradient({x:150,y:100},// 圆心[0xFFFF0000,0xFF0000FF,0xFF00FF00],// 红→蓝→绿drawing.TileMode.CLAMP,0,// 起始角度360// 结束角度);brush.setShaderEffect(shaderEffect);适合做圆形进度条、色轮选择器之类的 UI。面对三种渐变类型如何选择可以参考下面的流程单方向过渡从中心向外扩散绕中心旋转需要渐变效果渐变方向是什么?线性渐变 createLinearGradient径向渐变 createRadialGradient扫描渐变 createSweepGradient适合: 背景渐变、按钮适合: 发光效果、聚光灯适合: 圆形进度条、色轮渐变也能用在 Pen 上不只是 BrushPen 也支持 ShaderEffectconstpennewdrawing.Pen();pen.setStrokeWidth(10);pen.setShaderEffect(shaderEffect);canvas.attachPen(pen);canvas.drawLine(0,0,300,200);// 渐变色的线条canvas.detachPen();一条从红到蓝渐变的线是不是很酷阴影给文字加立体感ShadowLayer可以给绘制内容加阴影。不过目前只在绘制文字时生效图形暂时不支持。import{common2D,drawing}fromkit.ArkGraphics2D;// 创建阴影层模糊半径、x偏移、y偏移、颜色letcolor:common2D.Color{alpha:0xFF,red:0x00,green:0x00,blue:0x00};letshadowLayerdrawing.ShadowLayer.create(3,-3,3,color);constbrushnewdrawing.Brush();brush.setShadowLayer(shadowLayer);canvas.attachBrush(brush);// 在这里绘制文字...canvas.detachBrush();create的四个参数blurRadius阴影的模糊半径值越大阴影越散x阴影在 x 方向的偏移正值向右负值向左y阴影在 y 方向的偏移正值向下负值向上color阴影的颜色比如你想做一个文字投影效果create(5, 2, 2, 黑色)就是向右下方偏移 2 像素、模糊半径 5 的黑色阴影。混合模式颜色叠加的魔法当两个图形重叠时重叠区域的颜色怎么算这就是混合模式BlendMode决定的。brush.setBlendMode(drawing.BlendMode.SRC_OVER);// 默认模式SRC_OVER是默认模式——后画的盖在先画的上面。其他常见的混合模式还有SRC只显示后画的忽略先画的DST_OVER后画的在先画的下面SRC_IN只显示后画的和先画的重叠部分用后画的颜色DST_IN只显示重叠部分用先画的颜色MULTIPLY正片叠底颜色相乘重叠区域变暗SCREEN滤色重叠区域变亮混合模式在做图层特效时很有用。比如你想做一个叠加效果就用MULTIPLY想做发光效果就用SCREEN。颜色滤波器调整颜色ColorFilter可以对颜色做变换比如转灰度、调色相等letcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();brush.setColorFilter(colorFilter);ColorFilter提供了多种创建方式createSRGBGammaToLinear()sRGB gamma 转线性createLinearToSRGBGamma()线性转 sRGB gammacreateFromMatrix(colorMatrix)自定义颜色矩阵和 effectKit 的 setColorMatrix 类似颜色滤波器会作用在所有绘制的颜色上相当于给整个画面加了一层颜色滤镜。图像滤波器模糊和锐化ImageFilter可以对绘制结果做图像处理比如模糊letimageFilterdrawing.ImageFilter.createBlur(5,5,drawing.TileMode.CLAMP,null);brush.setImageFilter(imageFilter);和effectKit的 blur 不同这里的模糊是实时的——每次绘制都会应用。适合做毛玻璃效果的 UI 元素。Pen 也支持 ImageFilterletcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();letimgFilterdrawing.ImageFilter.createFromColorFilter(colorFilter);pen.setImageFilter(imgFilter);完整示例渐变色卡片来一个实际的例子——画一个带渐变背景和圆角的卡片import{RenderNode}fromkit.ArkUI;import{common2D,drawing}fromkit.ArkGraphics2D;classCardRenderNodeextendsRenderNode{draw(context:DrawContext){constcanvascontext.canvas;// 渐变背景从左上到右下的蓝紫渐变constbrushnewdrawing.Brush();constgradientdrawing.ShaderEffect.createLinearGradient({x:0,y:0},{x:300,y:200},[0xFF6200EE,0xFFBB86FC],drawing.TileMode.CLAMP);brush.setShaderEffect(gradient);brush.setAntiAlias(true);canvas.attachBrush(brush);// 画圆角矩形constroundRectnewdrawing.RoundRect({left:20,top:20,right:320,bottom:220},16,16);canvas.drawRoundRect(roundRect);canvas.detachBrush();}}这段代码画了一个从深紫到浅紫渐变的圆角卡片。渐变 圆角 抗锯齿三者组合起来就已经很好看了。几个实用技巧1. ShaderEffect 设为 null 可以清除brush.setShaderEffect(null);// 清除渐变回到纯色模式Brush 和 Pen 的所有设置方法都支持传null来清除效果setShaderEffect、setColorFilter、setImageFilter、setShadowLayer、setPathEffect。2. 拷贝构造可以复用样式如果你要画很多相同样式的图形可以用拷贝构造函数避免重复设置constbrushnewdrawing.Brush();brush.setColor(255,255,0,0);brush.setAntiAlias(true);// 拷贝一份两个 Brush 样式一样constbrush2newdrawing.Brush(brush);Pen 也一样new drawing.Pen(pen)。3. 渐变坐标是绝对像素createLinearGradient的起点和终点用的是画布上的绝对坐标不是相对坐标。如果你画了一个矩形从 (100, 100) 到 (400, 300)渐变的起点终点也要在这个范围内才有意义。小结Brush 和 Pen 的进阶功能功能BrushPen说明抗锯齿setAntiAliassetAntiAlias让边缘更平滑透明度setAlphasetAlpha0-255渐变色setShaderEffectsetShaderEffect线性/径向/扫描阴影setShadowLayersetShadowLayer仅文字生效混合模式setBlendMode-颜色叠加方式颜色滤波setColorFiltersetColorFilter颜色变换图像滤波setImageFiltersetImageFilter模糊等效果路径效果-setPathEffect虚线等下一篇我们来看 Path路径——怎么画直线、曲线、贝塞尔曲线做出各种复杂的形状。