一般我们给一个元素添加阴影效果第一时间想到box-shadow属性,但因其众多参数(X,Y轴偏移、模糊和扩散半径以及颜色参数)不好调试,所以一般也是看网上好看的阴影效果粘贴过来就是了。。今天准备写一个box-shadow可视化代码生成器,自己也能调试出好看的阴影效果!
线上地址 8jndl8.csb.app/
效果展示
html结构
划分的结构如图所示
结构清楚了代码也就好写咯
<body>
<div class="container">
<div class="result">
<div id="preview"></div>
</div>
<div class="settings">
<div class="range-wrapper">
<label for="x-shadow">Horizontal Shadow :</label>
<input type="range" id="x-shadow" min="-100" max="100" value="-6" />
</div>
<div class="range-wrapper">
<label for="y-shadow">Vertical Shadow :</label>
<input type="range" id="y-shadow" min="-100" max="100" value="15" />
</div>
<div class="range-wrapper">
<label for="blur-r">Blur Radius :</label>
<input type="range" id="blur-r" min="0" max="100" value="30" />
</div>
<div class="range-wrapper">
<label for="spread-r">Spread Radius :</label>
<input type="range" id="spread-r" min="-50" max="50" value="6" />
</div>
<div class="range-wrapper">
<label for="border-r">Border Radius :</label>
<input type="range" id="border-r" min="0" max="100" step="1" value="25" />
</div>
<div class="range-wrapper">
<label for="shadow-opacity">Shadow Opacity :</label>
<input type="range" id="shadow-opacity" min="0" max="1" step="0.1" value="0.5" />
</div>
<div class="input-wrapper">
<label for="inset-shadow">Inset Shadow :</label>
<input type="checkbox" id="inset-shadow" />
</div>
<div id="color-wrapper">
<label for="shadow-color">Shadow Color :</label>
<input type="color" id="shadow-color" />
</div>
</div>
<div class="code-container">
<textarea id="styles" rows="2"></textarea>
<button id="copy-styles" onclick="copyStyles()">Copy Styles</button>
</div>
</div>
<script src="index.js"></script>
</body>
需要注意的点
<input type='range'>
就是那个滑块,可以指定最小值,最大值,步进值,初始值(min, max, step, value)<input type='color'>
是颜色选择器, 可选RGB,hSL,HEX<textarea rows="2"></textarea>
文本框,输入区域设置默认显示2行文本
style样式
.settings
和.code-container
用grid布局实现,grid-template-columns
按比例分布.settings
里面的.range-wrapper
input标签等用flex布局 主轴为列 再space-between
实现- 点击copy会有个animation, 动画周期到50%处
button
放大1.1倍
:root {
--bg: #311b92;
}
body {
background-color: var(--bg);
}
label {
font-size: 14px;
}
input {
cursor: pointer;
}
input[type='color'] {
width: 25px;
height: 25px;
border: 1px solid #ccc;
}
textarea {
resize: none;
padding: 5px;
border: 1px solid #000;
border-radius: 5px;
}
.container {
background-color: #fff;
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
padding: 30px;
width: 80vmin;
border-radius: 25px;
}
.result {
padding: 20px 0 120px;
}
#preview {
background-color: var(--bg);
width: 200px;
height: 200px;
position: relative;
margin: auto;
}
.settings {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px 25px;
}
.range-wrapper {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.code-container {
display: grid;
grid-template-columns: 3fr 1fr;
gap: 10px;
margin-top: 20px;
}
.code-container button {
background-color: var(--bg);
border-radius: 5px;
cursor: pointer;
border: none;
color: #fff;
}
.input-wrapper,
#color-wrapper {
display: flex;
align-items: center;
gap: 10px;
}
.copy-success-animation {
animation: copied 1s ease-in-out;
}
@keyframes copied {
50% {
transform: scale(1.1);
}
}
js
当每个input滑块改变时都要响应式地应用效果,都需要监听input
事件的触发, 给每一个input都绑定generateStyles事件来响应效果
const ranges = document.querySelectorAll('.settings input')
ranges.forEach(slider => {
slider.addEventListener('input', generateStyles)
})
generateStyles实现
- 获取DOM元素value值,然后拼装成box-shadow参数
DOM.style.
语法 给DOM添加box-shadow
和border-radius
样式DOM.textContent
语法 替换code-container
中的文字框文本
const preview = document.getElementById('preview') // demo方块
const styles = document.getElementById('styles') // box-shadow 代码文本框
function generateStyles() {
const xShadow = document.getElementById('x-shadow').value
const yShadow = document.getElementById('y-shadow').value
const blurRadius = document.getElementById('blur-r').value
const spreadRadius = document.getElementById('spread-r').value
const shadowColor = document.getElementById('shadow-color').value
const shadowOpacity = document.getElementById('shadow-opacity').value
const shadowInset = document.getElementById('inset-shadow').checked
const borderRadius = document.getElementById('border-r').value
const boxShadow = `${
shadowInset ? 'inset ' : ''
} ${xShadow}px ${yShadow}px ${blurRadius}px ${spreadRadius}px ${hexToRgba(
shadowColor,
shadowOpacity
)}`
preview.style.boxShadow = boxShadow
preview.style.borderRadius = `${borderRadius}px`
styles.textContent = `box-shadow: ${boxShadow};\nborder-radius: ${borderRadius}px;`
}
由于shadowColor其实是HEX格式,需要写个hexToRgba
方法转化为rgba格式
hexToRgba
- substr(start, length) 第一个参数是起始索引,第二个参数是截取长度
parseInt(hexStr, 16)
将十六进制转换为十进制 例子 : shadowColor = '#2a203c' 其中 r = '2a'; g = '20'; b = '3c'
// 16进制转换为rgba
function hexToRgba(shadowColor, shadowOpacity) {
const r = parseInt(shadowColor.substr(1, 2), 16)
const g = parseInt(shadowColor.substr(3, 2), 16)
const b = parseInt(shadowColor.substr(5, 2), 16)
return `rgba(${r}, ${g}, ${b}, ${shadowOpacity})`
}
copyStyles复制到剪切板
- 当我们点击复制样式按钮时,通过
Clipboard Api
实现复制到剪切板 - .then等待执行完,copyButton直接添加
animation
样式,更换innerText
, - 再用
setTimeout
1s之后移除animation
和复原innerText
。 那为啥1s? 因为动画也是1s 保持统一咯
function copyStyles() {
styles.select()
const textToCopy = styles.value
navigator.clipboard
.writeText(textToCopy)
.then(() => {
copyButton.innerText = '复制成功!🎉'
copyButton.classList.add('animation')
setTimeout(() => {
copyButton.innerText = '复制样式'
copyButton.classList.remove('animation')
}, 1000)
})
.catch(() => {
copyButton.innerText = '复制失败 😔'
})
}
代码片段
box-shadow推荐网站
box-shadow.art
样式超多,一键复制,还可自己DIY