【SkiaSharp绘图12】SKCanvas方法详解(一)清空、裁切区域设置、连接矩阵、注释、弧与扇形、图集、九宫格绘图、圆

文章目录

  • SKCanvas 方法
    • Clear 清空
    • ClipPath/ClipRect/ClipRegion/ClipRoundRect 设置裁切区域
    • Concat 连接矩阵
    • DrawAnnotation绘制注释
    • DrawArc绘制椭圆弧、扇形
    • DrawAtlas绘制图集(一个图像、多个区域、多个缩放、一次绘制)
    • DrawBitmap绘制图像
    • DrawBitmapNinePatch九宫格绘图
    • DrawBitmapLattice 格子绘图
    • DrawCircle 绘制圆

SKCanvas 方法

Clear 清空

public void Clear ();//清空为#00000000
public void Clear (SkiaSharp.SKColor color);
public void Clear (SkiaSharp.SKColorF color);

用指定颜色替换当前裁切区域的所有像素颜色。

ClipPath/ClipRect/ClipRegion/ClipRoundRect 设置裁切区域

public void ClipPath (SkiaSharp.SKPath path, SkiaSharp.SKClipOperation operation = SkiaSharp.SKClipOperation.Intersect, bool antialias = false);
public void ClipRect (SkiaSharp.SKRect rect, SkiaSharp.SKClipOperation operation = SkiaSharp.SKClipOperation.Intersect, bool antialias = false);
public void ClipRegion (SkiaSharp.SKRegion region, SkiaSharp.SKClipOperation operation = SkiaSharp.SKClipOperation.Intersect);
public void ClipRegion (SkiaSharp.SKRegion region, SkiaSharp.SKClipOperation operation = SkiaSharp.SKClipOperation.Intersect);

使用指定的路径修改当前裁切区域。
SKClipOperation

说明
Difference从原区域减去指定区域
Intersect原区域与指定区域的交集
var canvas = e.Surface.Canvas;
var info = e.Info;using(var paint=new SKPaint())
{paint.TextSize = 18;paint.Color = SKColors.Red;var path = new SKPath();path.AddCircle(200, 200, 100);canvas.Save();canvas.ClipPath(path);canvas.Clear(SKColors.LightGreen);canvas.DrawText($"ClipPath", 150, 200, paint);canvas.Restore();canvas.Save();canvas.ClipRect(new SKRect(250, 100, 550, 300));canvas.Clear(SKColors.LightBlue);canvas.DrawText($"ClipRect", 350, 200, paint);canvas.Restore();canvas.Save();canvas.ClipRegion(new SKRegion(new SKRectI(100, 280, 300, 450)));canvas.Clear(SKColors.LightPink);canvas.DrawText($"ClipRegion", 120, 400, paint);canvas.Restore();canvas.ClipRoundRect(new SKRoundRect(new SKRect(350, 350, 600, 600), 50));canvas.Clear(SKColors.LightCyan);canvas.DrawText($"ClipRoundRect", 400, 450, paint);
}

分配使用ClipPath、ClipRect、ClipRegion、ClipRoundRect修改裁切区域。
注意,还原裁切区域需要使用SKCanvas的Save()与Restore()方法。
裁切区域

Concat 连接矩阵

public void Concat (ref SkiaSharp.SKMatrix m);

原SKCanvas的矩阵与指定合并。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{paint.TextSize = 18;paint.Color = SKColors.LightGreen;paint.IsStroke = true;var rect = new SKRect(50, 50, 250, 150);canvas.DrawRect(rect, paint);canvas.DrawText($"TotalMatrix:{string.Join(",", canvas.TotalMatrix.Values)}", 400, 100, paint);var matrixA = SKMatrix.CreateTranslation(50, 50);canvas.Concat(ref matrixA);canvas.DrawRect(rect, paint);canvas.DrawText($"TotalMatrix:{string.Join(",", canvas.TotalMatrix.Values)}", 400, 100, paint);canvas.Concat(ref matrixA);canvas.DrawRect(rect, paint);canvas.DrawText($"TotalMatrix:{string.Join(",", canvas.TotalMatrix.Values)}", 400, 100, paint);
}

