Appearance
场景应用
各种场景应用题。
一、炉石传说3D卡片
鼠标悬停于卡片之上时,触发3D旋转与缩放效果。
代码实现:
vue
<template>
<div class="playing-card">
<div class="playing-card-front"></div>
</div>
</template>
<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
// 引用卡片元素
const card = ref(null);
const cardFront = ref(null);
onMounted(() => {
card.value = document.querySelector('.playing-card');
cardFront.value = document.querySelector('.playing-card-front');
const handleMouseMove = (e) => {
if (!card.value ||!cardFront.value) return;
const rect = card.value.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const halfWidth = card.value.offsetWidth / 2;
const halfHeight = card.value.offsetHeight / 2;
const dx = (x - halfWidth) / halfWidth;
const dy = (y - halfHeight) / halfHeight;
cardFront.value.style.transform = `scale(1.1) rotateY(${dx * -20}deg) rotateX(${dy * 20}deg)`;
};
const handleMouseOut = () => {
if (cardFront.value) {
cardFront.value.style.transform = 'none';
}
};
card.value.addEventListener('mousemove', handleMouseMove);
card.value.addEventListener('mouseout', handleMouseOut);
// 在组件销毁时移除事件监听器,避免内存泄漏
onUnmounted(() => {
if (card.value) {
card.value.removeEventListener('mousemove', handleMouseMove);
card.value.removeEventListener('mouseout', handleMouseOut);
}
});
});
</script>
<style scoped>
/* 整体页面布局 */
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
/* 扑克卡片容器 */
.playing-card {
width: 240px;
height: 330px;
border-radius: 10px;
overflow: visible;
perspective: 700px;
cursor: pointer;
position: relative;
}
/* 扑克卡片正面 */
.playing-card-front {
width: 100%;
height: 100%;
background-image: url('/xiaoxiayan.png');
background-size: cover;
transform-style: preserve-3d;
will-change: transform;
transition: all 1s cubic-bezier(0.03, 0.98, 0.52, 0.99);
}
</style>
二、复制文本到剪切板
navigator.clipboard.writeText
html
<!DOCTYPE html>
<html lang="en">
<body>
<button onclick="copyText('要复制的文本')">复制文本</button>
<script>
function copyText(text) {
navigator.clipboard.writeText(text).then(() => {
console.log('已复制到剪切板');
}, (err) => {
console.error('复制失败:', err);
});
}
</script>
</body>
</html>
document.execCommand
原理:document.execCommand方法主要用于在文档的可编辑区域(如contenteditable属性为true的元素或textarea、input等表单元素)执行各种命令。在复制文本到剪贴板的场景中,它通过操作选中的文本来实现复制功能。 使用场景:在不支持navigator.clipboard.writeText的较旧浏览器中发挥作用,以提供一种相对兼容的方式来实现复制文本的功能。不过,这种方法存在一些局限性,并且在现代浏览器开发中逐渐被废弃。
html
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" id="textToCopy" value="要复制的文本">
<button onclick="copyText()">复制文本</button>
<script>
function copyText() {
var textToCopy = document.getElementById('textToCopy').value;
var textarea = document.createElement('textarea');
textarea.value = textToCopy;
document.body.appendChild(textarea);
textarea.select();
try {
return document.execCommand('copy');
} catch (err) {
console.error('复制失败:', err);
return false;
} finally {
document.body.removeChild(textarea);
}
}
</script>
</body>
</html>
三、对象扁平化
将
js
const obj = {
a: 1,
b: [1,2,3],
c: {
d: [2,3,4, {
ok: true,
fine:[100,200]
}],
e: {
f: false,
g: null
}
},
h: undefined
}
这样的对象扁平化为
json
{
"a": 1,
"b[0]": 1,
"b[1]": 2,
"b[2]": 3,
"c.d[0]": 2,
"c.d[1]": 3,
"c.d[2]": 4,
"c.d[3].ok": true,
"c.d[3].fine[0]": 100,
"c.d[3].fine[1]": 200,
"c.e.f": false
}
去除掉 undefined
和 null
递归实现
js
function flatten(obj) {
let res = {};
function flat(obj, prefix) {
if (!(typeof obj === 'object') && obj !== null && obj !== undefined) {
res[`${prefix}`] = obj;
} else {
if (obj instanceof Array) {
for (let i = 0; i < obj.length; i++) {
flat(obj[i], `${prefix}[${i}]`);
}
} else {
for (let key in obj) {
if (prefix) {
flat(obj[key], `${prefix}.${key}`)
} else {
flat(obj[key], key)
}
}
}
}
}
flat(obj, '');
return res;
}