Crie uma Impressora 3D CSS que Realmente Imprime!

Por algum tempo, tenho criado essas cenas 3D com CSS apenas por diversão — geralmente durante minha transmissão ao vivo.

Cada demonstração é uma oportunidade para tentar algo diferente ou descobrir maneiras de fazer coisas com CSS. Uma coisa que frequentemente faço é aceitar sugestões sobre o que devemos tentar criar na transmissão. Uma sugestão recente foi uma impressora que imprime em “3D”. E aqui está o que eu montei!

Criando Coisas 3D com CSS

I’ve written about making things 3D with CSS before. The general gist is that most scenes are a composition of cuboids.

Para criar um cuboide, podemos usar transformações CSS para posicionar os lados de um cuboide — a propriedade mágica sendo transform-style. Configurando isso para preserve-3d nos permite transformar elementos na terceira dimensão:

* {
  transform-style: preserve-3d;
}

Uma vez que você cria algumas dessas cenas, começa a descobrir maneiras de agilizar as coisas. Eu gosto de usar o Pug como pré-processador HTML. A capacidade de mixins me dá uma maneira de criar cuboides mais rapidamente. Os exemplos de marcação deste artigo usam Pug. Mas para cada demonstração CodePen, você pode usar a opção “Ver HTML Compilado” para ver a saída HTML:

mixin cuboid()
  .cuboid(class!=attributes.class)
    - let s = 0
    while s < 6
      .cuboid__side
      - s++

Usar +cuboid()(class="printer__top") produz isto:

<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>

Então, eu tenho um bloco de CSS que utilizo para dispor os cuboides. A alegria aqui é que podemos aproveitar propriedades CSS personalizadas para definir as propriedades de um cuboide (como mostrado no vídeo acima):

.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 propriedades personalizadas, podemos controlar várias características dos cuboides, e assim por diante:

  • --width: a largura de um cuboide no plano
  • --height: a altura de um cuboide no plano
  • --depth: a profundidade de um cuboide no plano
  • --x: a posição X no plano
  • --y: a posição Y no plano

Isso não é muito impressionante até colocarmos o cuboide em uma cena e rotacioná-lo. Mais uma vez, eu uso propriedades personalizadas para manipular a cena enquanto trabalho na criação de algo. Dat.GUI é extremamente útil aqui.

Se você inspecionar a demonstração, usando o painel de controle atualiza as propriedades CSS personalizadas na cena. Essa escopagem de propriedades CSS personalizadas economiza muito código repetido e mantém as coisas DRY.

Mais de Uma Maneira

Assim como muitas coisas no CSS, há mais de uma maneira de fazê-lo. Muitas vezes, você pode compor uma cena a partir de cubóides e posicionar as coisas conforme necessário. No entanto, pode se tornar complicado de gerenciar. Muitas vezes há a necessidade de agrupar coisas ou adicionar algum tipo de container.

Considere este exemplo em que a cadeira é sua própria sub-cena que pode ser movida.

Muitos exemplos recentes não são tão complexos. Tenho recorrido à extrusão. Isso significa que posso mapear o que estou fazendo em elementos 2D. Por exemplo, aqui está um helicóptero que criei recentemente:

.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

Em seguida, podemos colocar cubóides em todos os containers usando o mixin. Em seguida, aplicar uma “espessura” necessária a cada cubóide. A espessura é determinada por propriedades customizadas delimitadas. Este demo alterna a propriedade --thickness para os cubóides que compõem o helicóptero. Isso dá uma ideia de como o mapeamento 2D se parecia para começar.

Essa é a essência de como proceder para criar coisas 3D com CSS. Ao investigar o código, certamente serão descobertos alguns truques. Mas, em geral, monte uma cena, preencha com cubóides e colora os cubóides. Geralmente, você desejará algumas tonalidades diferentes de uma cor para que possamos diferenciar os lados de um cubóide. Eventuais detalhes extras são coisas que podemos adicionar a um lado do cubóide ou transformações que podemos aplicar a um cubóide. Por exemplo, girando e movendo no eixo Z.

Vamos considerar um exemplo simplificado:

.scene
  .extrusion
    +cuboid()(class="extrusion__cuboid")

