【问题标题】:How to generate a new image from overlaid text and images over one large background image using Javascript?如何使用 Javascript 从覆盖在一个大背景图像上的文本和图像生成新图像?
【发布时间】:2021-05-04 07:55:57
【问题描述】:

我在页面上有一张图片(我将其称为背景图片),并且我允许用户输入一些通过 CSS 定位在背景图片上的文本。此外,还有一些其他小图像会根据文本使用 css 自动定位在背景图像上。

我现在想将用户设置/创建的内容转换为实际可下载的图像,本质上是照片编辑术语中的“扁平化图层”。

理想情况下,我还希望以非常高分辨率进行此操作,因为原始背景图像以比人们在编辑时看到的格式更大、更高分辨率的格式存在。

我不确定执行此操作的最佳方法。我会使用 NodeJS 和 Lambdas。

我认为一个解决方案可能是让另一个页面存在完整尺寸的背景图像,并让 css 重新定位并完美调整所有内容的大小,并使用 puppeteer 或其他东西截取屏幕截图,尽管我不知道这是否会丢失以某种方式原始图像的质量?

或者我是否为背景正确调整了叠加的文本和图像的大小,并对它们中的每一个进行截图,以某种方式添加透明度,然后以某种方式合并图片?

有没有我遗漏的更简单的方法或一些可以提供帮助的包?

【问题讨论】:

  • 你有没有想过在屏幕外有一个元素(而不是另一个页面),带有完整尺寸的图像和其他东西(适当放大)并在元素上使用类似 html2canvas 的东西?
  • 实际上,由于您可以完全控制最终图像中想要的内容,您也许可以自己将其全部写入画布。

标签: javascript html css node.js aws-lambda


【解决方案1】:

如果您创建一个具有全尺寸图像的元素,覆盖用户的文本和任何其他所需的图像 - 两者都在大小和位置上适当放大,您可以将该元素保存在画布上,然后将其转换为图片。

这里有一些代码可以给出这个想法。它使用 html2canvas 但实际上您可以创建画布并绘制图像并将文本写入其中而无需库(如果需要)。 (代码从我的服务器、我的笔记本电脑和https://codepen.io/rgspaces/pen/RwoNxVQ 上运行,但不在 SO sn-p 中运行 - ??在 sn-p 系统中 iframe 的 CORS 问题??)。

<head>
<script src="https://ahweb.org.uk/html2canvas.js"></script>
<style>
body {
  overflow: hidden;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  --t: 20px; /*  distance from top of the user's text in the workspace */
  --l: 20px; /* distance from left of the user's text */
  --f: 30px; /* fontsize of the user's text in the workspace */
}

#big {
  position: absolute;
  left: 100vw;
  display: none;
  width: auto;
  height: auto;
}

#workspace {
  width: 50vw;
  height: auto;
}

#workspace .mainimg {
  width: 100%;
  height: auto;
}

#workspace .text, #big .text {
  position: absolute;
  color: white;
}

#workspace .text {
  top: var(--t);
  left: var(--l);
  font-size: var(--f);
}
</style>
</head>
<body>
  <div id="big">
    <img id="bigimg" src="https://picsum.photos/id/1016/3844/2563.jpg" class="mainimg" crossOrigin = "anonymous">
    <div class="text"></div>
  </div>
  <div id="workspace">
    <img src="https://picsum.photos/id/1016/3844/2563.jpg" class="mainimg">
    <div class="text">User's text</div>
    <!-- other imgs -->
  </div>
  <p>YOUR IMAGE WILL APPEAR BELOW - RIGHT CLICK TO SAVE IT TO FILE (WINDOWS); PRESS TO SAVE TO PHOTOS (IOS)</p>
  <img id="resultimg" style="clear:both;" src=""/>

<script>
function start() {
  let big = document.getElementById('big');
  let bigImg = document.getElementById('bigimg');
  let bigText = document.querySelector('#big .text');
  let width = bigimg.width;
  let height = bigimg.height;
  let workspace = document.getElementById('workspace');
  let workspaceText = document.querySelector('#workspace .text');
  let props = window.getComputedStyle(workspace, null);
  let scaling = width/props.getPropertyValue("width").replace('px','');

  bigText.innerHTML = workspaceText.innerHTML;
  // just some simple scaling to give an idea for now
  bigText.style.fontSize = 'calc(var(--f) * ' + scaling + ')';
  bigText.style.top = 'calc(var(--t) * ' + scaling + ')';
  bigText.style.left = 'calc(var(--l) * ' + scaling + ')';
  big.style.display = 'inline-block';
  
  window.scrollTo(0, 0);
  html2canvas(big, {allowTaint: true, useCORS: true, logging: true, width: width, height: height})
    .then((canvas) => {
      big.style.display = 'none';
      document.body.style.overflow = 'visible';
      const imgData = canvas.toDataURL('image/png', 1);
      const resultImg = document.getElementById('resultimg')
      resultImg.src = imgData;
      resultImg.style.width = width + 'px';
      resultImg.style.height = 'auto';    
    });
  }
  
window.onload = start;

</script>
</body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多