手把手教你从空白页面开始通过拖拉拽可视化的方式制作【立体键盘】的静态页面,不用手写一行CSS代码,全程只用10来行表达式就完成了【盲打练习】的交互逻辑。
整个过程在众触应用平台进行,快速直观。
效果图是用Win + Shift + S快捷键截的屏,所以Meta和Shift键处于按下的高亮状态

自由按键 vs 盲打练习


等不及了,马上亲自动手试一试:https://keyboard.zc-app.cn/z
下面的文章描述的是重点要点,手把手的教学请移步哔哩哔哩视频:https://www.bilibili.com/video/BV16T411377x
通过观察键盘我们很容易发现它是由4排按键组成的,每排按键又有不同数目的按键。很自然我们会把它们抽象出一个二维数组。
为了实现交互,需要捕捉被用户按下按键的编码(code),所以我们就把每个按键编码提取出来作为数组项。
具体的编码可以通过log($event.code)打印出来。
把所有按键编码的二维数组赋给变量$v.keys:
[
["Backquote", "Digit1", "Digit2", "Digit3", "Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9", "Digit0", "Minus", "Equal", "Backspace", "Home"],
["Tab", "KeyQ", "KeyW", "KeyE", "KeyR", "KeyT", "KeyY", "KeyU", "KeyI", "KeyO", "KeyP", "BracketLeft", "BracketRight", "Backslash", "End"],
["CapsLock", "KeyA", "KeyS", "KeyD", "KeyF", "KeyG", "KeyH", "KeyJ", "KeyK", "KeyL", "Semicolon", "Quote", "Enter", "PageUp"],
["ShiftLeft", "KeyZ", "KeyX", "KeyC", "KeyV", "KeyB", "KeyN", "KeyM", "Comma", "Period", "Slash", "ShiftRight", "ArrowUp", "PageDown"],
["ControlLeft", "Fn", "MetaLeft", "AltLeft", "Space", "AltRight", "ControlRight", "ArrowLeft", "ArrowDown", "ArrowRight"]
]
同时在UI上也要显示打印按钮上的标识,我们把标识和编码对于匹配规律性不强的按钮挑出来(字母、数字很有规律),用对象把标识和按钮编码匹配起来,赋给变量$v.label:
{
"Backquote": "`",
"Minus": "-",
"Equal": "=",
"BracketLeft": "[",
"BracketRight": "]",
"Backslash": "\\\\",
"Semicolon": ";",
"Quote": "\'",
"PageUp": "PgUp",
"ShiftLeft": "Shift",
"Comma": ",",
"Period": ".",
"Slash": "/",
"ShiftRight": "Shift",
"ArrowUp": "▲",
"PageDown": "PgDn",
"ControlLeft": "Ctrl",
"MetaLeft": "Meta",
"AltLeft": "Alt",
"AltRight": "Alt",
"ControlRight": "Ctrl",
"ArrowLeft": "◄",
"ArrowDown": "▼",
"ArrowRight": "►"
}
先添加一个数据组件(类名keyboard),绑定$v.keys作为数据源;再在它里面添加一个数据组件(类名row),用外层数据组件提供的数据项$x作为数据源,它其实是某排按键数组。
再添加一个div(动态类名("key " + $x))作为每个按键的容器,并通过可视化设计器添加阴影和圆角等共通样式,给部分特殊按键添加选择器以更改其颜色和宽度。
添加一个span,给它添加动态文本内容($v.label[$x]),这样在$v.label里有匹配的按键就显示出来了。 再添加|| $x.replace("Key", "").replace("Digit", "")那数字和字母也显示出来了。
鼠标移到组件树的各层组件上,对应的元素就会高亮显示,提示它(们)渲染的对应关系。

