使用 html2canvas 截取用 css 包裹在杯子周围的图像结果

Capturing an image wrapped around a mug with css using html2canvas results cut up

我正在尝试捕捉我第一次使用 CSS 生成的图像。

CSS生成的图片是这样的..

并且当前的 html2canvas 输出是...

目前我试过的代码如下...

html2canvas(document.querySelector("#capture"), {
  allowTaint: true
}).then(canvas => {
  document.body.appendChild(canvas)
});
body {
  background: #0000007a;
}

h1 {
  font: small-caps 167% Arial, Helvetica, sans-serif
}

#container {
  margin-left: -56px;
  top: 450px;
  width: 550px;
  -moz-perspective: 800px;
  -webkit-perspective: 800px;
  margin-top: 130px;
}

#container:hover * {
  -moz-animation-play-state: paused;
  -webkit-animation-play-state: paused
}

#frame {
  margin-top: 95px;
  width: 23px;
  -moz-transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  /* translate must be last */
  -moz-transform: rotateX(-1deg) rotateY(45deg) rotateZ(0deg) translate3d(325px, -70px, 50px);
  -webkit-transform: rotateX(-1deg) rotateY(45deg) rotateZ(0deg) translate3d(325px, -70px, 50px)
}

.strip {
  -moz-transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  animation: spin 0.01s forwards;
}

.mastercontainer {
  width: 400px;
  height: 400px;
  display: inline-block;
  overflow: hidden;
}

.strip div {
  position: absolute;
  background: #000 url(http://automation.stickermonkey.shop/codeplayground/images/djmug2.jpg);
  border: solid rgb(145, 87, 0);
  border-width: thin 0;
  height: 275px;
  width: 34px;
  opacity: 1;
}

.strip .a {
  background-position: 0 0;
  -moz-transform: rotateY(0deg) translateZ(124px);
  -webkit-transform: rotateY(0deg) translateZ(124px)
}

.strip .b {
  background-position: 759px 0;
  -moz-transform: rotateY(15deg) translateZ(124px);
  -webkit-transform: rotateY(15deg) translateZ(124px)
}

.strip .c {
  background-position: 726px 0;
  -moz-transform: rotateY(30deg) translateZ(124px);
  -webkit-transform: rotateY(30deg) translateZ(124px)
}

.strip .d {
  background-position: 693px 0;
  -moz-transform: rotateY(45deg) translateZ(124px);
  -webkit-transform: rotateY(45deg) translateZ(124px)
}

.strip .e {
  background-position: 660px 0;
  -moz-transform: rotateY(60deg) translateZ(124px);
  -webkit-transform: rotateY(60deg) translateZ(124px)
}

.strip .f {
  background-position: 627px 0;
  -moz-transform: rotateY(75deg) translateZ(124px);
  -webkit-transform: rotateY(75deg) translateZ(124px)
}

.strip .g {
  background-position: 594px 0;
  -moz-transform: rotateY(90deg) translateZ(124px);
  -webkit-transform: rotateY(90deg) translateZ(124px)
}

.strip .h {
  background-position: 561px 0;
  -moz-transform: rotateY(105deg) translateZ(124px);
  -webkit-transform: rotateY(105deg) translateZ(124px)
}

.strip .i {
  background-position: 528px 0;
  -moz-transform: rotateY(120deg) translateZ(124px);
  -webkit-transform: rotateY(120deg) translateZ(124px)
}

.strip .j {
  background-position: 495px 0;
  -moz-transform: rotateY(135deg) translateZ(124px);
  -webkit-transform: rotateY(135deg) translateZ(124px)
}

.strip .k {
  background-position: 462px 0;
  -moz-transform: rotateY(150deg) translateZ(124px);
  -webkit-transform: rotateY(150deg) translateZ(124px)
}

.strip .l {
  background-position: 429px 0;
  -moz-transform: rotateY(165deg) translateZ(124px);
  -webkit-transform: rotateY(165deg) translateZ(124px)
}

.strip .m {
  background-position: 396px 0;
  -moz-transform: rotateY(180deg) translateZ(124px);
  -webkit-transform: rotateY(180deg) translateZ(124px)
}

.strip .n {
  background-position: 363px 0;
  -moz-transform: rotateY(195deg) translateZ(124px);
  -webkit-transform: rotateY(195deg) translateZ(124px)
}

