如何用css做一个打印机🖨️?
先看效果
在表单中输入https://source.unsplash.com/random
或其他图片url试试吧~
用css制作3d场景, 一般情况下都是长方体的组合。其实没有想的那么复杂,大家有兴趣可以看看用 CSS 制作 3D 这篇文章。
而要制作一个长方体,我们可以使用 CSS 属性transform-style
. 将此设置为preserve-3d
允许我们在第三维上转换元素:
现在我们可以利用 CSS 自定义属性来定义长方体的属性(如上面代码片段) 使用自定义属性,我们可以控制长方体的各种特征,等等:
--width
: 平面上长方体的宽度--height
: 平面上长方体的高度--depth
: 平面上长方体的深度--x
: 平面上的 X 位置--y
: 平面上的 Y 位置
知道了相关的操作我们便可以开始制作一个打印机🖨️demo了
先来一个demo
首先,我们可以搭建出我们需要的所有部分,首先可以尝试将所有内容可视化成为一个个盒子。
// 结构大概是这样
.scene
.printer //打印机
.printer__side.printer__side--left
.printer__side.printer__side--right
.printer__tray.printer__tray--bottom
.printer__tray.printer__tray--top
.printer__top
.printer__back
基本的框架就像这样 代码上可以看到其实就是一个个的立方体拼接起来的,值得一提如果你使用Dat.GUI可以很方便调整这些参数
再加点细节
为了让你的打印机更真实,我们可以用css来添加: 例如打印机的顶部你可以加一个你的logo,打印机的开口等等......
渐变处理打印机的开启和细节:
.cuboid--top {
--thickness: var(--depth);
--shade-one: linear-gradient(#292929, #292929) 100% 50%/14% 54% no-repeat, linear-gradient(var(--p-7), var(--p-7)) 40% 50%/12% 32% no-repeat, linear-gradient(var(--p-7), var(--p-7)) 30% 50%/2% 12% no-repeat, linear-gradient(var(--p-3), var(--p-3)) 0% 50%/66% 50% no-repeat, var(--p-1);
}
还可以用 background-image
来做一个伪元素将其定位到打印机顶部来做打印机的log:
.cuboid--top > div:nth-of-type(1):after {
content: '';
position: absolute;
top: 7%;
left: 10%;
height: calc(var(--depth) * 0.12vmin);
width: calc(var(--depth) * 0.12vmin);
background: url("https://avatars.githubusercontent.com/u/36911813?s=400&u=102d1c03c513387ec81e0645738f654b23470ad7&v=4");
background-size: cover;
transform: rotate(90deg);
filter: grayscale(0.5);
}
纸张飞舞📄
有了打印机怎么能没纸呢,同理 我们可以用长方体来当作纸,然后使用多个堆叠就是纸堆啦,而我们要的效果是纸张从打印机进入 然后打印出我们想要的东西。样式如下
:root {
--load-speed: 2;
}
.paper-stack--top .cuboid--paper .paper {
animation: transfer calc(var(--load-speed) * 0.5s) ease-in-out forwards;
}
.paper-stack--top .cuboid--paper .paper__flyer {
animation: fly calc(var(--load-speed) * 0.5s) ease-in-out forwards;
}
.paper-stack--top .cuboid--paper .paper__flyer:after {
animation: feed calc(var(--load-speed) * 0.5s) calc(var(--load-speed) * 0.5s) forwards;
}
@keyframes transfer {
to {
transform: translate(0, -270%) rotate(22deg);
}
}
@keyframes feed {
to {
transform: translate(100%, 0);
}
}
@keyframes fly {
0% {
transform: translate3d(0, 0, 0) rotateY(0deg) translate(0, 0);
}
50% {
transform: translate3d(140%, 0, calc(var(--height) * 1.2)) rotateY(-75deg) translate(180%, 0);
}
100% {
transform: translate3d(140%, 0, var(--height)) rotateY(-75deg) translate(0%, 0) rotate(-180deg);
}
}
我们可以使用 CSS 自定义属性。来计算每个动画的正确延迟。纸张同时旋转和移动。一个动画处理移动容器,另一个动画处理旋转纸张。等动画结束,纸张就会被送入打印机,而动画延迟等于前两个动画的持续时间。然后纸张被定位到该元素的边缘。
这里分别标记了几个颜色来区别不同的元素,你可以更好的看到他是如何工作的
打印时间到
打印机当然是需要能够打印东西啦,这里我们接受一个图片的url,例如(source.unsplash.com/random)当然你也可以用其他的
获得图像源后,我们将预览图像src设置为该URL的值并重置表单的输入值,我们可以监听预览图像的“load”事件。当事件触发时,我们为要打印的纸创建一个新元素并将其附加到printer
元素上。
PREVIEW.addEventListener('load', () => {
PRINTER.classList.add('printing')
const PRINT = document.createElement('div')
PRINT.className = 'printed'
PRINT.innerHTML = `
<div class="printed__spinner">
<div class="printed__paper">
<div class="printed__papiere">
<img class="printed__image" src=${PREVIEW.src}/>
</div>
</div>
<div class="printed__paper-back"></div>
</div>
`
PRINTER.appendChild(PRINT)
// 过几秒再把打印机重置回待打印状态
setTimeout(() => {
printing = false
SUBMIT.removeAttribute('disabled')
PRINTER.classList.remove('printing')
}, 4500)
})
你甚至可以加个指示灯表示正在打印中
.progress-light {
background: hsla(var(--progress-hue, 104), 80%, 50%);
}
.printing {
--progress-hue: 10; /* Equates to red */
}
如此你的打印机就制作完成啦
转载自:https://juejin.cn/post/7156436852176584717