Concat

DrawAnnotation绘制注释

public void DrawAnnotation (SkiaSharp.SKRect rect, string key, SkiaSharp.SKData value);

绘制注释。(只在某些SKCanvas中有效,如PDF doc生成的SKCanvas)
实测使用CreatePdf也没成功。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);using (var stream = File.OpenWrite(@"Images\test.pdf"))
using (var doc = SKDocument.CreatePdf(stream,72))
using (var pdfCanvas = doc.BeginPage(600, 600))
using (var paint = new SKPaint())
{paint.TextSize = 18;paint.Color = SKColors.LightGreen;paint.IsStroke = true;var rect = new SKRect(50, 50, 250, 150);pdfCanvas.DrawRect(rect, paint);using (MemoryStream byteStream = new MemoryStream(Encoding.UTF8.GetBytes("This is rect annotation"))){// 重置流的位置byteStream.Position = 0;using (var annoData = SKData.Create(byteStream)){//生成的PDF没看到pdfCanvas.DrawAnnotation(rect, "Rect Anno", annoData);}}pdfCanvas.DrawText($"Test DrawAnnotation", 20, 200, paint);doc.EndPage();doc.Close();
}

DrawArc绘制椭圆弧、扇形

public void DrawArc (SkiaSharp.SKRect oval, float startAngle, float sweepAngle, bool useCenter, SkiaSharp.SKPaint paint);
参数说明
oval确定弧所在椭圆的矩形
startAngle起始角度
sweepAngle持续角度(正数:顺时针,负数:逆时针)
useCentertrue:扇形,false:弧
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);using (var paint = new SKPaint())
{paint.TextSize = 18;paint.Color = SKColors.Red;paint.IsStroke = true;paint.StrokeWidth = 5;var rect = new SKRect(50, 50, 250, 150);//顺时针120度canvas.DrawArc(rect, 0, 120, false, paint);paint.Color = SKColors.Green;//逆时针120度canvas.DrawArc(rect, 0, -120, false, paint);paint.Color = SKColors.Blue;//扇形canvas.DrawArc(rect, 120, 120, true, paint);
}

分三段绘制,其中一段为扇形。
DrawArc

DrawAtlas绘制图集(一个图像、多个区域、多个缩放、一次绘制)

public void DrawAtlas (SkiaSharp.SKImage atlas, SkiaSharp.SKRect[] sprites, SkiaSharp.SKRotationScaleMatrix[] transforms, SkiaSharp.SKPaint paint);
public void DrawAtlas (SkiaSharp.SKImage atlas, SkiaSharp.SKRect[] sprites, SkiaSharp.SKRotationScaleMatrix[] transforms, SkiaSharp.SKColor[] colors, SkiaSharp.SKBlendMode mode, SkiaSharp.SKPaint paint);
public void DrawAtlas (SkiaSharp.SKImage atlas, SkiaSharp.SKRect[] sprites, SkiaSharp.SKRotationScaleMatrix[] transforms, SkiaSharp.SKColor[] colors, SkiaSharp.SKBlendMode mode, SkiaSharp.SKRect cullRect, SkiaSharp.SKPaint paint);

通过指定多个原图像矩形区域和多个缩放矩阵,将一张图像一次性绘制在画布上。

  1. 提高性能:减少绘制调用的次数可以显著提高渲染性能,尤其是在需要同时绘制大量小图像时。
  2. 降低内存开销:使用一个大图集而不是多个小图像可以减少纹理切换次数,降低 GPU 内存开销。
  3. 简化管理:将多个图像集中在一个图集中便于管理和使用,特别是在游戏开发或需要大量图形资源的应用中。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);using (var paint = new SKPaint())
{paint.Color = SKColors.Red;if (skImg == null) skImg = SKImage.FromBitmap(SKBitmap.Decode(@"Images\wall.png"));const int count = 100;var srcRects = new List<SKRect>();var rotScaleMatrix = new List<SKRotationScaleMatrix>();var offsetY = 0;var offsetX = 0;for (int i = 0; i < count; i++){srcRects.Add(SKRect.Create(skImg.Width, skImg.Height));rotScaleMatrix.Add(SKRotationScaleMatrix.CreateTranslation(offsetX, offsetY));offsetX += skImg.Width;if (offsetX > info.Width - skImg.Width){offsetX = 0;offsetY += skImg.Height;}}//模拟平铺canvas.DrawAtlas(skImg,srcRects.ToArray(), rotScaleMatrix.ToArray(), paint);
}