hover到keyboard时整个键盘的边框高亮;
hover到row时每排按键高亮;
hover到div时每个按键的边框高亮;
hover到span时每个按键上的字高亮。
我们需要全局捕捉按键事件,所以在根节点上的onKeyDown事件上添加如下逻辑:
$v.key = $("." + $event.code)
stopIf(!$v.key)
$v.key.addClass("active")
先根据事件中的按键编码($event.code)选择有没有以此编码为类名的元素,如果没找到说明用户按下的键不在此虚拟键盘上(真实键盘第一排的功能键),则停止往下运行(stopIf),如果找到了则给此元素添加acitve类。此时我们要添加选择器.key.active,并在可视化设计器添加按键处于按下状态时的样式(按键的按下位移、背光、阴影)
按键弹起的时候就应该去掉上面添加的active类以恢复常态,所以在根节点上的onKeyUp事件上添加如下逻辑:
$("." + $event.code).removeClass("active")
盲打逻辑会在两种情况下执行:一是用户在【盲打练习】勾勾上打勾时,二是用户按中待按按键时。
盲打的逻辑是从所有按键中随机选择一个按键,给它添加selected类,等待用户按键,如果用户按下的按键刚好是此键则继续产生一个随机按键,如此往复。
在onReady中把键盘二维数组合并成一维数组$v.all,再去除Fn和MetaLeft两个特殊按键:
$v.all = $v.keys.reduce('$acc.concat($x)', [])
$v.all.splice($v.all.indexOf("Fn"), 1)
$v.all.splice($v.all.indexOf("MetaLeft"), 1)
添加$exp.盲打局部表达式:
stopIf(!$f.x.盲打)
$v.selected = $v.all[$w.Math.floor($w.Math.random() * $v.all.length)]
$("." + $v.selected).addClass("selected")
如果【盲打练习】勾勾未勾上则停止继续运行;从所有按键$v.all中,产生随机数,并添加selected类。
把表达式转换成函数(func)并赋给变量$v.盲打:
$v.盲打 = func($exp.盲打)
用户打勾时开始执行此函数:
$v.盲打()
在上面的onKeyDown事件上继续添加如下逻辑:
stopIf(!$v.key.classList.contains("selected"))
$v.key.removeClass("selected")
$v.盲打()
如果用户按下的按键类名中包含selected类名,说明按对了,移除此类名,继续执行盲打函数,否则说明打错了,不予理会(stopIf)。
更多教学视频请移步哔哩哔哩空间:https://space.bilibili.com/475645807,里面不仅有各种前端可视化案例演示和讲解,还有多个完整功能的网站应用案例的开发过程演示和讲解。
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我在MiniTest::Spec和Capybara中使用以下规范:find_field('Email').must_have_css('[autofocus]')检查名为“电子邮件”的字段是否具有autofocus属性。doc说如下:has_css?(path,options={})ChecksifagivenCSSselectorisonthepageorcurrentnode.据我了解,字段“Email”是一个节点,因此调用must_have_css绝对有效!我做错了什么? 最佳答案 通过JonasNicklas得到了答案:No
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f
我有一个div,它根据表单是否正确提交而改变。我想知道是否可以检查类的特定元素?开始元素看起来像这样。如果输入不正确,添加错误类。 最佳答案 试试这个:browser.div(:id=>"myerrortest").class_name更多信息:http://watir.github.com/watir-webdriver/doc/Watir/HTMLElement.html#class_name-instance_method另一种选择是只查看具有您期望的类的div是否存在browser.div((:id=>"myerrortes
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析: 在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1: print(k)k=k/2A.1000 B.10C.11D.9解析: 按照题意每次循环K/2,直到K值小于等
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
我刚刚安装了带有RVM的Ruby2.2.0,并尝试使用它得到了这个:$rvmuse2.2.0--defaultUsing/Users/brandon/.rvm/gems/ruby-2.2.0dyld:Librarynotloaded:/usr/local/lib/libgmp.10.dylibReferencedfrom:/Users/brandon/.rvm/rubies/ruby-2.2.0/bin/rubyReason:Incompatiblelibraryversion:rubyrequiresversion13.0.0orlater,butlibgmp.10.dylibpro
我正在运行Ubuntu11.10并像这样安装Ruby1.9:$sudoapt-getinstallruby1.9rubygems一切都运行良好,但ri似乎有空文档。ri告诉我文档是空的,我必须安装它们。我执行此操作是因为我读到它会有所帮助:$rdoc--all--ri现在,当我尝试打开任何文档时:$riArrayNothingknownaboutArray我搜索的其他所有内容都是一样的。 最佳答案 这个呢?apt-getinstallri1.8编辑或者试试这个:(非rvm)geminstallrdocrdoc-datardoc-da