2312skia,13画布包入门
画矶包快速入门
CanvasKit是用比canvasAPI更高级功能集的Skia来绘画元素到canvas中的wasm模块.
最小应用
此例是个最小Canvaskit应用,它为一帧绘画一个圆角矩形.从unpkg.com中提取wasm二进制文件,但你也可自己构建和管理它.
<canvas id=foo width=300 height=300></canvas>
<script type="text/Js"src="https://unpkg.com/canvaskit-wasm@0.19.0/bin/canvaskit.js"></script>
<script type="text/Js">const ckLoaded = CanvasKitInit({locateFile: (file) => 'https://unpkg.com/canvaskit-wasm@0.19.0/bin/'+file});ckLoaded.then((CanvasKit) => {const surface = CanvasKit.MakeCanvasSurface('foo');const paint = new CanvasKit.Paint();paint.setColor(CanvasKit.Color4f(0.9, 0, 0, 1.0));paint.setStyle(CanvasKit.PaintStyle.Stroke);paint.setAntiAlias(true);const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(10, 60, 210, 260), 25, 15);function draw(canvas) {canvas.clear(CanvasKit.WHITE);canvas.drawRRect(rr, paint);}surface.drawOnce(draw);});
</script>
分解为几个部分来解释:
<canvas id=foo width=300 height=300></canvas>
创建CanvasKit要绘画的画布.该元素控制绘图缓冲的宽度和高度,css风格控制绘画到这些像素后应用的缩放.
尽管使用了canvas元素,但CanvasKit并没有调用HTML的canvas自己的绘画方法.它使用此canvas元素,来取WebGL2环境,并用编译为WebAssembly的C++代码来绘图,然后在每帧结束时向GPU发送命令.
<script type="text/Js"src="https://unpkg.com/canvaskit-wasm@0.19.0/bin/canvaskit.js"></script>
和
const ckLoaded = CanvasKitInit({locateFile: (file) => 'https://unpkg.com/canvaskit-wasm@0.19.0/bin/'+file});
ckLoaded.then((CanvasKit) => {
分别加载canvaskit助手js和wasm二进制文件.CanvasKitInit接受一个一般叫CanvasKit的a函数函数,a允许你更改它试查找canvaskit.wasm的路径,并返回一个用加载模块解析的promise.
const surface = CanvasKit.MakeCanvasSurface('foo');
创建与上述HTMLcanvas元素关联的Surface.默认硬件加速,但可调用MakeSWCanvasSurface来覆盖.MakeCanvasSurface也可指定替代颜色空间或gl属性.
const paint = new CanvasKit.Paint();
paint.setColor(CanvasKit.Color4f(0.9, 0, 0, 1.0));
paint.setStyle(CanvasKit.PaintStyle.Stroke);
paint.setAntiAlias(true);
const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(10, 60, 210, 260), 25, 15);
创建绘画,描述如何在canvaskit中填充或描边,矩形,路径,文本和其他几何图形.rr是一个在X轴上圆角半径为25,在y轴上圆角半径为15个像素的圆角矩形.
function draw(canvas) {canvas.clear(CanvasKit.WHITE);canvas.drawRRect(rr, paint);
}
定义绘画帧的函数.它提供了一个在上面绘画的Canvas对象.一个用来清理整个画布,另一个用上面的画笔绘画圆形矩形.
还删除了画笔对象.必须删除使用new或以make为前缀的方法创建的CanvasKit对象,才能释放wasm内存.Js的GC不会自动处理它.
rr只是一个不是用new创建的数组,也不指向WASM内存,因此不必对它调用delete.
surface.drawOnce(draw);
paint.delete()
给绘图函数提交调用并刷新表面的surface.drawOnce.刷新后,Skia处理并批发送WebGL命令,这样,在屏幕上出现可见更改.
基本绘画循环
如果要在画布上每一帧,都重画该怎么办?此例像90年代的屏幕保护程序一样,反弹一个圆角矩形.
ckLoaded.then((CanvasKit) => {const surface = CanvasKit.MakeCanvasSurface('foo2');const paint = new CanvasKit.Paint();paint.setColor(CanvasKit.Color4f(0.9, 0, 0, 1.0));paint.setStyle(CanvasKit.PaintStyle.Stroke);paint.setAntiAlias(true);//`const rr=CanvasKit.RRectXY(CanvasKit.LTRBRect(10,60,210,260),25,15);`const w = 100; //矩形的大小const h = 60;let x = 10; //左上角的初始位置.let y = 60;let dirX = 1; //盒子总是在`四个对角线方向`之一上,按`恒定`速度移动let dirY = 1;function drawFrame(canvas) {//检查边界if (x < 0 || x+w > 300) {dirX *= -1; //撞击侧壁时反转X方向}if (y < 0 || y+h > 300) {dirY *= -1; //撞击顶壁和底壁时反转Y方向}//移动x += dirX;y += dirY;canvas.clear(CanvasKit.WHITE);const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(x, y, x+w, y+h), 25, 15);canvas.drawRRect(rr, paint);surface.requestAnimationFrame(drawFrame);}surface.requestAnimationFrame(drawFrame);
});
主要区别在,在绘画每一帧前,定义了一个要调用的函数,并把它传递给surface.requestAnimationFrame(drawFrame);,传递该回调给画布,并刷新.
function drawFrame(canvas) {canvas.clear(CanvasKit.WHITE);//在此更新和绘画框架的代码surface.requestAnimationFrame(drawFrame);
}
surface.requestAnimationFrame(drawFrame);
创建函数作为主绘图循环.每次渲染一帧(浏览器一般以60fps为目标)时,都会调用该函数,用白色清理画布,重画圆角矩形,然后调用surface.requestAnimationFrame(drawFrame)来注册要在下一帧前再次调用的函数.
surface.requestAnimationFrame(drawFrame)把window.requestAnimationFrame与surface.flush()``组合在一起,并同样方法使用.
如果应用仅因鼠标事件而有可见更改,请不要在drawFrame函数末尾调用surface.requestAnimationFrame.而仅在处理鼠标输入后调用它.
变形文本
CanvasKit在HTMLCanvasAPI上提供的最大功能之一是变形段落.要用它,提供字体文件,并在CanvasKit和字体文件都准备就绪时,使用Promise.all运行代码.
const loadFont = fetch('https://storage.googleapis.com/skia-cdn/misc/Roboto-Regular.ttf').then((response) => response.arrayBuffer());
Promise.all([ckLoaded, loadFont]).then(([CanvasKit, robotoData]) => {const surface = CanvasKit.MakeCanvasSurface('foo3');const canvas = surface.getCanvas();canvas.clear(CanvasKit.Color4f(0.9, 0.9, 0.9, 1.0));const fontMgr = CanvasKit.FontMgr.FromData([robotoData]);const paraStyle = new CanvasKit.ParagraphStyle({textStyle: {color: CanvasKit.BLACK,fontFamilies: ['Roboto'],fontSize: 28,},textAlign: CanvasKit.TextAlign.Left,});const text = 'Any sufficiently entrenched technology is indistinguishable from Js';const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);builder.addText(text);const paragraph = builder.build();paragraph.layout(290); //换行文本时使用的宽度(以像素为单位)canvas.drawParagraph(paragraph, 10, 10);surface.flush();
});
const fontMgr = CanvasKit.FontMgr.FromData([robotoData]);
在CanvasKit中,创建一个按名提供的包含字体的各种文本工具.如果需要,可在此语句中加载多个字体.
const paraStyle = new CanvasKit.ParagraphStyle({textStyle: {color: CanvasKit.BLACK,fontFamilies: ['Roboto'],fontSize: 28,},textAlign: CanvasKit.TextAlign.Left,
});
指定文本风格及字体名,机器从字体管理器中取它.可指定(color)或(foregroundColor和backgroundColor)以获得高亮.
有关API的完整文档,请查看npm包的types/子目录或Skia仓库中的ts定义.
const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
builder.addText(text);
const paragraph = builder.build();
接着,用风格创建ParagraphBuilder,添加一些文本,并使用build()完成它.或,可在段落中使用多个TextStyles.
const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
builder.addText(text1);
const boldTextStyle = CanvasKit.TextStyle({color: CanvasKit.BLACK,fontFamilies: ['Roboto'],fontSize: 28,fontStyle: {'weight': CanvasKit.FontWeight.Bold},
})
builder.pushStyle(boldTextStyle);
builder.addText(text2);
builder.pop();
builder.addText(text3);
const paragraph = builder.build();
最后,布局段落,即换行文本到指定宽度,然后用
paragraph.layout(290); //换行文本时使用的宽度(以像素为单位)
canvas.drawParagraph(paragraph, 10, 10); //段落左上角的(x,y)位置.
动画
Skia现在为从AfterEffects继承的Bodymovin插件的JSON动画提供了一个高性能,安全的本地播放器.可在包括安卓和iOS的Skia平台上使用.
该播放器旨在在创建当今广泛用来动画的Lottie播放器的基础上,为客户提高性能,功能集和平台凝聚力.是Bodymovin格式的忠实粉丝,并在可能时为Bodymovin/Lottie贡献.
示例JSON动画
Skia的动画代码入口可在Googlesource和GitHub上找到.该代码是Skia库的一部分,但也可作为单独的包提供这里及这里.
嵌入示例
1,可在此处找到用Skottie原生播放器的示例C代码.
2,可在此处找到取灵感的安卓应用代码.
3,在此嵌入Skottie到Viewer应用中的示例代码.
4,可按后面说明构建Viewer或SkottieAndroid应用.
相关文章:
2312skia,13画布包入门
画矶包快速入门 CanvasKit是用比canvasAPI更高级功能集的Skia来绘画元素到canvas中的wasm模块. 最小应用 此例是个最小Canvaskit应用,它为一帧绘画一个圆角矩形.从unpkg.com中提取wasm二进制文件,但你也可自己构建和管理它. <canvas idfoo width300 height300></c…...
【网络安全技术】消息认证技术
一、哈希函数 1.安全性质 1)抗第一原像攻击(Preimage Resistance) 给定哈希后的值,很难找到哈希前的原消息。这很好理解,需要哈希函数具有单向性。 一个简单的例子就是密码存储系统,用户登录服务器需要…...
智慧安防三大信息技术:云计算、大数据及人工智能在视频监控EasyCVR中的应用
说到三大信息技术大家都很清楚,指的是云计算、大数据和人工智能,在人工智能(AI)快速发展的当下,例如常见的大数据分析、人工智能芯片生产的智能机器人等等,在工作、生活、教育、金融、科技、工业、农业、娱…...
接口测试基础知识
一、接口测试简介 什么是接口测试? 接口测试是测试系统组件间接口的一种测试,主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。 测试的重点: 检查数据的交换,传递和控制管理过程;检查系统间的相互…...
C++多线程之通过成员函数作为线程入口
说明: 通过类里面的函数作为线程入口,我个人难理解的地方在于给线程传递参数的时候,怎么找到Main函数。后面会做分析。 首先创建类:创建MyThread类,其中公有函数Main作为入口。这个类的传教比较简单,成员…...
word、excel文件转PDF(documents4j方式,简单)
1 documents4j方式 引入pom <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.1.12</version></dependency><dependency><groupId>com.documents4j</g…...
【Linux】:信号(三)捕捉
信号捕捉 一.sigaction1.基本使用2.sa_mask字段 二.可重入函数三.volatile四.SIGCHLD信号 承接上文 果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信…...
数据结构 / 队列 / 循环队列 / 概念
1. 定义 为充分利用向量空间,克服假溢出现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。循环队列是把顺序队列首尾相连,把存储…...
elasticsearch 内网下如何以离线的方式上传任意的huggingFace上的NLP模型(国内闭坑指南)
es自2020年的8.x版本以来,就提供了机器学习的能力。我们可以使用es官方提供的工具eland,将hugging face上的NLP模型,上传到es集群中。利用es的机器学习模块,来运维部署管理模型。配合es的管道处理,来更加便捷的处理数据…...
vue中中的动画组件使用及如何在vue中使用animate.css
“< Transition >” 是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发: 由 v-if 所触发的切换由 v-show 所触…...
MATLAB 模型参考自适应控制 - Model Reference Adaptive Control
系列文章目录 文章目录 系列文章目录前言一、参考模型二、扰动与不确定性模型三、直接 MRAC名义模型参数更新间接 MRAC估计器模型和控制器增益参数更新学习修正参考文献 前言 模型参考自适应控制模块计算控制动作,使不确定的受控系统跟踪给定参考被控对象模型的行为…...
【如何用批处理文件实现自动编译Keil工程和C# Visual Studio工程】
如何用批处理文件实现自动编译Keil工程和C# Visual Studio工程 写个Bat 批处理文件,现自动编译Keil工程和C# Visual Studio工程。这样可以结合Python 实现复杂的操作。 编译Keil工程: echo off set UVC:\Keil_v5\UV4\UV4.exe set UV_PRO_PATHD:\worksp…...
大模型的实践应用11-“书生”通用大模型的搭建与模型代码详细介绍,以及快速使用方法
大家好,我是微学AI,今天给大家介绍一下大模型的实践应用11-“书生”通用大模型的搭建与模型代码详细介绍,以及快速使用方法。“书生” 通用大模型是上海人工智能实验室研制的大模型,并且已经开源了“书生浦语”大模型70亿参数的轻量级版本InternLM-7B。InternLM-7B模型主要…...
【开发PaaS】基于Postgresql的开发平台Supabase
Supadase是开源的。我们选择可扩展的开源工具,使其易于使用。 Supadase不是Firebase的1对1映射。虽然我们正在构建Firebase提供的许多功能,但我们不会以同样的方式进行: 我们的技术选择大不相同;我们使用的一切都是开源的&#…...
前端开启gzip优化页面加载速度
生成gizp的打包资源,可以优化页面加载速度 打包的时候开启gzip可以很大程度减少包的大小,页面大小可以变为原来的30%甚至更小,非常适合线上部署, 但还记得需要服务端支持 1、前端配置compression-webpack-plugin 先安装:npm install compres…...
用Java写一个俄罗斯方块
目录 游戏规则 小方块类:Cell 七种图形类:I、J、L、O、S、T、Z J L O S T Z 俄罗斯方块游戏主类:Tetris 效果展示 游戏规则 由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,使它…...
应用于智慧金融的AI边缘计算盒子+AI算法软硬一体化方案
传统金融营业厅存在运营管理模式落后、资源投放不平衡、从业人员培训效果不达预期、客户体验割裂等普遍现象; 部署英码数字金融解决方案,将助力企业从传统金融模式快速向数字金融模式转变,可针对每一个客户定制个性化“一对一”服务ÿ…...
目标检测——Faster R-CNN算法解读
论文:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks 作者:Shaoqing Ren, Kaiming He, Ross Girshick, and Jian Sun 链接:https://arxiv.org/abs/1506.01497 代码:https://github.com/rbgirsh…...
Wireshark (一)安装入门 —— 软件介绍
文章目录 Wireshark是什么?为什么要使用Wireshark?相关网络分析工具软件对比 Wireshark是什么? Wireshark是一种开源网络协议分析器,它可以捕获和分析网络中传输的数据包。 用户可以使用Wireshark来诊断网络问题、了解网络协议的…...
Web框架与Django路由层
Web框架 一 web框架 Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能&…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