模拟平铺的方式,多次绘制同一张图像。
DrawAtlas

DrawBitmap绘制图像

public void DrawBitmap (SkiaSharp.SKBitmap bitmap, SkiaSharp.SKPoint p, SkiaSharp.SKPaint paint = default);
public void DrawBitmap (SkiaSharp.SKBitmap bitmap, SkiaSharp.SKRect dest, SkiaSharp.SKPaint paint = default);
public void DrawBitmap (SkiaSharp.SKBitmap bitmap, SkiaSharp.SKRect source, SkiaSharp.SKRect dest, SkiaSharp.SKPaint paint = default);
public void DrawBitmap (SkiaSharp.SKBitmap bitmap, float x, float y, SkiaSharp.SKPaint paint = default);

将图像绘制到指定区域。(注意,先缩放或裁切到合适大小再绘制,比直接绘制时缩放,效率会高些)。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);using (var paint = new SKPaint())
{paint.Color = SKColors.Red;if (skBmp == null){skBmp = SKBitmap.Decode(@"Images\AIWoman.png");skBmp = skBmp.Resize(new SKSizeI(400, 400), SKFilterQuality.High);}canvas.DrawBitmap(skBmp, new SKPoint(20, 20), paint);canvas.DrawBitmap(skBmp, new SKRect(440, 20, 440 + 300, 20 + 300), paint);var srcRect = new SKRect(40, 40, 360, 360);canvas.DrawBitmap(skBmp, srcRect, new SKRect(20, 440, 20 + srcRect.Width, 480 + srcRect.Height), paint);
}

DrawBitmap

DrawBitmapNinePatch九宫格绘图

public void DrawBitmapNinePatch (SkiaSharp.SKBitmap bitmap, SkiaSharp.SKRectI center, SkiaSharp.SKRect dst, SkiaSharp.SKPaint paint = default);

以九宫格形式绘制一幅图像,通过指定中心矩形来局部缩放图像。九宫格中,四个角保持不拉伸,其中的随着目标矩形大小拉伸。

 /// <summary>/// 绘制刻度和根据中心矩形绘制井字形/// </summary>/// <param name="bmp"></param>/// <param name="centerRectI"></param>/// <returns></returns>private SKBitmap DrawLines(SKBitmap bmp,SKRectI centerRectI){var cloneBmp = bmp.Copy();using (var paint = new SKPaint())using (var sCanvas = new SKCanvas(cloneBmp)){paint.Color = SKColors.Red;paint.IsStroke = true;for (var x = 0; x < cloneBmp.Width; x += 10){sCanvas.DrawLine(x, 0, x, 10, paint);}sCanvas.DrawLine(0, 10, cloneBmp.Width, 10, paint);for (var y = 0; y < cloneBmp.Height; y += 10){sCanvas.DrawLine(0, y, 10, y, paint);}sCanvas.DrawLine(10, 0, 10, cloneBmp.Height, paint);sCanvas.DrawLine(0, centerRectI.Top, cloneBmp.Width, centerRectI.Top, paint);sCanvas.DrawLine(0, centerRectI.Bottom, cloneBmp.Width, centerRectI.Bottom, paint);sCanvas.DrawLine(centerRectI.Left, 0, centerRectI.Left, cloneBmp.Height, paint);sCanvas.DrawLine(centerRectI.Right, 0, centerRectI.Right, cloneBmp.Height, paint);}return cloneBmp;}
