1

I developed a project on Laravel and Vue Js. In a part of this site, I have made an App in Vue whom allow the user to drags a <img> tag on another <img> tag, both contained in a DIV. There are many (and the most unsupported) CSS applied to both images, as filters, 3dtransforation, mask, background-source...It works smooth on both Chrome and Firefox. What I have to do now, is to save in jpg/png the "result" of all the trasformations applied to those two images, or to say it better, the html of the div container have to be converted in a image file and saved on server/rendered on the page after a click. I didn't realise this will have been the hardest part.. Whatever I tried until now didn't worked. I tried using

  1. Domtoimage -> The problem that I have with this javascript library is that I'm loading 1 image from the server (local currently) and 1 image from an S3disk on the AWS, and there are cross-browser compatibility problems.
  2. Browsershot -> The issue experienced for me here is again about having the files on different storages, but here the problem is on the localhost. Hww, doing a try with both image on S3, some of the CSS properties are not rendered (mask, opacity, transform)
  3. HTML2CANVAS -> Again both issues: cross origin, and not rendering most of the required CSSs.

At this point I really not longer know where to look out for a solution. It seems that for as easy is to set the css for two elements that works, it's impossible to ask java or the server to just "print out" what you see, exactly as you are seeing it. About "printing": I noticed (trying to find a workaround) that even if by pressing print page, on the preview, some CSS are missing, while they are clearly visible in the page.

I'll be definitively grateful if somebody have any suggestion

  • I suggest using the JavaScript canvas API to render these graphics. You'll find it to be a faster, more reliable, and overall better alternative to using a DOM>image conversion library. Just my two cents ;) – www139 Jun 30 '18 at 19:33
  • 1
    Take a look at this https://stackoverflow.com/questions/50971937/dataurl-of-an-img-with-css-class/51093284?noredirect=1#comment89219284_51093284 there are several ways – Emeeus Jun 30 '18 at 19:37
  • @www139 Thanks for yours feedback. But I'm wondering if it's possible to convert existing Dom elements to canvas or I should re-write everything in order to have it drown in the canvas.? – Raffo Baffo Jun 30 '18 at 20:36
  • @Emeeus thanks but any of those can work for me. The answer for that question was to use SVG , but I'm using PNG images – Raffo Baffo Jun 30 '18 at 20:39
  • I think you could transform the PNG with svg, also there are a way that is my answer but is using backend. – Emeeus Jun 30 '18 at 20:42
  • @RaffoBaffo You'll need to rewrite everything. However, the new system would really benefit you. – www139 Jun 30 '18 at 20:48
  • @Emeeus using back end is not a problem in this case. Anything that can get rid of this problem that I MUST solve or the work I've done till now will be useless. I'll try to install it on my localhost. I'm on Mac os, do you know of any know compatibility issue? Thanks! – Raffo Baffo Jun 30 '18 at 20:51
  • @RaffoBaffo I think there is no problem. – Emeeus Jun 30 '18 at 21:02
  • @www139 Let's take it as a last-chance solution for now. I'm really surprised it's that hard to do.. – Raffo Baffo Jun 30 '18 at 21:07
  • @Emeeus I'm trying to install it now, let's see. Do you "guarantee" it won't have the usual conflict with Cross Origin and "special" css? – Raffo Baffo Jun 30 '18 at 21:07
  • @RaffoBaffo since you are in backend, the server must be able to reach all what you want, it's the only issue. About special css, I used it a lot, and with a lot of javascrtip too, and the result is exactly like browser. – Emeeus Jun 30 '18 at 21:12
  • @RaffoBaffo I said it's the only issue because sometimes backend servers has proxies or/and doesn't connect to internet. – Emeeus Jun 30 '18 at 21:15
  • @Emeeus Great! I'm going though it now. See that the user can edit multiple properties of 1 image (brighness, inclination, shadow color/alpha, mask..), I think I'll post the HTML of the div to a controller where il will passed to wkhtmltoimage then sent back to the user to download it . Sounds correct? – Raffo Baffo Jun 30 '18 at 21:24
  • @RaffoBaffo I'm performing an answer, yes you could send everything – Emeeus Jun 30 '18 at 21:29
  • @Emeeus SuperCool. I just printed out the google home page from terminal. But, how do I achieve this on a controller? In the other answer you was talking about making an ajax request. Would you believe It will be faster ? really appreciate – Raffo Baffo Jun 30 '18 at 21:29
  • @RaffoBaffo depends on what do you want, if you want the users download the results of their transformations or something like that, I think it's better an ajax – Emeeus Jun 30 '18 at 21:40
  • Great. I'll go for Ajax then.. When you say "I'm performing an answer" you mean about the Ajax request? – Raffo Baffo Jun 30 '18 at 21:46
  • @RaffoBaffo lol no, this https://stackoverflow.com/questions/51117900/save-multiple-img-with-all-css-applied-elements-from-self-dom-to-jpg-png-file/51118638#answer-51118638 – Emeeus Jun 30 '18 at 21:56