.strip .o {
  background-position: 330px 0;
  -moz-transform: rotateY(210deg) translateZ(124px);
  -webkit-transform: rotateY(210deg) translateZ(124px)
}

.strip .p {
  background-position: 297px 0;
  -moz-transform: rotateY(225deg) translateZ(124px);
  -webkit-transform: rotateY(225deg) translateZ(124px)
}

.strip .q {
  background-position: 264px 0;
  -moz-transform: rotateY(240deg) translateZ(124px);
  -webkit-transform: rotateY(240deg) translateZ(124px)
}

.strip .r {
  background-position: 231px 0;
  -moz-transform: rotateY(255deg) translateZ(124px);
  -webkit-transform: rotateY(255deg) translateZ(124px)
}

.strip .s {
  background-position: 198px 0;
  -moz-transform: rotateY(270deg) translateZ(124px);
  -webkit-transform: rotateY(270deg) translateZ(124px)
}

.strip .t {
  background-position: 165px 0;
  -moz-transform: rotateY(285deg) translateZ(124px);
  -webkit-transform: rotateY(285deg) translateZ(124px)
}

.strip .u {
  background-position: 132px 0;
  -moz-transform: rotateY(300deg) translateZ(124px);
  -webkit-transform: rotateY(300deg) translateZ(124px)
}

.strip .v {
  background-position: 99px 0;
  -moz-transform: rotateY(315deg) translateZ(124px);
  -webkit-transform: rotateY(315deg) translateZ(124px)
}

.strip .w {
  background-position: 66px 0;
  -moz-transform: rotateY(330deg) translateZ(124px);
  -webkit-transform: rotateY(330deg) translateZ(124px)
}

.strip .x {
  background-position: 33px 0;
  -moz-transform: rotateY(345deg) translateZ(124px);
  -webkit-transform: rotateY(345deg) translateZ(124px)
}

@-moz-keyframes spin {
  from {
    -moz-transform: rotateY(360deg)
  }
  to {
    -moz-transform: rotateY(230deg)
  }
}

@-webkit-keyframes spin {
  from {
    -webkit-transform: rotateY(360deg)
  }
  to {
    -webkit-transform: rotateY(230deg)
  }
}
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<div id="capture" class="mastercontainer">
  <div id="container">
    <div id="frame">
      <div class="strip">
        <div class="a"></div>
        <div class="b"></div>
        <div class="c"></div>
        <div class="d"></div>
        <div class="e"></div>
        <div class="f"></div>
        <div class="g"></div>
        <div class="h"></div>
        <div class="i"></div>
        <div class="j"></div>
        <div class="k"></div>
        <div class="l"></div>
        <div class="m"></div>
        <div class="n"></div>
        <div class="o"></div>
        <div class="p"></div>
        <div class="q"></div>
        <div class="r"></div>
        <div class="s"></div>
        <div class="t"></div>
        <div class="u"></div>
        <div class="v"></div>
        <div class="w"></div>
        <div class="x"></div>
      </div>
    </div>
  </div>
</div>

我已经把所有东西都放到了这里的 jsfiddle 中.. https://jsfiddle.net/StickerMonkey/tLqrdey5/4/

编辑添加: 我也试过 foreignObjectRendering: true 这给出了正确的形状但是是一个涂黑的图像。

要添加的第二次编辑; 我也乐于接受另一种方法的建议,将矩形图像包裹在杯子周围或另一种截屏方式或以其他方式抓取我已经生成的图像。

这是一个使用 Three.js 的例子。

它创建了一个带有彩绘杯子旋转视图的场景。

它还在新的 canvas 中以 60° 旋转拍摄快照。

它还在白色背景的第三个 canvas 中单独显示油漆。

//Moved to <script type="module">
//import * as THREE from 'https://cdn.skypack.dev/three';

