带有CSS类的img的DataURL

时间:2018-06-21 15:11:07

标签: javascript html css image fabricjs

由于CSS类,我不得不在<img>上应用一些样式。

是否可以使用CSS样式获得dataURL中的<img>

$(function() {
  // Original
  const imgOriginal = document.getElementById('original');
  const c1 = document.getElementById('c1');
  let ctx = c1.getContext('2d');
  ctx.drawImage(imgOriginal, 100, 100);

  // Filtered
  const imgFiltered = document.getElementById('filtered');
  const c2 = document.getElementById('c2');
  ctx = c2.getContext('2d');
  ctx.drawImage(imgFiltered, 100, 100);

  // Same dataURL :(
  console.log(c1.toDataURL(), c2.toDataURL());
  console.log(c1.toDataURL() === c2.toDataURL());
})
.filter::before {
  display: block;
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
  z-index: 1;
  border: 1px solid red;
}

.filter {
  position: relative;
  -webkit-filter: sepia(.5) hue-rotate(-30deg) saturate(1.4);
  filter: sepia(.5) hue-rotate(-30deg) saturate(1.4);
}

canvas {
  display: block;
  width: 100px;
  height: 100px;
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div>

  <img id="original" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg/170px-Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg">
  <canvas id="c1"></canvas>

  <img id="filtered" class="filter" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg/170px-Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg">
  <canvas id="c2"></canvas>

</div>

也许由于<canvas>标签,该代码片段将出现错误,但还是有想法。


编辑

如果有人对SVG有任何建议,我正在使用fabricJS


编辑2(无法解决,但无法找到其他方法)

  1. 感谢@KavianK。您可以使用CSS上下文复制canvas样式,但是对我来说很无聊,因为我们必须为每个callback类存储一个不同的CSS才能获得{{1} }。仍然在工作!

  2. 由于@Emeeus可能是您的后端提供的解决方案,而不是我的解决方案,因为我只想在前端执行此操作。 wkhtmltopdf

  3. 由于@pegasuspect,我们可以使用dataURL过滤图像,我正在按照这种方式,将fabricJS替换为svgjs,因此该库可以轻松替换{ {1}},使用SVG更容易,而且我不再需要canvas了!

  4. 由于@Kaiido,有一种方法可以将img样式的DataURL中的snapshothtml2canvas一起轻松获得{{1}在这种情况下。不幸的是,尚不支持某些HTML样式,例如CSSdataURL,这就是为什么它不是我的解决方案

该主题尚未解决,但是使用CSS并不需要实际使用box-shadow

4 个答案:

答案 0 :(得分:7)

CSSDOM与用于图像和画布的位图是一个独立的世界。位图本身不受CSS的影响,仅受充当位图的镜子的元素的影响。因此,应用于画布的CSS过滤器将不会应用于生成的图像。您需要在画布中复制滤镜,或者将相同的滤镜重新应用于生成的图像。

示例:

上下文对象上有一个鲜为人知的属性,方便命名为filter。这将对其自身的上下文应用过滤器。必须在下一次绘制操作之前设置过滤器。

var img = new Image();

img.crossOrigin = '';
img.src = document.getElementById( 'original' ).src;

img.onload = function() {
    var canvas = document.getElementById( 'canvas' ),
        ctx = canvas.getContext( '2d' );

    canvas.width = this.width;
    canvas.height = this.height;

    // filter
    if ( typeof ctx.filter !== 'undefined' ) {
        ctx.filter = "sepia(.5) hue-rotate(-30deg) saturate(1.4)";
        ctx.drawImage(this, 0, 0);
    } else {
        ctx.drawImage(this, 0, 0);
    }

    document.getElementById( 'filtered' ).src = canvas.toDataURL();
}
<img id="original" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg/170px-Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg" />
<img id="filtered" />
<canvas id="canvas" style="display: none"></canvas>

答案 1 :(得分:2)

tldr;

您可以使用SVG来实现。 http://jsfiddle.net/1hambw93/91/


如何将SVG用作图像的数据源

它的解释是here quite nicely。基本上说可以在img的src标记中使用svg元素。

如何在SVG中使用过滤器

这里也很好地解释了这一点:使用SVG过滤器,我可以用您的代码实现相同的过滤器效果。

您可以从this site using Sepium为svg生成过滤器,以获取与CSS相同的过滤器。到目前为止,您将拥有以下SVG:

<svg id="test">
    <image xlink:href='https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg/170px-Brad_Pitt_Inglorious_Basterds_Berlin_premiere.jpg'
      x="0" y="0" height="170px" width="218px" 
      filter='url(#sepium-filter)' />
    <filter id="sepium-filter">
      <feColorMatrix type="matrix" 
        values="1.3 -0.3 1.1   0 0 
                  0  1.3 0.2   0 0 
                  0    0 0.8 0.2 0 
                  0    0   0   1 0">
      </feColorMatrix>
    </filter>
</svg>

然后我使用a minimal javascript code转换为base64并将SVG的结果写入object,以HTML格式显示。

答案 2 :(得分:0)

有1个变通办法;使用CSS可能适合您的用例:

img[src^="data:image/png;"] {
  background-color: #000;
  filter: sepia(50%);
}

这将适用于所有以data:image/png开头的图像URL

答案 3 :(得分:0)

据我了解,您需要计算出的图像,因此您需要浏览器完成工作的结果。为此,您可以专门使用wkhtmltopdf wkhtmltoimage 。它使用Qt WebKit渲染引擎(就像浏览器一样)。您必须将其安装在服务器中,然后运行以下代码:

wkhtmltoimage  http://mysite/image-Plus-css-PLus-canvas.html myComputedImge.jpg

http://mysite/image-Plus-css-PLus-canvas.html是HTML中带有CSS,JavaScript和其他内容的图像。当然,所有这些都可以使用ajax完成。

因此,使用这种方法,您将拥有一个 .jpg .png 文件(在本例中为myComputedImge.jpg),该文件具有您要计算的所有内容,如屏幕截图。如果希望使用base64,则可以执行与.toDataURL()相同的操作,结果是使用 css的图像的base64。

如果要使用ajax执行此操作,则可以:

  • 使用文件作为参数或远程URL发送请求。
  • 如果文件是远程文件,则服务器必须能够访问它。
  • 在服务器端,您将使用图像,css和javascript或任何您想要的内容创建一个.html文件。
  • 运行上面详述的代码以创建.jpg或.png
  • 将创建的文件的位置响应给ajax请求。
  • 在回调中,您将具有计算出的过滤器的新图像的url。
  • 由于在服务器端具有此新映像,因此可以直接响应base64而不是位置,因此在客户端不需要.toDataURL()