Desde hace un tiempo, he estado creando estas escenas 3D con CSS por diversión, generalmente en mi transmisión en vivo.
¡Avión de acrobacias 3D CSS! 🛩️
¡Hace bucles y rollos! 😎
Responde al movimiento del ratón 🐭
👉 https://t.co/A1zNmfEzzi a través de @CodePen pic.twitter.com/87D7LIXLr2
— Jhey 🐻🛠 (Exploring Opportunities ✨) (@jh3yy) March 27, 2021
Cada demo es una oportunidad para probar algo diferente o encontrar maneras de hacer cosas con CSS. Una cosa que a menudo hago es tomar sugerencias sobre lo que deberíamos intentar crear en la transmisión. Una sugerencia reciente fue una impresora que imprime en “3D”. ¡Y esto es lo que armé!
¡📢 La Imprenta CSS está abierta para el negocio! 😅
¡Impresión gratis! 😮
Ingrese una URL de imagen para verla impresa por la Impresora 3D CSS 😁
👉 https://t.co/UWTDAyUadn a través de @CodePen pic.twitter.com/z3q9dJavYv
— Jhey 🐻🛠 (Exploring Opportunities ✨) (@jh3yy) April 22, 2021
Haciendo cosas 3D con CSS
I’ve written about making things 3D with CSS before. The general gist is that most scenes are a composition of cuboids.
Para hacer un cuboide, podemos usar transformaciones CSS para posicionar los lados de un cuboide, la propiedad mágica siendo transform-style
. Configurar esto en preserve-3d
nos permite transformar elementos en la tercera dimensión:
* {
transform-style: preserve-3d;
}
Una vez que creas algunas de estas escenas, comienzas a descubrir formas de acelerar las cosas. Me gusta usar Pug como preprocesador de HTML. La capacidad de mixin me permite crear cuboides más rápidamente. Los ejemplos de marcado en este artículo utilizan Pug. Pero para cada demostración de CodePen, puedes usar la opción “Ver HTML compilado” para ver la salida HTML:
mixin cuboid()
.cuboid(class!=attributes.class)
- let s = 0
while s < 6
.cuboid__side
- s++
Usar +cuboid()(class="printer__top")
producirá esto:
<div class="cuboid printer__top">
<div class="cuboid__side"></div>
<div class="cuboid__side"></div>
<div class="cuboid__side"></div>
<div class="cuboid__side"></div>
<div class="cuboid__side"></div>
<div class="cuboid__side"></div>
</div>
Luego, tengo un bloque de CSS que utilizo para organizar los cuboides. La alegría aquí es que podemos aprovechar las propiedades personalizadas de CSS para definir las propiedades de un cuboide (como se muestra en el video anterior):
.cuboid {
// Defaults
--width: 15;
--height: 10;
--depth: 4;
height: calc(var(--depth) * 1vmin);
width: calc(var(--width) * 1vmin);
transform-style: preserve-3d;
position: absolute;
font-size: 1rem;
transform: translate3d(0, 0, 5vmin);
}
.cuboid > div:nth-of-type(1) {
height: calc(var(--height) * 1vmin);
width: 100%;
transform-origin: 50% 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotateX(-90deg) translate3d(0, 0, calc((var(--depth) / 2) * 1vmin));
}
.cuboid > div:nth-of-type(2) {
height: calc(var(--height) * 1vmin);
width: 100%;
transform-origin: 50% 50%;
transform: translate(-50%, -50%) rotateX(-90deg) rotateY(180deg) translate3d(0, 0, calc((var(--depth) / 2) * 1vmin));
position: absolute;
top: 50%;
left: 50%;
}
.cuboid > div:nth-of-type(3) {
height: calc(var(--height) * 1vmin);
width: calc(var(--depth) * 1vmin);
transform: translate(-50%, -50%) rotateX(-90deg) rotateY(90deg) translate3d(0, 0, calc((var(--width) / 2) * 1vmin));
position: absolute;
top: 50%;
left: 50%;
}
.cuboid > div:nth-of-type(4) {
height: calc(var(--height) * 1vmin);
width: calc(var(--depth) * 1vmin);
transform: translate(-50%, -50%) rotateX(-90deg) rotateY(-90deg) translate3d(0, 0, calc((var(--width) / 2) * 1vmin));
position: absolute;
top: 50%;
left: 50%;
}
.cuboid > div:nth-of-type(5) {
height: calc(var(--depth) * 1vmin);
width: calc(var(--width) * 1vmin);
transform: translate(-50%, -50%) translate3d(0, 0, calc((var(--height) / 2) * 1vmin));
position: absolute;
top: 50%;
left: 50%;
}
.cuboid > div:nth-of-type(6) {
height: calc(var(--depth) * 1vmin);
width: calc(var(--width) * 1vmin);
transform: translate(-50%, -50%) translate3d(0, 0, calc((var(--height) / 2) * -1vmin)) rotateX(180deg);
position: absolute;
top: 50%;
left: 50%;
}
Usando propiedades personalizadas, podemos controlar varias características de los cuboides, y así sucesivamente:
--width
: el ancho de un cuboide en el plano--height
: la altura de un cuboide en el plano--depth
: la profundidad de un cuboide en el plano--x
: la posición X en el plano--y
: la posición Y en el plano
Esto no es muy impresionante hasta que colocamos el cuboide en una escena y lo rotamos. De nuevo, utilizo propiedades personalizadas para manipular la escena mientras trabajo en la creación de algo. Dat.GUI resulta muy útil aquí.
Si inspeccionas la demostración, usando el panel de control actualiza las propiedades CSS personalizadas en la escena. Este alcance de propiedades CSS personalizadas ahorra mucho código repetido y mantiene las cosas DRY.
Más de Una Forma
Al igual que muchas cosas en CSS, hay más de una forma de hacerlo. A menudo puedes componer una escena a partir de cuboides y posicionar las cosas cuando las necesites. Sin embargo, puede volverse complicado de gestionar. A menudo existe la necesidad de agrupar cosas o agregar algún tipo de contenedor.
Considera este ejemplo en el que la silla es su propia subescena que puede moverse.
Muchos ejemplos recientes no son tan complejos. He estado recurriendo a la extrusión. Esto significa que puedo trazar lo que estoy haciendo en elementos 2D. Por ejemplo, aquí hay un helicóptero que creé recientemente:
.helicopter
.helicopter__rotor
.helicopter__cockpit
.helicopter__base-light
.helicopter__chair
.helicopter__chair-back
.helicopter__chair-bottom
.helicopter__dashboard
.helicopter__tail
.helicopter__fin
.helicopter__triblade
.helicopter__tail-light
.helicopter__stabilizer
.helicopter__skids
.helicopter__skid--left.helicopter__skid
.helicopter__skid--right.helicopter__skid
.helicopter__wing
.helicopter__wing-light.helicopter__wing-light--left
.helicopter__wing-light.helicopter__wing-light--right
.helicopter__launchers
.helicopter__launcher.helicopter__launcher--left
.helicopter__launcher.helicopter__launcher--right
.helicopter__blades
Luego podemos colocar cuboides en todos los contenedores utilizando el mixin. Luego aplicar un “espesor” requerido a cada cuboide. El espesor queda dictado por propiedades personalizadas en ámbito. Este demo alterna la propiedad --thickness
para los cuboides que forman el helicóptero. Da una idea de cómo se veía el mapeo 2D para comenzar.
Ese es el resumen de cómo proceder para crear cosas 3D con CSS. Al profundizar en el código, sin duda se revelarán algunos trucos. Pero, en general, esqueletar una escena, poblarla con cuboides y colorear los cuboides. A menudo querrás diferentes tonos de un color para diferenciar los lados de un cuboide. Cualquier detalle extra son cosas que podemos agregar a un lado de un cuboide o transformaciones que podemos aplicar a un cuboide. Por ejemplo, rotar y mover en el eje Z.
Consideremos un ejemplo simplificado:
.scene
.extrusion
+cuboid()(class="extrusion__cuboid")
El nuevo CSS para crear un cuboide con extrusión podría verse así. Observa cómo estamos incluyendo propiedades personalizadas en ámbito para el color de cada lado también. Sería prudente incluir algunos valores predeterminados debajo del :root
aquí o valores de respaldo:
.cuboid {
width: 100%;
height: 100%;
position: relative;
}
.cuboid__side:nth-of-type(1) {
background: var(--shade-one);
height: calc(var(--thickness) * 1vmin);
width: 100%;
position: absolute;
top: 0;
transform: translate(0, -50%) rotateX(90deg);
}
.cuboid__side:nth-of-type(2) {
background: var(--shade-two);
height: 100%;
width: calc(var(--thickness) * 1vmin);
position: absolute;
top: 50%;
right: 0;
transform: translate(50%, -50%) rotateY(90deg);
}
.cuboid__side:nth-of-type(3) {
background: var(--shade-three);
width: 100%;
height: calc(var(--thickness) * 1vmin);
position: absolute;
bottom: 0;
transform: translate(0%, 50%) rotateX(90deg);
}
.cuboid__side:nth-of-type(4) {
background: var(--shade-two);
height: 100%;
width: calc(var(--thickness) * 1vmin);
position: absolute;
left: 0;
top: 50%;
transform: translate(-50%, -50%) rotateY(90deg);
}
.cuboid__side:nth-of-type(5) {
background: var(--shade-three);
height: 100%;
width: 100%;
transform: translate3d(0, 0, calc(var(--thickness) * 0.5vmin));
position: absolute;
top: 0;
left: 0;
}
.cuboid__side:nth-of-type(6) {
background: var(--shade-one);
height: 100%;
width: 100%;
transform: translate3d(0, 0, calc(var(--thickness) * -0.5vmin)) rotateY(180deg);
position: absolute;
top: 0;
left: 0;
}
Hemos optado por tres tonos para este ejemplo. Pero a veces puede necesitar más. Esta demo lo combina pero permite cambiar propiedades personalizadas en ámbito. El valor de “grosor” cambiará la extrusión del cuboide. Las transformaciones y dimensiones afectarán al elemento contenedor con la clase “extrusión”.
Escalonamiento de una Impresora
Para comenzar, podemos escalonar todas las piezas que necesitamos. Con la práctica esto se vuelve más obvio. Pero la regla general es tratar de visualizar todo como cajas. Eso te da una buena idea de cómo descomponer algo:
.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
Trata de visualizar lo que estamos buscando aquí. Las dos piezas laterales dejan un espacio en el medio. Luego tenemos un cuboide que se coloca en la parte superior y otro que llena la parte posterior. Luego, dos cuboides para formar la bandeja de papel.
Una vez que estés en esa etapa, se trata de poblar los cuboides, que se ve así:
.scene
.printer
.printer__side.printer__side--left
+cuboid()(class="cuboid--side")
.printer__side.printer__side--right
+cuboid()(class="cuboid--side")
.printer__tray.printer__tray--bottom
+cuboid()(class="cuboid--tray")
.printer__tray.printer__tray--top
+cuboid()(class="cuboid--tray")
.printer__top
+cuboid()(class="cuboid--top")
.printer__back
+cuboid()(class="cuboid--back")
Fíjate cómo somos capaces de reutilizar los nombres de clase como cuboid--side
. Esos cuboides probablemente tengan el mismo grosor y usen los mismos colores. Su posición y tamaño se dictan por el elemento contenedor.
Uniendo las piezas, podemos obtener algo como esto.
La explosión de la demo muestra los diferentes cuboides que componen la impresora. Si apagas la extrusión, puedes ver los elementos contenedores planos.
Añadiendo Detalle
Ahora, es posible que hayas notado que hay más detalle que simplemente añadir colores a cada lado. Y esto se reduce a encontrar formas de añadir detalles adicionales. Tenemos diferentes opciones dependiendo de lo que queramos añadir.
Si se trata de una imagen o algunos cambios de color básicos, podemos aprovechar el background-image
para superponer gradientes, y así sucesivamente.
Por ejemplo, la parte superior de la impresora tiene detalles, así como la apertura de la impresora. Este código aborda el lado superior del cuboide superior. El gradiente maneja la apertura de la impresora y los detalles:
.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);
}
Para el logo del oso, podríamos usar un background-image
o incluso recurrir a un pseudo-elemento y posicionarlo:
.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://assets.codepen.io/605876/avatar.png");
background-size: cover;
transform: rotate(90deg);
filter: grayscale(0.5);
}
Si necesitamos agregar detalles más extensos, probablemente tendremos que salir de usar nuestro mixin de cuboide. Por ejemplo, la parte superior de nuestra impresora tendrá una pantalla de vista previa utilizando un img
elemento:
.printer__top
.cuboid.cuboid--top
.cuboid__side
.cuboid__side
.cuboid__side
.cuboid__side
.screen
.screen__preview
img.screen__preview-img
.cuboid__side
.cuboid__side
Agregue algunos detalles más y estamos listos para agregar papel al proceso!
Viaje del Papel
¿Qué es una impresora sin papel? Queremos animar un poco de papel volando hacia la impresora y saliendo por el otro extremo. Algo como esta demo: haga clic en cualquier lugar para ver una hoja de papel alimentada en la impresora e impresa.
Podemos agregar un bloque de papel a la escena con un cuboide y luego usar un elemento separado para actuar como una sola hoja de papel:
.paper-stack.paper-stack--bottom
+cuboid()(class="cuboid--paper")
.paper-stack.paper-stack--top
.cuboid.cuboid--paper
.cuboid__side
.paper
.paper__flyer
.cuboid__side
.cuboid__side
.cuboid__side
.cuboid__side
.cuboid__side
Pero animar el papel volando hacia la impresora requiere algo de prueba y error. Es conveniente jugar con diferentes transformaciones en el inspector de DevTools. Esta es una buena manera de ver cómo se verán las cosas. A menudo, también es más fácil usar elementos envolventes. Utilizamos el elemento .paper
para hacer la transferencia y luego usamos .paper__flyer
para animar la alimentación del papel:
: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);
}
}
Notarás que hay bastante uso de calc
allí. Para componer la cronología de la animación, podemos aprovechar las propiedades personalizadas de CSS. Al referirnos a una propiedad, podemos calcular los retardos correctos para cada animación en la cadena. La transferencia de papel y vuela al mismo tiempo. Una animación maneja el movimiento del contenedor, otra maneja la rotación del papel. Una vez que finalizan esas animaciones, el papel se introduce en la impresora con la animación feed
. El retraso de la animación es igual a la duración de las dos primeras animaciones que se ejecutan al mismo tiempo.
Ejecuta esta demo donde he coloreado los elementos del contenedor de rojo y verde. Utilizamos el pseudo-elemento de .paper__flyer
para representar la hoja de papel. Pero los elementos del contenedor hacen el trabajo duro:
Quizás te estés preguntando cuándo sale el papel por el otro extremo. Pero, de hecho, el papel no es el mismo elemento a lo largo de todo el proceso. Usamos un elemento para que entre en la impresora. Y otro elemento para el papel cuando vuela fuera de la impresora. Este es otro caso en el que elementos adicionales facilitan nuestra vida.
El papel utiliza más de un elemento para hacer el bucle, y luego el papel se posiciona en el borde de ese elemento. Ejecutar esta demo con más elementos de contenedor coloreados muestra cómo funciona.
Una vez más, requiere un poco de ensayo y error, así como pensar en cómo podemos aprovechar el uso de elementos de contenedor. Tener un contenedor con un transform-origin
de desplazamiento nos permite crear el bucle.
Impresión
Tenemos todo en su lugar. Ahora se trata de imprimir algo realmente. Para ello, vamos a agregar un formulario que permita a los usuarios introducir la URL de una imagen:
form.customer-form
label(for="print") Print URL
input#print(type='url' required placeholder="URL for Printing")
input(type="submit" value="Print")
Con algo de estilo, obtenemos algo como esto.
El comportamiento nativo de los formularios y el uso de required
y type="url"
significa que solo aceptamos una URL. Podríamos ir más allá con un pattern
y verificar ciertos tipos de imágenes. Pero algunas buenas URLs para imágenes aleatorias no incluyen el tipo de imagen, como https://source.unsplash.com/random.
Enviar nuestro formulario no se comporta como queremos, y también la animación de impresión se ejecuta una vez al cargar. Una forma de solucionarlo sería ejecutar la animación solo cuando se aplica un cierto clase al impresor.
Cuando enviamos el formulario, podemos hacer una solicitud para la URL y luego establecer el src
para las imágenes en nuestra escena — una imagen siendo la vista previa en la pantalla de la impresora, la otra siendo una imagen en un lado del papel. De hecho, cuando imprimimos, vamos a agregar un nuevo elemento para cada pieza de papel impresa. De esa manera, cada impresión parece que se añade a una pila. Podemos eliminar la pieza de papel que tenemos al cargar.
Empecemos por manejar la presentación del formulario. Vamos a evitar el evento por defecto y llamar a una función PROCESS
:
const PRINT = e => {
e.preventDefault()
PROCESS()
}
const PRINT_FORM = document.querySelector('form')
PRINT_FORM.addEventListener('submit', PRINT)
Esta función manejará la solicitud de nuestra fuente de imagen:
let printing = false
const PREVIEW = document.querySelector('img.screen__preview-img')
const SUBMIT = document.querySelector('[type="submit"]')
const URL_INPUT = document.querySelector('[type="url"]')
const PROCESS = async () => {
if (printing) return
printing = true
SUBMIT.disabled = true
const res = await fetch(URL_INPUT.value)
PREVIEW.src = res.url
URL_INPUT.value = ''
}
También establecemos una variable printing
en true
, que utilizaremos para rastrear el estado actual y deshabilitar el botón del formulario.
¿Por qué hacemos una solicitud para la imagen en lugar de establecerla en la imagen? Queremos una URL absoluta a una imagen. Si usamos la URL de “Unsplash” mencionada anteriormente y luego la compartimos entre las imágenes, esto podría no funcionar. Eso se debe a que podemos encontrarnos en escenarios en los que se muestran imágenes diferentes.
Una vez que tenemos la fuente de la imagen, establecemos la fuente de la imagen previa en esa URL y reiniciamos el valor de entrada del formulario.
Para activar la animación, podemos engancharnos al evento “cargar” de nuestra imagen previa. Cuando se dispara el evento, creamos un nuevo elemento para la hoja de papel a imprimir y lo adjuntamos al elemento printer
. Al mismo tiempo, agregamos una clase printing
a nuestro impresor. Podemos usar esto para activar la primera parte de nuestra animación de papel:
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)
// Después de un tiempo determinado, reiniciar el estado
setTimeout(() => {
printing = false
SUBMIT.removeAttribute('disabled')
PRINTER.classList.remove('printing')
}, 4500)
})
Después de un tiempo determinado, podemos reiniciar el estado. Un enfoque alternativo sería desacoplar un evento animationend
de burbujeo. Pero podemos usar un setTimeout
, ya que sabemos cuánto tiempo durará la animación.
Sin embargo, nuestra impresión no está a la escala correcta. Y eso se debe a que necesitamos escalar la imagen al trozo de papel. Necesitamos un pequeño trozo de CSS para esto:
.printed__image {
height: 100%;
width: 100%;
object-fit: cover;
}
También sería genial si las luces en la parte delantera de la impresora comunicaran que la impresora está ocupada. Podríamos ajustar el tono de una de las luces cuando la impresora está imprimiendo:
.progress-light {
background: hsla(var(--progress-hue, 104), 80%, 50%);
}
.printing {
--progress-hue: 10; /* Equivale al rojo */
}
Juntando todo, tenemos una “impresora” funcional hecha con CSS y un toque de JavaScript.
¡Eso es!
Hemos revisado cómo podemos crear una impresora 3D funcional con CSS, un toque de JavaScript y aprovechando Pug. Prueba agregando el siguiente enlace de imagen en el campo de URL, o otro de tu elección, y pruébalo!
https://source.unsplash.com/random
Cubrimos un montón de cosas diferentes para lograr esto, incluyendo estas:
- cómo hacer cosas 3D con CSS
- usando mixins de Pug
- usando propiedades CSS personalizadas en ámbito para mantener las cosas DRY
- usando extrusión para crear escenas 3D
- manejando formularios con JavaScript
- componiendo cronogramas de animación con propiedades personalizadas
La alegría de crear estos demos es que muchos de ellos plantean diferentes problemas para superar, como cómo crear ciertas formas o construir ciertas animaciones. A menudo hay más de una forma de hacer algo.
¿Qué cosas geniales podrías hacer con CSS 3D? ¡Me encantaría verlo!
Como siempre, gracias por leer. ¿Quieres ver más? Ven a encontrarme en Twitter o mira mi transmisión en vivo!
Preguntas Frecuentes (FAQs) sobre Impresora 3D CSS
¿Qué es una Impresora 3D CSS?
A 3D CSS Printer is a unique concept that uses Cascading Style Sheets (CSS), a style sheet language used for describing the look and formatting of a document written in HTML, to create a 3D representation of a printer. This innovative approach allows developers to create interactive and visually appealing web elements that can enhance user experience.
¿Cómo funciona una Impresora 3D CSS?
A 3D CSS Printer works by using CSS properties to create a 3D model of a printer. It uses properties such as transform, perspective, and animation to create the 3D effect. The printer is made up of multiple elements, each styled and positioned to create the overall 3D effect. The animation property is then used to create the printing effect.
¿Puedo personalizar la Impresora 3D CSS?
Sí, puedes personalizar la Impresora 3D CSS. Puedes cambiar los colores, el tamaño e incluso la velocidad de la animación. Esto se logra modificando las propiedades CSS de la impresora. Por ejemplo, puedes cambiar el color modificando la propiedad background-color de los elementos de la impresora.
¿Cómo puedo integrar una Impresora 3D CSS en mi sitio web?
Integrar una Impresora 3D CSS en tu sitio web implica copiar el código CSS y HTML en el código de tu sitio. Debes asegurarte de que el código CSS se incluya en la sección head del documento HTML, y que el código HTML se coloque donde desees que aparezca la impresora en tu página web.
¿Es posible animar la Impresora 3D CSS?
Sí, es posible animar la Impresora 3D CSS. La animación se logra utilizando la propiedad CSS animation. Esta propiedad te permite crear keyframes que definen los estados inicial y final de la animación, así como cualquier paso intermedio.
¿Qué navegadores soportan la Impresora 3D CSS?
La Impresora 3D CSS debería funcionar en todos los navegadores modernos que soporten las propiedades CSS transform y animation. Esto incluye navegadores como Google Chrome, Mozilla Firefox, Safari y Microsoft Edge.
¿Puedo usar la Impresora 3D CSS para fines comerciales?
Sí, puedes usar la Impresora 3D CSS para fines comerciales. Sin embargo, siempre es una buena idea verificar los términos de licencia de cualquier código que utilices para asegurarte de que estás en cumplimiento.
¿Qué habilidades necesito para crear una Impresora 3D CSS?
Para crear una Impresora CSS 3D, necesitas una buena comprensión de HTML y CSS. Debes estar familiarizado con propiedades CSS como transform, perspective y animation. Conocimientos básicos de modelado 3D también pueden ser útiles, pero no es necesario.
¿Puedo usar JavaScript con la Impresora CSS 3D?
Sí, puedes usar JavaScript con la Impresora CSS 3D. Aunque la impresora puede ser creada únicamente con CSS, JavaScript puede ser utilizado para agregar interactividad, como iniciar o detener la animación basándose en acciones del usuario.
¿Hay recursos para aprender más sobre la Impresora CSS 3D?
Existen muchos recursos en línea para aprender más sobre la Impresora CSS 3D. Sitios web como SitePoint, CSS-Tricks y MDN Web Docs tienen tutoriales y guías extensas sobre animaciones CSS y transformaciones 3D. YouTube también cuenta con muchos tutoriales en video sobre el tema.