当前位置: 首页 > news >正文

在Android上实现汉字笔顺动画效果——HanZiWriter

序,万般皆是命,半点不由人。

Hanzi Writer 是 javascript 免费开源库,根据汉字书写时按照笔画顺序的特征,可以播放正确笔画顺序的描边动画和练习测试。支持简体字和繁体字。可以让全球用户能够通过手绘模仿的方式来学习和练习书写汉字。

特点
  • 丰富性: 包含9000+个常用汉字的笔画数据,覆盖广泛。
  • 准确性: 笔画轨迹详细且精准,模拟真实书写体验。
  • 开放源代码: 全面免费,可自由使用和扩展,鼓励社区参与和贡献。
  • 易用性: 提供简洁的JSON格式数据,易于集成到各类开发环境中。
  • 跨平台兼容: 数据基于SVG标准,能在多种设备和浏览器上无缝运行。
  • 体积小:Hanzi Writer 库仅仅 30 kb (压缩后仅 9kb!), 所以添加它不会使网页体积增大。
  • 用处广泛:Hanzi Writer 使用 javascript, HTML5 and SVG, 所以它几乎能嵌入到任何平台应用, iOS 应用、安卓应用、桌面端应用和网页。

在Android中使用,我使用的是加载WebView。

写一个html的引用地址,在定义几个和我们安卓交互的方法。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Hanzi Writer</title><script src="file:///android_asset/js/hanzi-writer3.js"></script><script src="file:///android_asset/js/polyfill.min.js"></script><style>body, html {margin: 0;padding: 0;width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;background-color: rgba(0, 0, 0, 0);}#target {width: 300px;height: 300px;}</style>
</head>
<body>
<div id="target"></div>
<script>let writer;function clearCharacter() {// 如果已存在 writer 实例,则删除if (writer) {writer.cancelQuiz(); // 取消正在进行的测试(如果有)writer.setCharacter(''); // 将汉字设置为空document.getElementById('target').innerHTML = ''; // 清空目标区域writer = null; // 将 writer 实例置为 null}}function loadCharacter(character,wide,height) {clearCharacter()writer = HanziWriter.create('target', character, {width: 300,height: 300,showOutline: true,showCharacter: false,drawingColor:'#168F16',drawingWidth:30,});}function startQuiz() {if (writer) {writer.quiz({onMistake: function(strokeData) {AndroidInterface.onMistake(JSON.stringify(strokeData));},onCorrectStroke: function(strokeData) {AndroidInterface.onCorrectStroke(JSON.stringify(strokeData));},onComplete: function(summaryData) {AndroidInterface.onComplete(JSON.stringify(summaryData));}});}}function getSVG() {if (writer) {const path = writer.getPath();const svg = path.toSVG();AndroidInterface.showSVG(svg);}}function init() {loadCharacter('');}window.onload = init;// 新增函数,用于从Android接收汉字function receiveCharacterFromAndroid(character) {loadCharacter(character);}</script>
</body>
</html>

在Android中调用

        webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);webView.loadUrl( "file:///android_asset/hanziwriter1.html")webView.postDelayed({Log.i("AAAA","加载汉字----")loadCharacterFromAndroid("慕")webView.evaluateJavascript("startQuiz()", null)}, 500)

