AARRGGHHH 0 Posted December 1, 2020 Report Share Posted December 1, 2020 I've seen this (and similar) code used to apply an SVG filter to an image. How do I use this code to apply an SVG filter to a canvas? The canvas' content may change often. <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <filter id="darkGreen"> <feColorMatrix type="matrix" values="0 0 0 0 0 0 0.5 0 0 0 0 0 0 0 0 0 0 0 0 1" /> </filter> </defs> <image xlink:href="(url to image)" width="" height="" filter="url(#darkGreen)" /> </svg> Thank you Quote Link to post Share on other sites
Ingolme 1,019 Posted December 2, 2020 Report Share Posted December 2, 2020 SVG does not have a <canvas> element. The <foreignObject> tag might work to embed an HTML5 <canvas> element but I'm not sure how well <foreignObject> works. Instead of trying to embed the <canvas> in an SVG document, you could put the SVG code in a separate file and load its filter with the CSS filter property. Quote Link to post Share on other sites
AARRGGHHH 0 Posted December 3, 2020 Author Report Share Posted December 3, 2020 (edited) On 12/1/2020 at 9:42 PM, Ingolme said: Instead of trying to embed the <canvas> in an SVG document, you could put the SVG code in a separate file and load its filter with the CSS filter property. Thank you for the reply! SO what you have in mind is: <script> svgfile() </script> And svgfile() is a function in an external file. How do I get the main page to load the filter from the external page? One potential complication: There will also be CSS filters working in the main page. How can I get the .filter property to accept both CSS filters from the main page, plus SVG filter(s) from the external page? Thank you! PS: On this page https://www.w3.org/TR/SVG2/embedded.html I found this: Which would seem to imply that a canvas tag can be placed within an svg tag. Quote 12.4. HTML elements in SVG subtrees The following HTML elements render when included in an SVG subtree as a child of a container element and when using the HTML namespace: 'video' 'audio' 'iframe' 'canvas' <svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"> <html:video src="file.mp4" controls="controls"> </html:video> </svg> They gave a simple example for video (above), but not for canvas. Based on that example, I tried this: <canvas id="cSave" width="400" height="200" onclick="clickPreview()" style="position:relative; max-width:100%;"></canvas> <svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"> <defs> <filter id="darkGreen"> <feColorMatrix type="matrix" values="0 0 0 0 0 0 0.5 0 0 0 0 0 0 0 0 0 0 0 0 1" /> </filter> </defs> <html:canvas name="cSave"> </html:canvas> </svg> Which should create a dark Green color cast. But all I got was an empty canvas. Do you think this <svg> inside <canvas> can be made to work? Thanks again! Edited December 3, 2020 by AARRGGHHH Added content Quote Link to post Share on other sites
Ingolme 1,019 Posted December 6, 2020 Report Share Posted December 6, 2020 No, it is much simpler than that. Save your SVG filter in a .svg file, then apply the filter to any object using the CSS filter property: <style> #myCanvas { filter: url("file.svg#darkGreen"); } </style> ... <canvas id="myCanvas"></canvas> Quote Link to post Share on other sites
AARRGGHHH 0 Posted December 10, 2020 Author Report Share Posted December 10, 2020 I will try that, thank you VERY much. Will it be possible manipulate the SVG filter's values (for example, a feColorMatrix or feConvolver filter's matrix values) with JavaScript in my HTML page? Thanks again! Quote Link to post Share on other sites
Ingolme 1,019 Posted December 10, 2020 Report Share Posted December 10, 2020 Unfortunately, you can't modify it with Javascript if it is being loaded from another file. To do that, since canvas can be embedded in SVG, that's probably the best way to do it. Just a tweak to your previous code: <svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"> <defs> <filter id="darkGreen"> <feColorMatrix type="matrix" values="0 0 0 0 0 0 0.5 0 0 0 0 0 0 0 0 0 0 0 0 1" /> </filter> </defs> <html:canvas id="cSave" width="400" height="200" onclick="clickPreview()" style="position:relative; max-width:100%;"></html:canvas> </svg> In this way, you can access the filter as a DOM element and change its values. Quote Link to post Share on other sites
AARRGGHHH 0 Posted December 10, 2020 Author Report Share Posted December 10, 2020 Thank you so much. Unfortunately, I'm still getting something wrong. The canvas is showing up first, as it should. The SVG is showing up under the canvas. I tried wrapping it in <foreignObject> tags, but that did not help. Also, the table that the canvas should exist in is outside of the canvas. I have a feeling I missed something simple. ... <td id="tdSave" style="width:100%; border-style:none;"> <!-- START NEW SVG CODE --> <svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"> <defs> <filter id="xPurple"> <feColorMatrix type="matrix" values="2 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1" /> </filter> </defs> <foreignObject> <html:canvas id="cSave" width="400" height="200" onclick="clickPreview()" style="position:relative; max-width:100%;"> </html:canvas> </foreignObject> </svg> <!-- END NEW SVG Code --> </td> ... Screen Shots (hope this helps) are below. Many Thanks !!! Quote Link to post Share on other sites
AARRGGHHH 0 Posted December 10, 2020 Author Report Share Posted December 10, 2020 Just a thought, it's almost as though there's nothing "connecting" the table data and canvas to the filter. But I could be way off on that. Quote Link to post Share on other sites
Ingolme 1,019 Posted December 11, 2020 Report Share Posted December 11, 2020 Oh, the filter needs to be applied using the svg filter attribute. I'm not entirely sure what the best way to do it is, I would have to do experiments. Either give a filter attribute to the <html:canvas> element or give it to the <foreignObject> tag. Either this: <html:canvas filter="url(#xPurple)" ... ... > or this: <foreignObject filter="url(#xPurple)"> ... ... If the <foreignObject> tag necessary? Quote Link to post Share on other sites
AARRGGHHH 0 Posted December 11, 2020 Author Report Share Posted December 11, 2020 Thank you once again! Neither worked, but I'm still trying different things to see if I can make it work. I've read <foreignObject> is needed, I'm not really sure. What I'll ultimately be doing is combining CSS and SVG filters to make changes to an image. This uh ... this can be done, right? I would think (hope) that canvas.filter will hold all the applied filters, not just the multiple CSS filters. Please let me know if you have any other thoughts on applying the svg filter attribute. Thanks again! Quote Link to post Share on other sites
Ingolme 1,019 Posted December 12, 2020 Report Share Posted December 12, 2020 I think it may be possible to use embedded SVG filters in the CSS rule. Have the SVG embedded anywhere in your document, but use the CSS rule on the <canvas> element. The same as the original solution, but instead of the SVG being in a different file, it is within the same document: <style> #myCanvas { filter: url("#darkGreen"); } </style> ... <svg> <defs> <filter id="darkGreen"> ... </filter> </defs> </svg> ... <canvas id="myCanvas"></canvas> With this setup (if it works), you will be able to edit the SVG filter with Javascript while also applying the filter to a <canvas> element. Quote Link to post Share on other sites
AARRGGHHH 0 Posted 20 hours ago Author Report Share Posted 20 hours ago Hi Ingolme Thank you once again! I was away for a while due to the holidays and an illness in the family. For some reason, the SVG filter is not being applied to the canvas cPreview, but is being applied to the canvas cSave. Do you have any thoughts on why this may be happening? Here's my code: <style> #cSave { filter: url("#svgCOLOR"); } #cPreview { filter: url("#svgCOLOR"); } </style> <!-- SVG Declaration --> <svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml" width="2" height="1"> <defs> <filter id="svgCOLOR"> <!-- Matrix values will eventually be adjustable using a range slider control --> <feColorMatrix type="matrix" values="2 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1" /> </filter> </defs> </svg> <!-- CANVAS cPreview --> <canvas id="cPreview" width="2" height="1" style="position:relative; max-width:100%;"></canvas> <!-- CANVAS cSave --> <canvas id="cSave" width="2" height="1" onclick="clickPreview()" style="position:relative; max-width:100%;"></canvas> Thank you! Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.