1 Answers1

1

As I said in comments, here are some solutions. About the solution that involves wkhtmltoimage in server side, is as follow:

wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command line tools to render HTML into PDF and various image formats using the Qt WebKit rendering engine

  • Download and install wkhtmltopdf wich includes wkhtmltoimage
  • Send from client all what you need (more detail below)
  • In backend create a html file with all what you need, you could include css and javascript
  • run wkhtmltoimage http://yourHtml.html yourdesiredImage.jpg
  • You have your page with all rendered like a browser in yourdesiredImage.jpg

As you have to send to backend some behaviors that users perform with css, you could use window.getComputedStyle(element) to store all properties applied to an element into an object.

You have to send the object created by window.getComputedStyle(element) to the backend with ajax and reapply the rules.

To reapply those styles you could use something like:

var stylesComputed = {}//My object from frontend 

var source = document.getElementById("source");
var target = document.getElementById("target");


var copy = document.getElementById("copy");

copy.addEventListener("click", function(){
      var styles = "";
      for(let i = 0; i<stylesComputed.length-1; i++){
      styles += stylesComputed[i]+":"+stylesComputed[stylesComputed[i]]+"; ";
      }
      target.setAttribute("style", styles);

      document.getElementById("t2").innerHTML = "Target (copied)";
});

full example here: https://jsfiddle.net/5c9rhxbn/

Emeeus
  • 5,072
  • 2
  • 25
  • 37
  • Ok, about window.getComputedStyle(element) it definitively make sense. Maybe I'm tired now, but just to be clear and avoid my usual beginner errors: when you say "In backend create a html file with all what you need, you could include css and javascript" you mean to populate this html file, let's call it codeImage.html, with the content of "what I need"? And "run wkhtmltoimage http:// yourHtml.html yourdesiredImage.jpg" you mean from shell_exec in php? – Raffo Baffo Jun 30 '18 at 22:06
  • to create a file since you are in php do it with fopen() or some similar. to run wkhtmltoimage, yes, with shell_exec or similar – Emeeus Jun 30 '18 at 22:09
  • Great. Thanks a lot. I'll give it a try later or tomorrow and accept the answer – Raffo Baffo Jun 30 '18 at 22:10
  • I put the question as answered because as far from now it's been the thing closer to work properly. There is stil some property not correctly applied, but I'll check tomorrow, it's wired, it seems to work on some and not on some else, so it could be a mistake on the vue.js part. To grab the content that the user create, I use a method ` logHtml(){ var canvasHtml = document.getElementById('appser').innerHTML; document.getElementById('copyCanvas').innerHTML = canvasHtml; this.codedImageExport = canvasHtml;` , it could be the cause – Raffo Baffo Jun 30 '18 at 23:16
  • Where #Appser is the div where all the transformations are made, let's call it a canvas – Raffo Baffo Jun 30 '18 at 23:17
  • @RaffoBaffo don't forget to put all librarys you use in the backend html – Emeeus Jun 30 '18 at 23:33
  • So far so great. Everything it's working correctly. I'm just having a problem by executing wkhtmltopdf from shell_exec. It breaks the server. I'm investigating, but it seems to be a know issue. – Raffo Baffo Jul 01 '18 at 11:34
  • Bad to be back here :( ; So after some time spent doing some other modifications to my app, now that I'm back to wkhtmltoimage I'm having a problem with the css property: "filter" . No filter are applied to the images, I need drop-shadow (that show'us up perfectly in both chrome and firefox), but I tried also to to some test with "brightess" and neither that seems to work. I've achived to have many peculiar css properties, included masking, but it seem I got no way to apply filter? – Raffo Baffo Jul 18 '18 at 12:07