function actualCode(THREE) {
  //Variables for rendering
  const renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(30, 400.0 / 400, 1, 1000);

  //Object variables
  let texture;
  let paintedMug;

  //Preload image, then trigger rendering
  const loader = new THREE.TextureLoader();
  //Real URL triggers cross origin error in tests:
  // texture = loader.load("http://automation.stickermonkey.shop/codeplayground/images/djmug2.jpg", function(_tex) {
  //Hosting it on local server works:
  // texture = loader.load("./djmug2.jpg", function(_tex) {
  //Example with image hosted from Imgur:
  texture = loader.load("https://i.imgur.com/TQZrUSP.jpeg", function(_tex) {
    // /*Debugging:*/ setTimeout(() => document.body.appendChild(texture.image), 100);
    init();
    snapShot(60);
    renderImageSolo(60);
    render();
  });
  
  function init() {
    //Init scene and camera
    camera.position.set(0, 1.3, 11);
    camera.lookAt(scene.position);
    renderer.setSize(400, 400);
    addTitle("Animated scene:");
    document.body.appendChild(renderer.domElement);
    
    //Set an ambient light
    const light = new THREE.AmbientLight(0xffffff); // soft white light
    scene.add(light);

    //Draw white mug
    const muggeom = new THREE.CylinderGeometry(1.5, 1.5, 3.5, 240, 1);
    const mugmaterial = new THREE.MeshStandardMaterial({
      color: "#fff",
    });
    const mug = new THREE.Mesh(muggeom, mugmaterial);

    //Draw painting on mug with slightly larger radius
    const paintgeom = new THREE.CylinderGeometry(1.5001, 1.5001, 3.3, 240, 1, true);
    const paintmaterial = new THREE.MeshStandardMaterial({
      map: texture,
    });
    const paint = new THREE.Mesh(paintgeom, paintmaterial);

    //Define a group as mug + paint
    paintedMug = new THREE.Group();
    paintedMug.add(mug);
    paintedMug.add(paint);
    //Add group to scene
    scene.add(paintedMug);
  }

  function render() {
    try {
      //Draw
      renderer.render(scene, camera);
      //Rotate a bit at each frame
      paintedMug.rotation.y += -.01
      //Trigger next animation frame (default 60fps)
      requestAnimationFrame(render);
    } catch (err) {
      console.log(err, err.message);
    }
  }

  function snapShot(angle) {
    const orgAngle = paintedMug.rotation.y;
    //Rotate objects by angle
    paintedMug.rotation.y = angle;
    //render once
    renderer.render(scene, camera);
    //Take still into new canvas
    var canvas = document.createElement("canvas");
    canvas.width = renderer.domElement.width;
    canvas.height = renderer.domElement.height;
    canvas.getContext("2d").drawImage(renderer.domElement, 0, 0);
    canvas.style.marginTop = "1em"; //Space out canvas
    addTitle(`Snapshot at ${angle}°:`);
    document.body.append(canvas);
    //Restore rotation
    paintedMug.rotation.y = orgAngle;
  }

  function renderImageSolo(angle) {
    //Init just like main renderer / scene, will use same camera
    const solo_renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
    solo_renderer.setSize(renderer.domElement.width, renderer.domElement.height);
    solo_renderer.domElement.style.marginTop = "1em"; //Space out canvas
    addTitle(`Paint alone at ${angle}°:`);
    document.body.appendChild(solo_renderer.domElement);
    const solo_scene = new THREE.Scene();
    //Set an ambient light
    const light = new THREE.AmbientLight(0xffffff); // soft white light
    solo_scene.add(light);

    //Draw painting alone
    const paintgeom = new THREE.CylinderGeometry(1.5, 1.5, 3.3, 240, 1, true);
    const paintmaterial = new THREE.MeshStandardMaterial({
      map: texture,
    });
    const paint = new THREE.Mesh(paintgeom, paintmaterial);
    //Add paint to scene
    solo_scene.add(paint);
    //Rotate paint by angle
    paint.rotation.y = angle
    //Draw result
    solo_scene.background = new THREE.Color(0xffffff);
    solo_renderer.render(solo_scene, camera);
  }

  function addTitle(title) {
    const h2 = document.createElement('h2');
    h2.innerText = title;
    document.body.appendChild(h2);
  }
}
<!-- Below code is just a workaround for ES6 imports in SO snippet -->
<script type="module"> //Forced to put import in HTML section, as SO snippet does not support ES6 module loading
import * as THREE from 'https://cdn.skypack.dev/three';
document.addEventListener("DOMContentLoaded", _e => actualCode(THREE));
</script>

由于 CORS 策略,使用来自另一台服务器的原始图像时出现问题。我已经使用托管在 Imgur 上的副本设置示例,但还包括原始位置的代码(请参阅评论)。