O novo CSS para criar um cubóide com extrusão poderia ser assim. Observe como estamos incluindo propriedades customizadas delimitadas para a cor de cada lado também. Seria prudente adicionar alguns valores padrão sob o :root aqui ou valores de fallback:

.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;
}

Optamos por três tons para este exemplo. Mas às vezes você pode precisar de mais. Este demo monta isso, mas permite que você altere propriedades personalizadas encaixadas. O valor de “espessura” mudará a extrusão do cuboide. As transformações e dimensões afetarão o elemento contido com a classe “extrusão”.

Escorando uma Impressora

Para começar, podemos esboçar todas as peças necessárias. Com prática isso se torna mais óbvio. Mas a regra geral é tentar visualizar tudo como caixas. Isso lhe dá uma boa ideia de como dividir 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

Veja se consegue visualizar o que estamos buscando aqui. As duas peças laterais deixam uma lacuna no meio. Então temos um cuboide que se estende pelo topo e um que preenche a parte de trás. Em seguida, dois cuboides para compor a bandeja de papel.

Uma vez que você chega a esse estágio, é uma questão de preencher os cuboides, o que se parece com isto:

.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")      

Observe como somos capazes de reutilizar nomes de classes como cuboid--side. Esses cuboides provavelmente terão a mesma espessura e usarão as mesmas cores. Sua posição e tamanho são determinados pelo elemento contido.

Juntando tudo, podemos obter algo assim.

A explosão do demo mostra os diferentes cuboides que compõem a impressora. Se você desativar a extrusão, poderá ver os elementos contidos planos.

Adicionando Alguns Detalhes

Agora, você pode ter notado que há mais detalhes do que você obteria apenas adicionando cores a cada lado. E isso se resume a encontrar maneiras de adicionar detalhes extras. Temos opções diferentes dependendo do que queremos adicionar.

Se for uma imagem ou algumas mudanças básicas de cor, podemos usar o `background-image` para criar camadas de gradientes, e assim por diante.

Por exemplo, o topo da impressora possui detalhes, bem como a abertura da impressora. Este código aborda o lado superior do cubóide superior. O gradiente lida com a abertura da impressora e os detalhes:

.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 o logotipo do urso, poderíamos usar um `background-image` ou até mesmo recorrer a um pseudo-elemento e posicioná-lo:

.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);
}

Se precisarmos adicionar detalhes mais extensos, provavelmente teremos que sair do uso do nosso mixin de cubóide. Por exemplo, o topo da nossa impressora terá uma tela de visualização usando um elemento `img`:

.printer__top
  .cuboid.cuboid--top
    .cuboid__side
    .cuboid__side
    .cuboid__side
    .cuboid__side
      .screen
        .screen__preview
          img.screen__preview-img
    .cuboid__side
    .cuboid__side

Adicione mais alguns detalhes e estaremos prontos para colocar papel na mistura!

Jornada do Papel

O que é uma impressora sem um pouco de papel? Queremos animar algum papel voando para a impressora e sendo atirado para fora do outro lado. Algo como este demo: clique em qualquer lugar para ver um pedaço de papel sendo alimentado na impressora e impresso.

Podemos adicionar um bloco de papel à cena com um cubóide e, em seguida, usar um elemento separado para agir como uma única folha 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

Mas animar o papel voando para a impressora requer algumas tentativas e erros. É prudente experimentar diferentes transformações no inspetor do DevTools. Esta é uma boa maneira de ver como as coisas ficarão. Muitas vezes, também é mais fácil usar elementos envoltórios. Usamos o elemento `.paper` para fazer a transferência e, em seguida, usamos `.paper__flyer` para animar a alimentação do 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);
  }
}

Você notará que há uma quantidade razoável de uso de calc lá. Para compor a linha do tempo da animação, podemos fazer uso das propriedades personalizadas do CSS. Referenciando uma propriedade, podemos calcular os atrasos corretos para cada animação na cadeia. O papel transfere e voa ao mesmo tempo. Uma animação lida com o movimento do contêiner, outra com a rotação do papel. Uma vez que essas animações terminam, o papel é alimentado na impressora com a animação feed. O atraso da animação é igual à duração das duas primeiras animações que funcionam ao mesmo tempo.

