文章目录
- 前言
- 效果
- 电脑效果
- 手机效果
- 说明
- 完整代码
- index.html
前言
诶?这有一个按钮(~ ̄▽ ̄)~,这是一个在html中实现的具有金属质感并且能镜面反射的按钮~
效果
电脑效果
手机效果
说明
主要思路是使用 navigator.mediaDevices.getUserMedia()
调用设备摄像头来实现镜面反射,css部分用到了filter
属性,后期可以根据需要调整它的属性值,做出更多反射效果。有了思路,实现起来还是比较简单的。
需要注意的是window.navigator.mediaDevices.getUserMedia()
只能在localhost
或https
下才能使用,否则会报错哦。
完整代码
index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><style>body {background-color: rgb(86, 86, 86);}:root {--transition: 0.1s;--border-radius: 56px;}.button-wrap {margin: calc(30vh - 50px) auto 0;width: 300px;height: 100px;position: relative;transition: transform var(--transition), box-shadow var(--transition);}.button-wrap.pressed {transform: translateZ(0) scale(0.98);}.button {width: 100%;height: 100%;overflow: hidden;border-radius: var(--border-radius);box-shadow:0px 0px 10px rgba(0, 0, 0, 0.6),0px 0px 20px rgba(0, 0, 0, 0.4),0px 0px 40px rgba(0, 0, 0, 0.2),inset 0 2px 2px rgba(255, 255, 255, 0.8),inset 0 -2px 2px rgba(255, 255, 255, 0.8);transform: translateZ(0);cursor: pointer;}.button.pressed {box-shadow:0px 0px 5px rgba(0, 0, 0, 0.6),0px 0px 10px rgba(0, 0, 0, 0.4),0px 0px 20px rgba(0, 0, 0, 0.2),inset 0 2px 2px rgba(255, 255, 255, 0.8),inset 0 -2px 2px rgba(255, 255, 255, 0.8);}.text {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);pointer-events: none;color: rgba(0, 0, 0, 0.9);font-size: 48px;font-weight: bold;text-shadow:0px 2px 1px rgba(255, 255, 255, 0.3),0px -2px 1px rgba(255, 255, 255, 0.3);}.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;}</style>
</head><body><div id="app"><div v-show="cameraOpened" :class="`button-wrap ${buttonPressed ? 'pressed' : ''}`"><div :class="`button ${buttonPressed ? 'pressed' : ''}`" @mousedown="setButtonPressed(true)"@mouseup="setButtonPressed(false)" @touchstart="setButtonPressed(true)" @touchend="setButtonPressed(false)"><video class="button-reflection" ref="reflectionRef" /></div><div class="text">Button</div></div></div><script>new Vue({el: '#app',data: {cameraOpened: false,buttonPressed: false},mounted() {const _this = thisnavigator.mediaDevices.getUserMedia({video: true,audio: false}).then((stream) => {const video = this.$refs.reflectionRefvideo.srcObject = stream;video.onloadedmetadata = () => {_this.cameraOpened = truevideo.play()}})},methods: {setButtonPressed(val) {this.buttonPressed = val}}})</script>
</body></html>