使用html2canvas截取CSS生成的马克杯包裹图案出现裁切问题
格式化后的提问内容
我正在尝试截取一段通过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>
补充说明:我也尝试过配置foreignObjectRendering: true参数,此时截图的形状正确,但整体显示为全黑图像,效果见:
二次补充:我也接受其他实现方案,要么可以实现将矩形图像包裹在马克杯上的效果,要么可以替代截图获取我当前已生成的图案。
解决方案
问题根源
html2canvas本身对CSS 3D变换属性的支持度非常有限:
- 默认模式下会忽略
transform-style: preserve-3d、3D旋转/位移这类属性,直接按平面元素渲染,就会出现你碰到的错位裁切问题 - 开启
foreignObjectRendering模式后,浏览器安全限制会阻止跨域图片资源在foreignObject中渲染,因此出现全黑。
可选方案
方案1:替换截图工具,适配现有CSS代码
将html2canvas替换为dom-to-image库,它对CSS 3D的支持度更好,只需提前给用到的贴图资源配置CORS跨域允许,就能正常生成截图,参考代码如下:
domtoimage.toPng(document.querySelector("#capture")) .then(dataUrl => { const img = new Image(); img.src = dataUrl; document.body.appendChild(img); }) .catch(error => console.error('截图生成失败', error));
方案2:直接用Canvas实现杯身贴图(更稳定,推荐)
如果核心需求是把矩形图贴到杯型上再导出,直接用Canvas实现效果更稳定,也不需要额外的截图工具:
- 加载原始矩形贴图,按杯身弧度切割为24等份竖条
- 对每个竖条做对应的透视变形后绘制到Canvas上
- 直接调用
canvas.toDataURL()就能导出最终效果,完全不存在渲染兼容问题。
如果需要支持角度调整、旋转交互,也可以用Three.js创建圆柱模型,把贴图贴到圆柱上渲染,后续调整参数、替换素材都更灵活。
内容的提问来源于stack exchange,提问作者Glen Keybit
相关产品推荐
相关产品推荐