public void OnPaintSurface12_07(object sender, SkiaSharp.Views.Desktop.SKPaintGLSurfaceEventArgs e)
{var canvas = e.Surface.Canvas;var info = e.Info;canvas.Clear(SKColors.White);//中间矩形SKRectI centerRectI = SKRectI.Empty;// 定义绘制目标矩形var dstRect = new SKRect(0, 0, 400, 400);using (var paint = new SKPaint()){paint.Color = SKColors.Red;paint.TextSize = 16;var skSizeI = new SKSizeI(200, 200);centerRectI = new SKRectI(10, 10, 60, 60);if (skBmp == null){skBmp = SKBitmap.Decode(@"Images\AIWoman.png");skBmp = skBmp.Resize(new SKSizeI(200, 200), SKFilterQuality.High);                    }                var bmpA= DrawLines(skBmp, centerRectI);canvas.DrawBitmapNinePatch(bmpA, centerRectI, dstRect, paint);canvas.DrawText($"Center Rect:{centerRectI}", 0, 430, paint);bmpA.Dispose();centerRectI =new SKRectI(skBmp.Width/3,skBmp.Height/3,skBmp.Width*2/3,skBmp.Height*2/3);var bmpB= DrawLines(skBmp, centerRectI);dstRect = new SKRect(410, 0, 810, 400);canvas.DrawBitmapNinePatch(bmpB, centerRectI, dstRect, paint);canvas.DrawText($"Center Rect:{centerRectI}", 410, 430, paint);bmpB.Dispose();}
}

定义两个不同的中心矩形,对同一幅图进行九宫格缩放,观察它们之间的不同。
DrawBitmapNinePatch

DrawBitmapLattice 格子绘图

public void DrawBitmapLattice (SkiaSharp.SKBitmap bitmap, SkiaSharp.SKLattice lattice, SkiaSharp.SKRect dst, SkiaSharp.SKPaint paint = default);
public void DrawBitmapLattice (SkiaSharp.SKBitmap bitmap, int[] xDivs, int[] yDivs, SkiaSharp.SKRect dst, SkiaSharp.SKPaint paint = default);

按函数原型是对九宫格绘图的扩展,可自定义长*宽个格子,也可指定哪一排或哪一列的缩放、以及哪一格是透明还是颜色填色。但实际应用中,相关的参数并不一定按实际指定的效果执行。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);if (skBmp == null)
{skBmp = SKBitmap.Decode(@"Images\AIWoman.png");skBmp = skBmp.Resize(new SKSizeI(200, 200), SKFilterQuality.High);
}var qtrWidth = skBmp.Width / 4;
// 定义 Lattice
var lattice = new SKLattice
{XDivs = new int[] { qtrWidth, qtrWidth * 2, qtrWidth * 3 }, // X 方向上的分割位置YDivs = new int[] { skBmp.Height / 3, 2 * skBmp.Height / 3 }, // Y 方向上的分割位置RectTypes = new SKLatticeRectType[] // 定义每个网格的类型{SKLatticeRectType.FixedColor, SKLatticeRectType.Default, SKLatticeRectType.Default,SKLatticeRectType.FixedColor,SKLatticeRectType.FixedColor, SKLatticeRectType.Default, SKLatticeRectType.Default,SKLatticeRectType.FixedColor,SKLatticeRectType.FixedColor, SKLatticeRectType.Default, SKLatticeRectType.Default,SKLatticeRectType.FixedColor},Colors = new SKColor[]{SKColors.Red,     SKColors.Green,   SKColors.Blue,    SKColors.Yellow,  SKColors.Cyan,    SKColors.Magenta, SKColors.Orange,  SKColors.Purple,  SKColors.Gray,SKColors.Pink,SKColors.DarkBlue,SKColors.Gold}
};// 定义绘制目标矩形
var dstRect = new SKRect(0, 0, 300, 300);using (var paint = new SKPaint())
{paint.Color = SKColors.Red;using (var sCanvas = new SKCanvas(skBmp)){foreach (var x in lattice.XDivs){sCanvas.DrawLine(x, 0, x, skBmp.Height, paint);}foreach (var y in lattice.YDivs){sCanvas.DrawLine(0, y, skBmp.Width, y, paint);}}canvas.DrawBitmapLattice(skBmp, lattice, dstRect, paint);
}

