文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JS如何实现一个可以当镜子照的Button

2023-07-05 09:13

关注

本篇内容介绍了“JS如何实现一个可以当镜子照的Button”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

mediaDevices 的介绍

在 MDN 中可以看到 mediaDevices 的介绍:

JS如何实现一个可以当镜子照的Button

可以用来获取摄像头、麦克风、屏幕等。

它有这些 api:

JS如何实现一个可以当镜子照的Button

getDisplayMedia 可以用来录制屏幕,截图。

getUserMedia 可以获取摄像头、麦克风的输入。

JS如何实现一个可以当镜子照的Button

我们这里用到getUserMedia 的 api

它要指定音频和视频的参数,开启、关闭、分辨率、前后摄像头啥的:

JS如何实现一个可以当镜子照的Button

这里我们把 video 开启,把 audio 关闭。

也就是这样:

navigator.mediaDevices.getUserMedia({    video: true,    audio: false,}).then((stream) => {    //...}).catch(e => {    console.log(e)})

把获取到的 stream 用一个 video 来展示

navigator.mediaDevices.getUserMedia({    video: true,    audio: false,}).then((stream) => {  const video = document.getElementById('video');  video.srcObject = stream;  video.onloadedmetadata = () => {    video.play();  };}).catch((e) => console.log(e));

通过 css 的 filter 来加点感觉:

比如加点 blur:

video {  filter: blur(10px);}

加点饱和度:

video {  filter: saturate(5)}

或者加点亮度:

video: {  filter: brightness(3);}

filter 可以组合,调整调整达到这样的效果就可以了:

video {  filter: blur(2px) saturate(0.6) brightness(1.1);}

然后调整下大小:

video {  width: 300px;  height: 100px;  filter: blur(2px) saturate(0.6) brightness(1.1);}

你会发现视频的画面没有达到设置的宽高。

这时候通过 object-fit 的样式来设置:

video {  width: 300px;  height: 100px;  object-fit: cover;  filter: blur(2px) saturate(0.6) brightness(1.1);}

cover 是充满容器,但画面显示的位置不大对,看不到脸。我想显示往下一点的画面怎么办呢?

可以通过 object-position 来设置:

video {  width: 300px;  height: 100px;  object-fit: cover;  filter: blur(2px) saturate(0.6) brightness(1.1);  object-position: 0 -100px;}

y 向下移动 100 px ,画面显示的位置就对了。

其实现在还有一个特别隐蔽的问题,不知道大家发现没,就是方向是错的。照镜子的时候应该左右翻转才对。

所以加一个 scaleX(-1),这样就可以绕 x 周反转了。

video {  width: 300px;  height: 100px;  object-fit: cover;  filter: blur(2px) saturate(0.6) brightness(1.1);  object-position: 0 -100px;  transform: scaleX(-1);}

这样就是镜面反射的感觉了。

然后再就是 button 部分,这个我们倒是经常写:

function Button({ children }) {  const [buttonPressed, setButtonPressed] = useState(false);  return (    <div      className={`button-wrap ${buttonPressed ? "pressed" : null}`}    >      <div        className={`button ${buttonPressed ? "pressed" : null}`}        onPointerDown={() => setButtonPressed(true)}        onPointerUp={() => setButtonPressed(false)}      >         <video/>      </div>      <div className="text">{children}</div>    </div>  );}

这里我用 jsx 写的,点击的时候修改 pressed 状态,设置不同的 class。

样式部分

:root {  --transition: 0.1s;  --border-radius: 56px;}.button-wrap {  width: 300px;  height: 100px;  position: relative;  transition: transform var(--transition), box-shadow var(--transition);}.button-wrap.pressed {  transform: translateZ(0) scale(0.95);}.button {  width: 100%;  height: 100%;  border: 1px solid #fff;  overflow: hidden;  border-radius: var(--border-radius);  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.25), 0px 8px 16px rgba(0, 0, 0, 0.15),    0px 16px 32px rgba(0, 0, 0, 0.125);  transform: translateZ(0);  cursor: pointer;}.button.pressed {  box-shadow: 0px -1px 1px rgba(0, 0, 0, 0.5), 0px 1px 1px rgba(0, 0, 0, 0.5);}.text {  position: absolute;  left: 50%;  top: 50%;  transform: translate(-50%, -50%);  pointer-events: none;  color: rgba(0, 0, 0, 0.7);  font-size: 48px;  font-weight: 500;  text-shadow:0px -1px 0px rgba(255, 255, 255, 0.5),0px 1px 0px rgba(255, 255, 255, 0.5);}

这种 button 大家写的很多了,也就不用过多解释。

要注意的是 text 和 video 都是绝对定位来做的居中。

阴影的设置

阴影的 4 个值是 x、y、扩散半径、颜色。

我设置了个多重阴影:

JS如何实现一个可以当镜子照的Button

然后再改成不同透明度的黑就可以了:

JS如何实现一个可以当镜子照的Button

再就是按下时的阴影,设置了上下位置的 1px 黑色阴影:

.button.pressed {  box-shadow: 0px -1px 1px rgba(0, 0, 0, 0.5), 0px 1px 1px rgba(0, 0, 0, 0.5);}

同时,按下时还有个 scale 的设置

再就是文字的阴影,也是上下都设置了 1px 阴影,达到环绕的效果:

text-shadow:0px -1px 0px rgba(255, 255, 255, 0.5),0px 1px 0px rgba(255, 255, 255, 0.5);

最后,把这个 video 嵌进去就行了。

完整代码

import React, { useState, useEffect, useRef } from "react";import "./button.css";function Button({ children }) {  const reflectionRef = useRef(null);  const [buttonPressed, setButtonPressed] = useState(false);  useEffect(() => {    if (!reflectionRef.current) return;    navigator.mediaDevices.getUserMedia({        video: true,        audio: false,    })    .then((stream) => {        const video = reflectionRef.current;        video.srcObject = stream;        video.onloadedmetadata = () => {        video.play();        };    })    .catch((e) => console.log(e));  }, [reflectionRef]);  return (    <div      className={`button-wrap ${buttonPressed ? "pressed" : null}`}    >      <div        className={`button ${buttonPressed ? "pressed" : null}`}        onPointerDown={() => setButtonPressed(true)}        onPointerUp={() => setButtonPressed(false)}      >        <video          className="button-reflection"          ref={reflectionRef}        />      </div>      <div className="text">{children}</div>    </div>  );}export default Button;
body {  padding: 200px;}:root {  --transition: 0.1s;  --border-radius: 56px;}.button-wrap {  width: 300px;  height: 100px;  position: relative;  transition: transform var(--transition), box-shadow var(--transition);}.button-wrap.pressed {  transform: translateZ(0) scale(0.95);}.button {  width: 100%;  height: 100%;  border: 1px solid #fff;  overflow: hidden;  border-radius: var(--border-radius);  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.25), 0px 8px 16px rgba(0, 0, 0, 0.15),    0px 16px 32px rgba(0, 0, 0, 0.125);  transform: translateZ(0);  cursor: pointer;}.button.pressed {  box-shadow: 0px -1px 1px rgba(0, 0, 0, 0.5), 0px 1px 1px rgba(0, 0, 0, 0.5);}.text {  position: absolute;  left: 50%;  top: 50%;  transform: translate(-50%, -50%);  pointer-events: none;  color: rgba(0, 0, 0, 0.7);  font-size: 48px;  font-weight: 500;  text-shadow:0px -1px 0px rgba(255, 255, 255, 0.5),0px 1px 0px rgba(255, 255, 255, 0.5);}.text::selection {  background-color: transparent;}.button .button-reflection {  width: 100%;  height: 100%;  transform: scaleX(-1);  object-fit: cover;  opacity: 0.7;  filter: blur(2px) saturate(0.6) brightness(1.1);  object-position: 0 -100px;}

“JS如何实现一个可以当镜子照的Button”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