Js回调。

    private class JavaScriptInterface(private val context: Context) {@JavascriptInterfacefun onMistake(data: String) {Log.i("AAAAA","onMistake: $data")val jsonObject = JSONObject(data)val character = jsonObject.getString("character")val drawPath = jsonObject.getString("drawnPath") //使用 drawPath对比圈画区域是否重叠val jsonPath = JSONObject(drawPath)val pathString = jsonPath.getString("pathString")val strPoint = StringBuilder()jsonPath.getJSONArray("points").let {for (i in 0 until it.length()) {val jsonObject = it.getJSONObject(i)val x = jsonObject.getDouble("x")val y = jsonObject.getDouble("y")strPoint.append("$x,$y ")}}val totalMistakes = jsonObject.getInt("totalMistakes")val strokeNum = jsonObject.getInt("strokeNum") + totalMistakesval mistakesOnStroke = jsonObject.getInt("mistakesOnStroke")val strokesRemaining = jsonObject.getInt("strokesRemaining")uiThread {if (context is MainActivity) {context.takeBitmap()context.updateTextView("当前汉字:$character, 一共写了${strokeNum}笔, 错误笔顺${totalMistakes}笔, 剩余笔顺${strokesRemaining}笔")context.drawSVGImage(pathString, strPoint.toString())}}}@JavascriptInterfacefun onCorrectStroke(data: String) {Log.i("AAAAA","-onCorrectStroke: $data")val jsonObject = JSONObject(data)val character = jsonObject.getString("character")val drawPath = jsonObject.getString("drawnPath")//使用 drawnPath对比圈画区域是否重叠val jsonPath = JSONObject(drawPath)val pathString = jsonPath.getString("pathString")val strPoint = StringBuilder()jsonPath.getJSONArray("points").let {for (i in 0 until it.length()) {val jsonObject = it.getJSONObject(i)val x = jsonObject.getDouble("x")val y = jsonObject.getDouble("y")strPoint.append("$x,$y,")}}val totalMistakes = jsonObject.getInt("totalMistakes")val strokeNum = jsonObject.getInt("strokeNum") + totalMistakesval mistakesOnStroke = jsonObject.getInt("mistakesOnStroke")val strokesRemaining = jsonObject.getInt("strokesRemaining")uiThread {if (context is MainActivity) {context.takeBitmap()context.updateTextView("当前汉字:$character, 一共写了${strokeNum}笔, 错误笔顺${totalMistakes}笔, 剩余笔顺${strokesRemaining}笔")context.drawSVGImage(pathString, strPoint.toString())}}}@JavascriptInterfacefun onComplete(data: String) {Log.i("AAAAA","onComplete: $data")val jsonObject = JSONObject(data)val character = jsonObject.getString("character")if (context is MainActivity) {context.updateTextView("当前汉字:$character, 笔顺完成")}}}

HanziWriter官方API

1.创建新HanziWriter实例需要传入目标 div(ID 或 DOM 引用)、要呈现的字符以及配置选项。下面是一个简单的示例。在 Javascript 中:

     function loadCharacter(character) {clearCharacter()writer = HanziWriter.create('target', character, {width: 300,height: 300,showOutline: true,showCharacter: false,drawingColor:'#168F80',drawingWidth:30,});writer.quiz({onMistake: function(strokeData) {AndroidInterface.onMistake(JSON.stringify(strokeData));},onCorrectStroke: function(strokeData) {AndroidInterface.onCorrectStroke(JSON.stringify(strokeData));},onComplete: function(summaryData) {AndroidInterface.onComplete(JSON.stringify(summaryData));}});}

可以看到一下结果

2.创建 HanziWriter 实例后,您可以通过调用 animateCharacter()方法为其设置动画。

 function animateCharacter() {if (writer) {writer.animateCharacter({AndroidInterface.start());});}}

3.除了动画和测验的核心功能外,还有其他几种方法可用于控制角色的渲染。

writer.setCharacter(newCharacter) 加载新角色并重新渲染。
writer.showCharacter() 如果角色当前处于隐藏状态,则显示该角色
writer.hideCharacter() 如果当前显示该角色,则隐藏该角色
writer.showOutline() 如果字符轮廓当前处于隐藏状态,则显示该轮廓
writer.hideOutline() 如果当前显示字符轮廓,则隐藏它
writer.updateColor(colorName, newValue) 更改任意颜色选项的值。例如:writer.updateColor('strokeColor', '#AA12CD')
writer.cancelQuiz() 立即取消当前正在进行的测验

4.options包含其他配置选项的对象。可用的完整选项包括:

showOutline:布尔值,默认为 true。控制在第一次渲染时是否显示或隐藏轮廓。
showCharacter:布尔值,默认为 true。控制在第一次渲染时是否显示或隐藏字符。
width:数字。画布的宽度(以 px 为单位)。
height:数字。画布的高度(以 px 为单位)。
padding:数字,默认值为 20。字符和画布边缘之间的填充(单位为 px)。
strokeAnimationSpeed:数字,默认为 1。绘制每个笔触的速度必须大于 0。增加此数字可加快绘制笔触的速度,减少此数字可减慢绘制笔触的速度。
strokeHighlightSpeed:数字,默认为 2。在测验中给出提示时突出显示每个笔画的速度必须大于 0。增加此数字可加快突出显示速度,减少此数字可减慢突出显示速度。
strokeFadeDuration:数字,默认为 400。调用和隐藏笔画之间的转换时间(以毫秒为单位writer.show())writer.hide()
delayBetweenStrokes:数字,默认为 1000。动画时每次描边之间的时间(以毫秒为单位)。
delayBetweenLoops:数字,默认为 2000。循环动画时,每个动画循环之间的时间(以毫秒为单位)。
strokeColor:十六进制字符串,默认为“#555”。绘制每条笔画的颜色。
radicalColor:十六进制字符串,默认为 null。如果存在部首数据,则在笔画中绘制部首的颜色。如果未设置,部首将以与其他笔画相同的颜色绘制。
highlightColor:十六进制字符串,默认为“#AAF”。测验中用于突出显示的颜色。
outlineColor:十六进制字符串,默认为“#DDD”。字符轮廓的颜色。
drawingColor:十六进制字符串,默认为 '#333'。用户在测验期间绘制的线条的颜色。
drawingWidth:数字,默认4。用户在答题时绘制的线条宽度,单位为px。
showHintAfterMisses:整数,默认为 3。在向用户提供笔画高亮提示之前未完成的次数。设置为 false 以禁用。创建测验时也可以设置此项。
markStrokeCorrectAfterMisses:整数,默认禁用。强制将笔画标记为正确之前的未命中次数。这也可以在创建测验时设置。
quizStartStrokeNum:整数,默认为 0。可将此设置为从第一个笔划以外的笔划开始测验。也可在创建测验时设置。
acceptBackwardsStrokes:布尔值,默认 false。允许在测验期间向后绘制笔画。这也可以在创建测验时设置。
highlightOnComplete:布尔值,默认为 true。控制测验在用户完成绘制整个角色时是否短暂突出显示该角色。这也可以在创建测验时设置。
highlightCompleteColor:十六进制字符串,默认为 null。在测验中突出显示完成的字符时使用的颜色。如果未设置,highlightColor则将改为使用。仅当 时才highlightOnComplete相关true。
charDataLoader:函数。自定义函数用于加载字符数据。有关用法的更多信息,请参阅“加载字符数据”部分。
onLoadCharDataSuccess:函数。角色数据加载成功时的回调。此函数使用已加载的数据进行调用。这可用于实现加载微调器。
onLoadCharDataError:函数。字符数据加载失败时的回调。无论失败原因是什么,都会从charDataLoader传递此函数。
renderer:字符串,默认为“svg”。将其设置为“canvas”以使用 2d 画布而不是 SVG 进行渲染。在某些设备上可能会有更好的性能。

附上我的githubdemo地址。

PS:HanziWriter地址

github地址

 

相关文章:

在Android上实现汉字笔顺动画效果——HanZiWriter

序&#xff0c;万般皆是命&#xff0c;半点不由人。 Hanzi Writer 是 javascript 免费开源库&#xff0c;根据汉字书写时按照笔画顺序的特征&#xff0c;可以播放正确笔画顺序的描边动画和练习测试。支持简体字和繁体字。可以让全球用户能够通过手绘模仿的方式来学习和练习书写…...

黑马头条vue2.0项目实战(一)——项目初始化

1. 图标素材&#xff08;iconfont简介&#xff09; 制作字体图标的工具有很多&#xff0c;推荐使用&#xff1a;iconfont-阿里巴巴矢量图标库。 注册账户 创建项目 可以根据项目自定义 class 前缀 上传图标到项目 生成链接&#xff0c;复制 css 代码&#xff0c;在项目中使用…...

Unity Shader动画:用代码绘制动态视觉效果

在Unity中&#xff0c;Shader是运行在GPU上的小程序&#xff0c;用于控制顶点和像素的渲染过程。通过编写自定义Shader&#xff0c;开发者可以创造出各种令人惊叹的动画效果&#xff0c;从简单的颜色变化到复杂的流体模拟。本文将探讨如何使用Unity Shader来实现动画效果。 Sh…...

智税集成2.0生成凭证

:::info &#x1f4a1; 整体业务流程 从A9服务器中取数&#xff0c;生成列表数据&#xff0c;写入到对方oracle数据库中。 ::: 项目关键点 1.连接数据库 左连接连接本地SQLserver数据库、右连接要链接A9开票服务器的数据库然后设想用SQLserver 自带的外部连接来连接oracle数据…...

B4005 [GESP202406 四级] 黑白方块 【暴力枚举】【前缀和】

#include<bits/stdc.h> using namespace std; int n,m,ans,tmp; char mp[20][20]; int cheak(int a,int b,int c,int d){//a<c b<dint cnt0;//枚举矩阵中的每个点 for(int ia;i<c;i)for(int jb;j<d;j)if(mp[i][j]1) cnt;//统计黑格的个数 return 2*cnt(c-a1…...

深度学习趋同性的量化探索:以多模态学习与联合嵌入为例

深度学习趋同性的量化探索&#xff1a;以多模态学习与联合嵌入为例 参考文献 据说是2024年最好的人工智能论文&#xff0c;是否有划时代的意义&#xff1f; [2405.07987] The Platonic Representation Hypothesis (arxiv.org) ​arxiv.org/abs/2405.07987 趋同性的量化表达 …...

决策树与随机森林:比较与应用场景分析

决策树与随机森林&#xff1a;比较与应用场景分析 引言 决策树和随机森林是机器学习中广泛使用的两种算法&#xff0c;因其简单性和强大的功能而被广泛采用。决策树是一种树形结构的决策模型&#xff0c;易于理解和解释。随机森林则是通过集成多棵决策树来提高预测性能的模型…...

C#用Aspose.Cells导出Excel,.NET导出Excel

ASP.NET MVC 控制器里面Action处理&#xff0c;下载文件&#xff0c;输出文件流 public async Task<ActionResult> ExportNewsAuthorFee(string deptId, DateTime? startDate, DateTime? endDate){if (startDate null){startDate DateTime.Parse(DateTime.Now.Year …...

天猫番茄品类TOP1,复购率超40%,「一颗大」如何策划极致产品力?

桔子要买什么品牌&#xff1f;桃子买什么品牌&#xff1f;土豆买什么品牌&#xff1f;过去人们购买农产品几乎没有品牌意识。但近年来可能某些人买猕猴桃时会考虑佳沛&#xff0c;这是一个在全球达到30%猕猴桃市场的新西兰品牌。与此类似&#xff0c;一个国产品牌「一颗大™」正…...

Docker搭建私有仓库harbor(docker 镜像仓库搭建)

Harbor介绍 Docker容器应用的开发和运行离不开可靠的镜像管理&#xff0c;虽然Docker官方也提供了公共的镜像仓库&#xff0c;但是从安全和效率等方面考虑&#xff0c;部署我们私有环境内的Registry也是非常必要的。Harbor是由VMware公司开源的企业级的Docker Registry管理项目…...

面试题:MySQL 索引

1. 谈一下你对于MySQL索引的理解?(为什么MySQL要选择B+树来存储索引) MySQL的索引选择B+树作为数据结构来进行存储,使用B+树的本质原因在于可以减少IO次数,提高查询的效率,简单来说就是可以保证在树的高度不变的情况下存储更多的数据: IO效率的提高:在MySQL数据库中,…...

云计算day13

一、Git 概述 Git 是一种分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更。它是由 Linus Torvalds 创建的&#xff0c;最初被设计用于 Linux 内核的开发。Git 允许开发 人员跟踪和管理代码的版本&#xff0c;并且可以在不同的开发人员之间进行协作。 Github 用的就…...

2024年孝感中级职称报名开始了吗?

2024年孝感中级职称申报终于开始了&#xff0c;之前参加过水测的小伙伴们&#xff0c;开始准备评审了 2024年孝感本批次申报时间&#xff1a;中级、初级职称网上申报时间:2024年8月1日至8月31日。 注意&#xff1a;个人通过“湖北省职称评审管理信息系统”申报&#xff0c;须先…...

RAG技术之Router

Router有什么用&#xff1f; 在RAG应用中&#xff0c;Router可以帮助我们基于用户的查询意图来决定使用何种数据类型或数据源&#xff0c;比如是否需要进行语义检索、是否需要进行text2sql查询&#xff0c;是否需要用function call来进行API调用。 Router也可以根据用户的查询…...

linux系统通过修改sudo文件使普通用户拥有类似root用户权限

说明&#xff1a;普通用户要想拥有root权限&#xff0c;如果不在sudo文件里配置就算把该用户加到wheel组&#xff08;root用户所在的组&#xff09;也不行。 要想通过在命令前加上sudo使得该用户以root权限执行命令&#xff0c;需要修改/etc/sudoers文件。 &#xff08;如果通…...

基于PyCharm在Windows系统上远程连接Linux服务器中Docker容器进行Python项目开发与部署

文章目录 摘要项目结构项目开发项目上线参考文章 摘要 本文介绍了如何在Windows 10系统上使用PyCharm专业版2024.1&#xff0c;通过Docker容器在阿里云CentOS 7.9服务器上进行Python项目的开发和生产部署。文章详细阐述了项目结构的搭建、PyCharm的使用技巧、以及如何将开发项…...

TypeScript学习篇-类型介绍使用、ts相关面试题

文章目录 基础知识基础类型: number, string, boolean, object, array, undefined, void(代表该函数没有返回值)enum(枚举): 定义一个可枚举的对象typeinterface联合类型: |交叉类型: &any 类型null 和 undefinednullundefined never类型 面试题及实战1. 你觉得使用ts的好处…...

超详细!Jmeter性能测试

前言 性能测试是一个全栈工程师/架构师必会的技能之一&#xff0c;只有学会性能测试&#xff0c;才能根据得到的测试报告进行分析&#xff0c;找到系统性能的瓶颈所在&#xff0c;而这也是优化架构设计中重要的依据。 测试流程&#xff1a; 需求分析→环境搭建→测试计划→脚…...

C语言经典习题24

文件操作习题 一 编程删除从C盘home文件夹下data.txt文本文件中所读取字符串中指定的字符&#xff0c;该指定字符由键盘输入&#xff0c;并将修改后的字符串以追加方式写入到文本文件C:\home\data.txt中。 #include<stdio.h> main() { char s[100],ch; int i;…...

SQL labs-SQL注入(三,sqlmap使用)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; 盲注简述&#xff1a;是在没有回显得情况下采用的注入方式&#xff0c;分为布尔盲注和时间盲注。 布尔盲注&#xff1a;布尔仅有两种形式&#xff0c;ture&#…...

Java Eclipse JDK 1.8.0_25安装与配置全指南

1. JDK 1.8.0_25的下载与安装 如果你是刚接触Java开发的新手&#xff0c;可能会被各种版本的JDK搞得一头雾水。别担心&#xff0c;JDK 1.8.0_25&#xff08;也就是Java 8的一个子版本&#xff09;至今仍是企业开发中最常用的稳定版本之一。我当年刚开始学Java时&#xff0c;导师…...

C盘清理与优化:为Realistic Vision V5.1模型文件腾出空间

C盘清理与优化&#xff1a;为Realistic Vision V5.1模型文件腾出空间 你是不是也遇到过这种情况&#xff1a;电脑C盘突然飘红&#xff0c;系统提示空间不足&#xff0c;想下载个新的AI模型&#xff0c;比如最近很火的Realistic Vision V5.1&#xff0c;却发现根本没地方放。看…...

WordPress建站避坑指南:Ubuntu服务器常见权限问题与安全配置

WordPress建站避坑指南&#xff1a;Ubuntu服务器常见权限问题与安全配置 引言&#xff1a;为什么你的WordPress网站总出问题&#xff1f; 每次看到新手开发者兴奋地宣布"我的WordPress网站上线了"&#xff0c;我都忍不住想问&#xff1a;你真的检查过文件权限了吗&am…...

如何用Penpot构建完整的用户体验地图和用户旅程:7步打造完美设计流程

如何用Penpot构建完整的用户体验地图和用户旅程&#xff1a;7步打造完美设计流程 【免费下载链接】penpot Penpot - The Open-Source design & prototyping platform 项目地址: https://gitcode.com/GitHub_Trending/pe/penpot Penpot作为开源的设计与原型平台&…...

Ubuntu常用的命令

ls -l # 输出当前文件夹下的所有文件的权限大小信息 ls -l 文件名 # 输出当前文件的权限大小信息 du -sh # 查看文件夹下所有文件的大小总和 df -h # 查看当前文件系统各分区的大小 hdparm -Tt /dev/sda1 # 查看分区磁盘的速度 ls -l | grep "^-" | wc -l # 当前目…...

将 OnePlus 手机备份到云服务

丢失 OnePlus 设备上的珍贵照片、重要联系人、短信或应用数据可能会令人非常沮丧&#xff0c;无论是意外删除、设备损坏、被盗&#xff0c;甚至是恢复出厂设置。这时&#xff0c;云备份就派上了用场。它提供了一种简单可靠的数据保护方式&#xff0c;确保您可以随时随地在新 On…...

AI辅助开发:用提示词让快马AI自动生成技术职级成长路径分析应用

AI辅助开发&#xff1a;用提示词让快马AI自动生成技术职级成长路径分析应用 最近在研究技术职级体系时&#xff0c;发现很多开发者对阿里P10这类高级职位的成长路径特别感兴趣。但手动整理这些信息费时费力&#xff0c;于是尝试用AI辅助开发的方式快速生成一个可视化分析工具。…...

3大创新突破让千元机械臂媲美工业级性能:Faze4开源六轴机器人DIY全指南

3大创新突破让千元机械臂媲美工业级性能&#xff1a;Faze4开源六轴机器人DIY全指南 【免费下载链接】Faze4-Robotic-arm All files for 6 axis robot arm with cycloidal gearboxes . 项目地址: https://gitcode.com/gh_mirrors/fa/Faze4-Robotic-arm 价值定位&#xff…...

避坑指南:Double DQN和Dueling DQN在TensorFlow 2.x中的5个常见实现错误

Double DQN与Dueling DQN在TensorFlow 2.x中的五大工程陷阱与解决方案 当你在深夜调试强化学习模型时&#xff0c;是否遇到过这种情况&#xff1a;训练曲线像过山车一样剧烈波动&#xff0c;明明采用了Double DQN或Dueling DQN这些改进算法&#xff0c;效果却比基础DQN还要差&a…...

以太网MAC与PHY接口技术详解

以太网PHY、MAC及其通信接口技术解析1. 以太网接口架构概述1.1 基本组成结构以太网接口电路从硬件角度可分为两大核心组件&#xff1a;MAC控制器&#xff08;Media Access Control&#xff09;&#xff1a;负责数据链路层的媒体访问控制PHY芯片&#xff08;Physical Layer&…...