I am trying to implement a visual 'diff' strategy for printed circuit boards. The intent is to highlight 'new' additions in blue and old parts of the design (removed) in red. I have two b&w svg files each of which represent a particular revision of a single layer of the board. These are generated programatically. They look something like this png image of example svg- I cannot upload an .svg directly but there are a couple of examples here;
I have applied two separate feColorMatrix filters, one filter to version 1 & the other version 2 and have then placed both filtered images, positioned absolutely so they overlay each other, within a single <div>
.
This works in Chrome but fails in other browsers (have tried both Safari and Firefox).
I have attempted to apply the feColorMatrix filter directly and merge the result files but that does not work at all in any browser.
My current successful code (for Chrome):
.gallery {
border: 1px solid #ccc;
}
.gallery:hover {
border: 1px solid #777;
}
.gallery img {
width: 100%;
height: auto;
}
<div class="gallery">
<svg width="1123px" height="794px" viewBox="50 0 600 400" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="f1" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix result="original" id="c1" type="matrix" values="1 0 0 0 0
0 1 0 1 0
0 0 1 1 0
0 0 0 1 0 " />
</filter>
<filter id="f2" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix result="original" id="c2" type="matrix" values="1 0 0 1 0
0 1 0 0 0
0 0 1 0 0
0 0 0 .5 0" />
</filter>
</defs>
<image x="0" y="0" width="100%" filter="url(#f1)" xlink:href="../../75d8f4/ThermocoupleLogger-F_Cu.svg" style="position:absolute;" />
<image x="0" y="0" width="100%" filter="url(#f2)" xlink:href="../../3c9fec/ThermocoupleLogger-F_Cu.svg" style="position:absolute;" />
</svg>
</div>
My alternative attempt with a feMerge:
<div class="gallery">
<svg width="1123px" height="794px" viewBox="50 0 600 400" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="f1" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix xlink:href="../../75d8f4/ThermocoupleLogger-F_Cu.svg" result="one" type="matrix"
values="1 0 0 0 0
0 1 0 1 0
0 0 1 1 0
0 0 0 1 0 " />
</filter>
<filter id="f2" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix xlink:href="../../3c9fec/ThermocoupleLogger-F_Cu.svg" result="two" type="matrix"
values="1 0 0 1 0
0 1 0 0 0
0 0 1 0 0
0 0 0 .5 0" />
</filter>
<filter id="composite">
<feMerge>
<feMergeNode in="one"/>
<feMergeNode in="two"/>
</feMerge>
</filter>
</defs>
<g filter="url(#composite)"></g>
</svg>
</div>
I would value any advice that would allow me to achieve this with some degree of cross browser compatibility.
Your first version is mostly right - but add a height attribute directly to your image tag - SVG is fussy about dimensions & Chrome often accepts things it shouldn't. img and image tags are different elements, so that height:auto isn't applying to your image tags. Also - there is a limited number of CSS styles that apply to SVG sub-elements - when in doubt stick to SVG attributes. And remove the position: absolute
- positioning in SVG is absolute by default.
The second version won't work for numerous reasons. feColorMatrix doesn't take an xlink:href as an input - you have to import an external file into a filter using feImage first and add a result
attribute to it. You can then reference the result in the in
attribute of your feColorMatrix. Filters can only reference a result
within the same filter - so referencing one
and two
from the id=composite
filter won't work. Lastly, filtering an empty g
tag won't work - it doesn't have any dimensions so the filter area is zero. So ... use this tweaked version of your first try.
.gallery {
border: 1px solid #ccc;
}
.gallery:hover {
border: 1px solid #777;
}
.gallery img {
width: 100%;
height: auto;
}
<div class="gallery">
<svg width="1123px" height="794px" viewBox="50 0 600 400" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="f1" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix result="original" id="c1" type="matrix" values="1 0 0 0 0
0 1 0 1 0
0 0 1 1 0
0 0 0 1 0 " />
</filter>
<filter id="f2" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix result="original" id="c2" type="matrix" values="1 0 0 1 0
0 1 0 0 0
0 0 1 0 0
0 0 0 .5 0" />
</filter>
</defs>
<image x="0" y="0" height="100%" width="100%" filter="url(#f1)" xlink:href="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/beacon.svg" />
<image x="0" y="0" height="100%" width="100%" filter="url(#f2)" xlink:href="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/adobe.svg" />
</svg>
</div>
You can also do a more elegant version by using feComposite's xor operator. Mouse over to see the effect.
svg :hover {
filter: url(#diff);
}
<svg width="1600px" height="800px" viewBox="0 0 1600 800">
<defs>
<filter id="diff" x="20%" y="0%" width="80%" height="100%" >
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0" result="blue-original"/>
<feImage x="-100" y="0" width="800" height="600" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/32648/SVG-Test%201.svg">
</feImage>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"/>
<feComposite operator="xor" in="blue-original"/>
</filter>
</defs>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/32648/SVG-test2.svg" x="-100" y="0" width="800" height="600" preserveAspectRatio="xMinYMin slice"/>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/32648/SVG-Test%201.svg" x="500" y="0" width="800" height="600" preserveAspectRatio="xMinYMin slice"/>
</svg>