Execute este demo onde eu colori os elementos do contêiner em vermelho e verde. Fazemos uso do pseudo-elemento de .paper__flyer para representar o pedaço de papel. Mas os elementos do contêiner fazem o trabalho pesado:

Você pode estar se perguntando quando o papel sai do outro lado. Mas, na verdade, o papel não é o mesmo elemento durante todo o processo. Usamos um elemento para entrar na impressora. E outro elemento para o papel quando ele voa para fora da impressora. Este é outro exemplo em que elementos extras facilitam nossa vida.

O papel usa mais de um elemento para fazer o loop e, em seguida, o papel é posicionado na borda desse elemento. Executando este demo com mais elementos de contêiner coloridos mostra como isso está funcionando.

Mais uma vez, isso requer um pouco de tentativa e erro, bem como pensar sobre como podemos aproveitar o uso de elementos de contêiner. Ter um contêiner com um transform-origin com deslocamento nos permite criar o loop.

Impressão

Temos tudo pronto. Agora é questão de realmente imprimir algo. Para isso, vamos adicionar um formulário que permite que os usuários insiram a URL de uma imagem:

form.customer-form
  label(for="print") Print URL
  input#print(type='url' required placeholder="URL for Printing")
  input(type="submit" value="Print")

Com algum estilo, obtemos algo assim.

O comportamento nativo dos formulários e o uso de required e type="url" significa que só aceitamos uma URL. Poderíamos aprofundar isso com um pattern e verificar certos tipos de imagem. Mas algumas URLs aleatórias de boas imagens não incluem o tipo de imagem, como https://source.unsplash.com/random.

Enviar nosso formulário não se comporta como queremos, e também a animação de impressão é executada uma vez na carga. Uma maneira de contornar isso seria executar a animação apenas quando uma classe específica for aplicada à impressora.

Quando submetemos o formulário, podemos fazer uma requisição para a URL e, em seguida, definir o src para as imagens em nossa cena — uma imagem sendo a pré-visualização na tela da impressora, a outra sendo uma imagem em um lado do papel. De fato, ao imprimir, vamos adicionar um novo elemento para cada pedaço de papel impresso. Assim, cada impressão parece ser adicionada a uma pilha. Podemos remover o pedaço de papel que temos na carga.

Vamos começar tratando a submissão do formulário. Vamos impedir o evento padrão e chamar uma função PROCESS:

const PRINT = e => {
  e.preventDefault()
  PROCESS()
}

const PRINT_FORM = document.querySelector('form')
PRINT_FORM.addEventListener('submit', PRINT)

Esta função lidará com a requisição para a nossa fonte de imagem:

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 = ''
}

Também definimos uma variável printing como true, que usaremos para rastrear o estado atual e desabilitar o botão do formulário.

Por que fazemos uma solicitação para a imagem em vez de definir no próprio elemento de imagem? Queremos uma URL absoluta para uma imagem. Se usarmos a URL da “Unsplash” mencionada acima e a compartilharmos entre as imagens, isso pode não funcionar. Isso ocorre porque podemos enfrentar cenários em que diferentes imagens são exibidas.

Uma vez que temos a fonte de imagem, definimos a fonte da imagem de visualização para essa URL e redefinimos o valor de entrada do formulário.

Para acionar a animação, podemos nos conectar ao evento “load” de nossa imagem de visualização. Quando o evento é disparado, criamos um novo elemento para a folha de papel a ser impressa e o anexamos ao elemento printer. Ao mesmo tempo, adicionamos uma classe printing ao nosso impressor. Podemos usar isso para acionar a primeira parte de nossa animação 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)
  // Após um determinado período de tempo, redefinir o estado
  setTimeout(() => {
    printing = false
    SUBMIT.removeAttribute('disabled')
    PRINTER.classList.remove('printing')
  }, 4500)
})

Após um determinado período de tempo, podemos redefinir o estado. Uma abordagem alternativa seria debilitar um evento animationend que borbulha. Mas podemos usar um setTimeout, já que sabemos quanto tempo a animação durará.

No entanto, nossa impressão não está na escala correta. E isso ocorre porque precisamos dimensionar a imagem para a folha de papel. Precisamos de um pequeno pedaço de CSS para isso:

