参考了这篇文章,部分回答了我的问题:Force iOS to download image from HTML5 Canvas (using pure JavaScript)

总之,这个问题之前已经被问过,一般的回答是它不能在 iOS 上完成。然而,这些问题已经好几年了,回答上述问题的成员确实提供了部分答案:使用 HTMLCanvasElement.toDataURL() 将图像转换为数据 URL,然后强制将数据 URL 作为图像打开在新标签页中。从那里,然后可以通过将手指放在图像上,打开 iOS 保存对话框来下载它。

问题是,即使我的保存代码下载了应用了 CSS 过滤器的图像,在 iOS 的新选项卡中打开的图像也没有应用过滤器。

So, my question is, how do I take the final step: forcing the image that opens in the new tab to have the CSS Filters applied, just as a downloaded image on a computer would have the CSS Filters applied.

This is the code that takes the image from the original canvas and applies the CSS Filters, creating a new image with the CSS Filters applied:

function fileApply() 
{ 

  var cP = document.getElementById("cPreview");
  var cntxCP = cP.getContext("2d");

  var cS = document.getElementById("cSave");
  var cntxCS = cS.getContext("2d");

  // take whatever CSS filters are applied to the first canvas
  var cssFilter = getComputedStyle(cP).filter; 

  // use those filter as the second canvas' context's filter
  cS.width = cP.width; 
  cS.height = cP.height; 
  cntxCS.filter = cssFilter;

  cntxCS.drawImage(cP, 0, 0);
  cP.style.display = "none";   
  if (cS.style.display == "none") cS.style.display = "block";   
}

That all works.

This is the save code:

function fileSave()
{

  var canvas = document.getElementById('cSave');

  if (document.getElementById("png").checked == true)
  {
    var quality = null;  // canvas.toBlob() takes an extra argument if file type is JPG. Set quality to null to allow PNG downloads. Quality value will be supplied if JPG is selected.   
    var format = "image/png"; 
    var name = "new_image.png"; 
  }

  if (document.getElementById("jpg").checked == true)
  {
    var format = "image/jpeg";  
    var quality = Number(document.getElementById("quality").value) / 100; 
    var name = "new_image.jpg"
  }

  if (!isIOS())
  {
    canvas.toBlob(function(blob) // Send canvas to blob and download blob 
    {
    const anchor = document.createElement('a')
    const url = URL.createObjectURL(blob)
    anchor.href = url
    anchor.download = name, 
    document.body.appendChild(anchor)
    anchor.click()
    document.body.removeChild(anchor)
    URL.revokeObjectURL(url);   
    }, format, quality)
  }

  if (isIOS()) 
  {
    var iString = canvas.toDataURL(); // convert image to base64 string 
    document.getElementById("iOS").innerHTML = '<a href="' + iString + '">click me</a>'; // add string to url and target new tab.     
  }

That works fine on a computer. On iOS that creates the new image in a new tab without the CSS Filters applied.

Thank you


It downloads with the filters on it? Does that mean iString has the filters applied? CSS just affects the way the page renders, not the canvas data. Sounds like you need canvas filters.

Yes, it downloads with the filters applied. Thus, since iString is getting the image from the same place, it should have the filters applied. But it doesn't. CSS can be made to do more than just change how the page renders, in this case, it changes the actual image that's downloaded. I'm not sure what you mean by "canvas filters", is that something from a JS add-on library?

I just tested the above code on a custom filter I built (in other words, my own image filter, not a CSS3 filter). On iOS, the edited image opened in a new tab, with the filter's changes applied, and I was able to save it to the camera roll. So, that confirms that everything else works, the sole issue is keeping the CSS3 filters applied when using CSS3 filters.

@PHPglue In regard to using "canvas filters", I read developer.mozilla.org/en-US/docs/Web/API/…. It appears to me that what I'm doing above, specifically var cssFilter = getComputedStyle(cP).filter; cntxCS.filter = cssFilter; cntxCS.drawImage(cP, 0, 0); is using canvas filters. Did you have something else in mind? If so, please provide source code, because I don't see how what I'm doing differs from canvas filters. Thank you very much!

getComputedStyle(cP).filter? Pretty sure that won't work on any Browser. canvasContext.filter will work on Firefox, but not with most Browsers anyways. Use another technique.