Part Of Svg Mask Is Opaque And Color Is Inverted
Solution 1:
You need to see your <mask>
as a standalone grayscale image, that will get applied to the target element.
There every black pixels will be removed from the target, while every white and transparent ones will stay untouched or in other words, the darker it is in the mask, the more transparent it will be on the target.
So here are both masks
.bg {
width: 100%;
height: 100%;
fill: #666;
}
#background {
fill: #999;
}
#eye {
fill: #fff;
}
.fake-mask {
filter: grayscale(100%);
}
svg{width: 40vw; display: inline-block}
<svgviewBox='0 0 800 800'><defs><filterid="blurMe"><feGaussianBlurin="SourceGraphic"stdDeviation="2" /></filter></defs><!-- <mask id="myMask"> --><gclass="fake-mask"><rectclass='bg'width="800"height="800"/><gid="rectangle"filter="url(#blurMe)"><rectwidth="300"height="400"x="120"rx='10'ry='10'fill="white" /><imagexlink:href='https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png'width="200"height="200"/></g></g><!-- </mask> --></svg><svgviewBox='0 0 800 800'><!-- <mask id='mask'> --><gclass="fake-mask"><rectid='background'x='0'y='0'width='6144'height='4608' /><rectid='eye'x='0'y='0'width='500'height='500' /><imageid='frame'xlink:href='https://newvitruvian.com/images/speckled-vector-distress.png'x='0'y='0'width='500'height='500'preserveAspectRatio='none' /></g><!-- </mask> --></svg>
As you can see, your image's border is darker than the background rectangle, this means that the target will be more transparent at this image's border than in the background.
To solve this issue, you would have to make the black pixels of your image become the same shade of gray as the background, so that the target can get an unified opacity.
And while it is possible to do it with filters, note that it may kill the performances.
const
bdy = document.body,
svg = document.getElementById('svg'),
bkg = document.getElementById('background'),
eye = document.getElementById('eye'),
frm = document.getElementById('frame')
let
eyeW = 0.35,
eyeH = 0.75,
mousednX = 0,
mousednY = 0// position maps on load//window.addEventListener('load', position)
functionposition(){
const
box = svg.getBoundingClientRect()
svg.style.left = -(box.width - innerWidth) / 2 + 'px'
svg.style.top = -(box.height - innerHeight) / 2 + 'px'const
x = -(svg.getBoundingClientRect().left) + innerWidth * (1 - eyeW) / 2,
y = -(svg.getBoundingClientRect().top) + innerHeight * (1 - eyeH) / 2
eye.setAttribute('width', innerWidth * eyeW)
eye.setAttribute('height', innerHeight * eyeH)
eye.setAttribute('x', x)
eye.setAttribute('y', y)
frm.setAttribute('width', innerWidth * eyeW)
frm.setAttribute('height', innerHeight * eyeH)
frm.setAttribute('x', x)
frm.setAttribute('y', y)
}
// drag functionality to explore map//
bdy.addEventListener('mousedown', mousedown)
window.addEventListener('mouseup', mouseup)
functionmousedown(e){
e.preventDefault()
mousednX = e.clientX
mousednY = e.clientY
bdy.addEventListener('mousemove', mousemove)
}
functionmouseup(){
bdy.removeEventListener('mousemove', mousemove)
}
functionmousemove(e){
adjustX = e.clientX - mousednX
adjustY = e.clientY - mousednY
if (svg.getBoundingClientRect().left + adjustX < 0 && svg.getBoundingClientRect().right + adjustX > innerWidth){
svg.style.left = svg.getBoundingClientRect().left + adjustX + 'px'
} elseif (svg.getBoundingClientRect().left + adjustX >= 0){
svg.style.left = 0 + 'px'
} else {
svg.style.left = -(svg.getBoundingClientRect().width - innerWidth)
}
if (svg.getBoundingClientRect().top + adjustY < 0 && svg.getBoundingClientRect().bottom + adjustY > innerHeight){
svg.style.top = svg.getBoundingClientRect().top + adjustY + 'px'
} elseif (svg.getBoundingClientRect().top + adjustY >= 0){
svg.style.top = 0 + 'px'
} else {
svg.style.top = -(svg.getBoundingClientRect().height - innerHeight)
}
mousednX = e.clientX
mousednY = e.clientY
}
// center eye on cursor position//
bdy.addEventListener('mousemove', moveEye)
functionmoveEye(e){
const
x = -(svg.getBoundingClientRect().left) + e.clientX - eyeW * innerWidth / 2,
y = -(svg.getBoundingClientRect().top) + e.clientY - eyeH * innerHeight / 2
eye.setAttribute('x', x)
eye.setAttribute('y', y)
frm.setAttribute('x', x)
frm.setAttribute('y', y)
}
body {
width: 100vw;
height: 100vh;
overflow: hidden;
margin: 0;
}
#svg {
width: 6144px;
height: 4608px;
position: absolute;
left: -3072px;
top: -2304px;
}
#eye {
fill: #FFF;
}
#map {
width: 6144px;
height: 4608px;
mask: url('#mask');
}
<svgid='svg'viewBox='0 0 6144 4608'version='1.1'><filterid="contrast"><feComponentTransfer><feFuncRtype="linear"slope="0.4"intercept="0.2"/><feFuncGtype="linear"slope="0.4"intercept="0.2"/><feFuncBtype="linear"slope="0.4"intercept="0.2"/></feComponentTransfer></filter><maskid='mask'><gfilter="url(#contrast)"><rectid='background'x='0'y='0'width='6144'height='4608'fill="#000"/><rectid='eye'x='0'y='0'width='0'height='0' /><imageid='frame'xlink:href='https://newvitruvian.com/images/speckled-vector-distress.png'x='0'y='0'width='0'height='0'preserveAspectRatio='none'/></g></mask><imageid='map'xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg'x='0'y='0'width='6144'height='4608'mask="url(#myMask)"/></svg>
Solution 2:
Playing with your work in CodePen, I noticed that the white you get in the #frame
image and the outer background comes from the default SVG document background color, which is not defined and appears to be white.
If you define the background-color
style for the #svg
element, say #f00
(red), you will see both the background and the #frame
image as red.
Finally, I found that tweaking the opacity
of the #frame
image to 0.4
gives a better blend of the masked frame and background. You might re-paint the #frame
image to better match the background at the borders of the image rectangle.
I just added the background-color
(white) and opacity
(0.4) in your CodePen as follows:
#svg {
width: 6144px;
height: 4608px;
position: absolute;
left: -3072px;
top: -2304px;
background-color: #fff;
}
#frame {
opacity: .4;
}
Post a Comment for "Part Of Svg Mask Is Opaque And Color Is Inverted"