按 4 * 3 格子对图像进行缩放绘制
在这里插入图片描述

DrawCircle 绘制圆

public void DrawCircle (SkiaSharp.SKPoint c, float radius, SkiaSharp.SKPaint paint);
public void DrawCircle (float cx, float cy, float radius, SkiaSharp.SKPaint paint);

绘制和填充圆。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);using(var paint=new SKPaint())
{paint.Style = SKPaintStyle.StrokeAndFill;paint.Color = SKColors.LightGreen;paint.TextSize = 18;//实心圆canvas.DrawCircle(150, 150, 100, paint);canvas.DrawText($"Fill Circle", 50, 280, paint);canvas.Translate(200, 0);paint.IsStroke = true;//空心圆canvas.DrawCircle(150, 150, 100, paint);canvas.DrawText($"Stroke Circle", 50, 280, paint);
}

绘制两个圆,一个填充,另一个只描边。
DrawCircle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/367610.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

停车场车牌识别计费系统,用Python如何实现?

关注星标&#xff0c;每天学习Python新技能 前段时间练习过的一个小项目&#xff0c;今天再看看&#xff0c;记录一下~ 项目结构 说明&#xff1a; datefile文件夹&#xff1a;保存车辆信息表的xlsx文件 file文件夹&#xff1a;保存图片文件夹。ic_launcher.jpg是窗体的右上角…

vector模拟实现【C++】

文章目录 全部的实现代码放在了文章末尾准备工作包含头文件定义命名空间和类类的成员变量 迭代器迭代器获取函数 构造函数默认构造使用n个值构造迭代器区间构造解决迭代器区间构造和用n个值构造的冲突拷贝构造 析构函数swap【交换函数】赋值运算符重载emptysize和capacityopera…

字符串知识点

API API和API帮助文档 API:目前是JDK中提供的各种功能的Java类。 这些类将底层的实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff0c;只需要学习这些类如何使用即可。 API帮助文档&#xff1a;帮助开发人员更好的使用API和查询API的一个工具。 String概…