.printed__image {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

Seria legal também se as luzes na frente da impressora comunicassem que a impressora está ocupada. Poderíamos ajustar o tom de uma das luzes quando a impressora estiver imprimindo:

.progress-light {
  background: hsla(var(--progress-hue, 104), 80%, 50%);
}
.printing {
  --progress-hue: 10; /* Equivale ao vermelho */
}

Juntando tudo, temos uma “impressora” funcional feita com CSS e um toque de JavaScript.

É isso mesmo!

Nós demos uma olhada em como podemos fazer uma impressora 3D funcional com CSS, um toque de JavaScript e aproveitando o Pug. Tente adicionar o seguinte link de imagem no campo de URL, ou outro de sua escolha, e experimente!

https://source.unsplash.com/random

Cobrimos várias coisas diferentes para conseguir isso, incluindo:

  • como fazer coisas 3D com CSS
  • usando mixins Pug
  • usando propriedades CSS personalizadas com escopo para manter as coisas DRY
  • usando extrusão para criar cenas 3D
  • manipulando formulários com JavaScript
  • compilando cronogramas de animação com propriedades personalizadas

A alegria de criar esses demos é que muitos deles apresentam problemas diferentes a serem superados, como como criar certas formas ou construir certas animações. Geralmente há mais de uma maneira de fazer algo.

Que coisas legais você poderia fazer com CSS 3D? Eu adoraria ver!

Como sempre, obrigado por ler. Quer ver mais? Venha me encontrar no Twitter ou confira minha live stream!

Perguntas Frequentes (FAQs) sobre Impressora 3D CSS

O que é uma Impressora 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.

Como funciona uma Impressora 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.

Posso personalizar a Impressora 3D CSS?

Sim, você pode personalizar a Impressora 3D CSS. Você pode alterar as cores, o tamanho e até mesmo a velocidade da animação. Isso é feito modificando as propriedades CSS da impressora. Por exemplo, você pode alterar a cor modificando a propriedade background-color dos elementos da impressora.

Como posso integrar uma Impressora 3D CSS no meu site?

Integrar uma Impressora 3D CSS no seu site envolve copiar o código CSS e HTML no código do seu site. Você precisará garantir que o código CSS esteja incluído na seção head do documento HTML e que o código HTML seja colocado onde você deseja que a impressora apareça na sua página web.

É possível animar a Impressora 3D CSS?

Sim, é possível animar a Impressora 3D CSS. A animação é realizada usando a propriedade CSS animation. Essa propriedade permite que você crie keyframes que definem os estados inicial e final da animação, bem como quaisquer etapas intermediárias.

Quais navegadores suportam a Impressora 3D CSS?

A Impressora 3D CSS deve funcionar em todos os navegadores modernos que suportam as propriedades CSS transform e animation. Isso inclui navegadores como Google Chrome, Mozilla Firefox, Safari e Microsoft Edge.

Posso usar a Impressora 3D CSS para fins comerciais?

Sim, você pode usar a Impressora 3D CSS para fins comerciais. No entanto, é sempre uma boa ideia verificar os termos de licenciamento de qualquer código que você use para garantir que esteja em conformidade.

Quais habilidades preciso para criar uma Impressora 3D CSS?

Para criar uma Impressora CSS 3D, você precisa de uma boa compreensão de HTML e CSS. Você deve estar familiarizado com propriedades CSS como transform, perspective e animation. Conhecimento básico de modelagem 3D também pode ser útil, mas não é necessário.

Posso usar JavaScript com a Impressora CSS 3D?

Sim, você pode usar JavaScript com a Impressora CSS 3D. Embora a impressora possa ser criada usando apenas CSS, JavaScript pode ser usado para adicionar interatividade, como iniciar ou parar a animação com base nas ações do usuário.

Existe algum recurso para aprender mais sobre a Impressora CSS 3D?

Existem muitos recursos online para aprender mais sobre a Impressora CSS 3D. Sites como SitePoint, CSS-Tricks e MDN Web Docs têm tutoriais e guias extensivos sobre animações CSS e transformações 3D. O YouTube também possui muitos tutoriais em vídeo sobre o assunto.

Source:
https://www.sitepoint.com/3d-css-printer/