心血来潮,这次我用代码“敲”木鱼
技术栈
面对这种寿命短,后期也基本不需要维护的项目(更没有复杂的网络请求一说),本篇文章直接使用原生JavaScript
进行开发。或者您也可以尝试一下低代码
关于低代码,您大可放心的阅读此篇干货文章《低代码都做了什么?(为什么?怎么实现Low-Code?)》
至于TypeScript,您可以通过《谈谈写TypeScript实践而来的心得体会》这篇文章快速上手或进阶TS
实现
页面布局
图中右侧标出了三个部分:
img
标签用于指定木鱼的图片url地址,在木鱼进行缩放时,对该标签增加/删除
css类名即可- 每次敲击时所产生的文字由
p
标签生成,且所有的p
标签都存在于div
标签之下 audio
标签会在敲击时播放声音
本篇文章不会涉及具体的Html、Css部分。如有疑问,请在此项目的GitHub中找到答案
逻辑部分
准备工作
通过JavaScript
获取要操作的真实dom
const dom = {
// 木鱼
woodenFish: document.querySelector("img"),
// 文字浮层
text: document.querySelector(".w-f-c-text"),
// 音频
audio: document.querySelector("audio")
}
复制代码
木鱼缩放
这里的思路是敲击时给img
追加一个带有css animation
的样式类,该animation
的作用是让木鱼进行一次缩放,例如
.w-f-c-i-size {
/** 这里的animation只会执行一次缩放,所以后面会通过增加/删除该类名来达到可以进行n次缩放的效果 */
animation: wooden-fish-size 0.3s;
}
@keyframes wooden-fish-size {
0% {
transform: scale(1);
}
50% {
transform: scale(0.9);
}
100% {
transform: scale(1);
}
}
复制代码
样式搞定之后,通过原生JavaScript
提供的dom classList
进行css
样式类名的增加与删除。dom classList
共有四个方法:
add
:在指定节点上增加一个样式类名remove
:在指定节点上删除一个样式类名toggle
:在指定节点A
上若已有样式类名a
,则将a
删除;若没有样式类名a
,则添加类名a
replace
:将指定节点上的样式类名替换为另一个样式类名。效果同String##replace
一致
const woodenFish = {
// 封装一个用于增加/删除类名的方法
className(type) {
dom.woodenFish.classList[type]("w-f-c-i-size")
},
size() {
this.className("add")
setTimeout(() => this.className("remove"), 300)
}
}
复制代码
size
方法用于进行一次木鱼的缩放。调用该方法时,首先为img
标签增加类w-f-c-i-size
,在300毫秒
后,再将该类名移除
为什么是300毫秒
?因为css animation
的持续时间为300毫秒
需要注意的是,size
方法中的this
为woodenFish
对象,所以this.className
就相当于woodenFish.className
关于this或其它JavaScript的问题,您可以在《JavaScript每日一题》专栏中找到对应的题目进行练习
文字浮层
const woodenFish = {
className() {},
size() {},
createText() {
const p = document.createElement("p")
p.innerText = "功德+1"
dom.text.appendChild(p)
}
}
复制代码
createText
方法用于创建一个p
标签,该标签的文字内容为“功德+1”,随后将该标签追加在div
下即可
小tip:JSX(或react)中书写HTML类型的注释
博主在此刻书写document.createElement
这个原生方法时,突然想到了最近用到的一个原生属性outerHTML
,该属性与innerHTML
的区别就不再赘述。在JSX
中书写html
类型的注释,使用大括号的形式({/** */}
)是不可以的,因为在编译时这些东西都会被扔掉,此时可以使用由React
提供的dangerouslySetInnerHTML
属性,但体验感不太好。所以可以使用ouertHTML
配合ref
来解决,vue
同理,例如:
const HtmlComment: FC<HtmlCommentType> = ({ children }) => {
const virtual = useRef<HTMLSpanElement>(null)
useEffect(() => {
virtual.current!.outerHTML = `<!-- ${children} -->`
}, [])
return <span ref={virtual} />
}
复制代码
H5控制手机震动
const vibrate = () => {
const navigator = window.navigator
if (!("vibrate" in navigator)) return
navigator.vibrate =
navigator.vibrate ||
navigator.webkitVibrate ||
navigator.mozVibrate ||
navigator.msVibrate
if (!navigator.vibrate) return
// 上面的代码全是进行兼容性判断,只有下面这一行是发起手机震动的API
navigator.vibrate(300)
}
复制代码
像发起手机震动这类Api
,首先就要进行兼容性判断,所以上面vibrate
方法的90%
部分都在进行兼容性判断。注意,window.navigator
提供了一个用于发起设备震动的方法,即window.navigator.vibrate
window.navigator.vibrate
方法的参数:
- 一个
number
类型的值
这种方式表示震动持续多长时间,例如window.navigator.vibrate(300)
,则表示震动持续300毫秒
- 一个
number
类型的数组
这种方式表示震动、暂停间隔的时间。例如window.navigator.vibrate([100, 30, 100])
,则表示先震动100毫秒
,随后暂停30毫秒
,然后再震动100毫秒
window.navigator.vibrate
方法在震动成功时返回true
,否则返回false
vibrate兼容性
浏览器全屏操作
const toggleFullScreen = () => {
if (!document.fullscreenElement)
return document.documentElement.requestFullscreen()
if (!document.exitFullscreen) return
document.exitFullscreen()
}
document.addEventListener("keydown", (e) =>
e.keyCode == 13 ? toggleFullScreen() : false
)
复制代码
toggleFullScreen
方法会在全屏或非全屏之间来回切换,用到了以下属性/方法:
document.fullscreenElement
返回当前正在以全屏模式显示的元素,如果没有,则返回null
document.documentElement.requestFullscreen
用于发起全屏请求。若全屏请求成功,则该函数返回成功的Promise
对象,否则返回失败的Promise
对象。
在全屏成功时,全屏显示的元素会触发fullscreenchange事件;类似于输入框在输入时会触发onchange事件
document.exitFullscreen
方法用于使当前元素退出全屏模式
随后为document
绑定keydown
事件,如果按下了回车键,则在全屏/非全屏之间切换,否则不做出任何操作
音频事件操作
之前博主在写播放器的时候就发现音频的属性、方法、事件很多很多,所以此处只列举两个本项目中用到的方法
play()
使播放开始pause()
使播放暂停
制作完成
通过以上几个步骤就已经完成了所有要用到的东西,最后只需为木鱼注册“敲击”事件即可
dom.woodenFish.addEventListener("click", () => {
// 木鱼缩放
woodenFish.size()
// 创建文字浮层
woodenFish.createText()
// 播放敲击木鱼的声音
dom.audio.play()
// 发起手机震动
vibrate()
})
复制代码
文末
从一次心血来潮,到自己从0至1完成这个简单而有趣的小项目,无论是技术角度,还是个人收获角度来讲,都是收获满满!现在您可以通过以下两个地址来 “功德+1” :
由于时间匆忙,文中错误之处在所难免,敬请读者斧正。如果您觉得本篇文章还不错,欢迎点赞收藏和关注,我们下篇文章见!
链接:https://juejin.cn/post/7199660596735164475
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。