【Linux】线程封装与互斥(万字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 C多线程的用法 对原生线程进行一次封装 理解pthread线程 Linux线程互斥 进程线程间的互斥相关背景概念 互斥量mutex 操作共享变量会有问题的售票…

eventloop 事件循环机制 (猜答案)

// eventloop 事件循环机制// console.log(555);setTimeout(() > {console.log(666);})let p new Promise((resolve,reject)>{// 同步执行console.log(111);resolve();});// promise 的回调函数是异步的微任务p.then(v > {console.log(222);}, r > {console.log(r…

解决ps暂存盘已满的问题

点击编辑->首选项->暂存盘 ps默认暂存盘使用的是c盘&#xff0c;我们改成d盘即可 然后重启ps

OpenSSL的一些使用案例

目录 一、介绍 二、基本使用 1、Shell &#xff08;1&#xff09;文件加解密 &#xff08;2&#xff09;生成密钥文件 2、API &#xff08;1&#xff09;md5sum &#xff08;2&#xff09;AES256加解密 一、介绍 本篇博客重点不是详细描述 OpenSSL 的用法&#xff0c;只…

snap和apt的区别简单了解

Linux中没有tree命令的时候提示安装的时候出现了两个命令&#xff0c;简单看了看两者有何区别&#xff08;一般用apt就可以了&#xff09;&#xff1a; sudo snap install tree 和 sudo apt install tree 这两个命令都是用来安装 tree 命令行工具的&#xff0c;但它们使用的是不…

antfu/ni 在 Windows 下的安装

问题 全局安装 ni 之后&#xff0c;第一次使用会有这个问题 解决 在 powershell 中输入 Remove-Item Alias:ni -Force -ErrorAction Ignore之后再次运行 ni Windows 11 下的 Powershell 环境配置 可以参考 https://github.com/antfu-collective/ni?tabreadme-ov-file#how …

SpringBoot源码阅读3-启动原理

SpringBootApplication public class DistApplication {public static void main(String[] args) {// 启动入口SpringApplication.run()SpringApplication.run(DistApplication.class, args);} }1、服务构建 这里"服务"指的是SpringApplication对象&#xff0c;服务…

【QT】概述|对象树模型|两种控件模式|信号和槽|lambda

目录 什么是QT 特点 QT程序 main函数 QT按钮 纯代码模式 图形化模式 对象树模型 信号和槽 连接与断开 自动连接 断开连接 信号的发射 lambda表达式 基本语法 捕获列表 Lambda表达式用于信号与槽的连接 例如 什么是QT Qt是一个跨平台的C图形用户界面应用…

WAF的新选择,雷池 SafeLine-安装动态防护使用指南

什么是 WAF WAF 是 Web Application Firewall 的缩写&#xff0c;也被称为 Web 应用防火墙。 区别于传统防火墙&#xff0c;WAF 工作在应用层&#xff0c;对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果&#xff0c;使其免于受到黑客的攻击&#xff1b; 通俗来讲&#…

【数据库】Oracle安装报错(win10安装oracle提示环境不满足最低要求)

目录 一、问题场景&#xff1a; 二、问题描述 三、原因分析&#xff1a; 四、解决方案&#xff1a; 一、问题场景&#xff1a; 安装Oracle数据库 二、问题描述 安装之前提示&#xff08; [INS-13001]环境不满足最低要求。 是否确实要继续? &#xff09; 如图所示&…

运维锅总浅析云原生DevOps工具

本文从Tekton与Kubevela、Jenkins、GitLab CI的区别与联系对常见的云原生DevOps工具进行对比分析&#xff0c;最后给出DevOps工具选型思路。希望对您有所帮助&#xff01; 一、DevOps简介 DevOps是一种结合了软件开发&#xff08;Development&#xff09;和IT运维&#xff08…

1、项目基础

1、系统架构图 2、项目业务组成 3、技术选型 3.1 前端 vue3 ts sass axios 3.2后端 spring-cloud系列 gateway openfeign spring-cloud-alibaba系列 nacos sentinel seata

开放式耳机怎么选?五大2024年口碑销量爆棚机型力荐!

在选购开放式耳机的时候&#xff0c;我们总会因为有太多的选择而陷入两难&#xff0c;又想要一个颜值比较高的&#xff0c;又想要同时兼顾性能还不错的&#xff0c;所以作为测评博主&#xff0c;今天我们就给大家带来自己的一些选购技巧和自己觉得还不错开放式耳机&#xff0c;…

TP8/6 子域名绑定应用

原www.xxx.com/admin改为admincms.xxx.com config/app.php

3d模型里地毯的材质怎么赋予?---模大狮模型网

在进行3D建模时&#xff0c;赋予地毯逼真的材质是营造现实感和增强场景氛围的重要步骤。模大狮将介绍在常见的3D建模软件中&#xff0c;如何有效地为地毯赋予各种材质&#xff0c;以及一些实用的技巧和注意事项。 一、选择合适的地毯材质 在3D建模中&#xff0c;地毯的材质选择…

uniapp实现可拖动悬浮按钮(最新版2024-7月)

此章主要介绍如何使用uniapp跨平台开发&#xff0c;实现悬浮按钮&#xff0c;移动端经常会有所这样的需求&#xff0c;那么功能如下&#xff1a; 1.圆圈悬浮球&#xff0c;上下左右靠边显示 2.可以界面任何拖动&#xff0c;不会超出界面 3.单击悬浮球的点击事件 效果&#xf…

C++ 和C#的差别

首先把眼睛瞪大&#xff0c;然后憋住一口气&#xff0c;读下去&#xff1a; 1、CPP 就是C plus plus的缩写&#xff0c;中国大陆的程序员圈子中通常被读做"C加加"&#xff0c;而西方的程序员通常读做"C plus plus"&#xff0c;它是一种使用非常广泛的计算…