简体   繁体   English

像画布渐变一样的SVG渐变?

[英]SVG Gradient like Canvas Gradient?

Here is what I've built. 是我建造的。 You can drag the image around to explore the whole image. 您可以拖动图像来浏览整个图像。

<?xml version='1.0' standalone='no'?>
<svg version='1.1'>
  <image xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg'
    id='background-image' />
  <clipPath>
    <rect />
  </clipPath>
  <image xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg'
    id='main-image'/>
</svg>

Instead of the clipped rectangle having solid edges, what I would like to do is something like this, except for SVG. 除了具有实心边缘的裁剪矩形之外,我想做的是这样, 除了SVG。 The caveat is that it must be responsive since the clipped rectangle is responsive. 需要注意的是,由于裁剪后的矩形具有响应性,因此它必须具有响应性。

Is it possible to do something similar in SVG? 可以在SVG中做类似的事情吗?

One idea that comes to mind is something similar to either of the following images, whereby multiple gradients would be used, but it seems like a whole lot of work for something that can be done so easily in canvas. 我想到的一个想法是类似于以下任一图像,其中将使用多个渐变,但是对于可以在画布中轻松完成的操作来说,似乎需要大量工作。

在此处输入图片说明

在此处输入图片说明

What you want is a <mask> . 您想要的是<mask>

In this mask, you will append your small rounded <rect> filled in black, with an feGaussianBlur applied on it. 在此蒙版中,将附加黑色填充的小圆形<rect> ,并在其上应用feGaussianBlur。

 const bdy = document.body, svg = document.getElementById('svg'), crc = document.getElementById('circle'), rec = document.getElementById('rectangle') let mousednX = 0, mousednY = 0 window.addEventListener('load', position) bdy.addEventListener('mousedown', mousedown) window.addEventListener('mouseup', mouseup) bdy.addEventListener('mousemove', moveEye) function position(){ const box = svg.getBoundingClientRect() svg.style.left = -(box.width - innerWidth) / 2 + 'px' svg.style.top = -(box.height - innerHeight) / 2 + 'px' } function mousedown(e){ e.preventDefault() mousednX = e.clientX mousednY = e.clientY bdy.addEventListener('mousemove', mousemove) } function mouseup(){ bdy.removeEventListener('mousemove', mousemove) } function mousemove(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' } else if (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' } else if (svg.getBoundingClientRect().top + adjustY >= 0){ svg.style.top = 0 + 'px' } else { svg.style.top = -(svg.getBoundingClientRect().height - innerHeight) } mousednX = e.clientX mousednY = e.clientY } function moveEye(e){ rec.setAttribute('x', -(svg.getBoundingClientRect().left) + e.clientX - rec.getBoundingClientRect().width / 2) rec.setAttribute('y', -(svg.getBoundingClientRect().top) + e.clientY - rec.getBoundingClientRect().height / 2) } 
 body { width: 100vw; height: 100vh; overflow: hidden; margin: 0; } #svg { width: 6144px; height: 4608px; position: absolute; left: -3072px; /* set with JS */ top: -2304px; /* set with JS */ } #background-image { width: 6144px; height: 4608px; opacity: 0.25; } #rectangle { width: 35vw; height: 75vh; } #main-image { width: 6144px; height: 4608px; mask: url(#myMask); } #myMask .bg { width: 100%; height: 100%; } 
 <svg id='svg' viewBox='0 0 6144 4608' version='1.1'> <defs> <filter id="blurMe"> <feGaussianBlur in="SourceGraphic" stdDeviation="5" /> </filter> <mask id="myMask"> <rect class='bg'/> <rect id='rectangle' x='3172' y='2404' rx='10' ry='10' fill="white" filter="url(#blurMe)"/> </mask> </defs> <image x='0' y='0' preserveAspectRatio='none' xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg' id='background-image' /> <image x='0' y='0' preserveAspectRatio='none' xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg' id='main-image'/> </svg> 

But note that setting the dimensions of your svg elements through CSS is a new feature of SVG2 and that all browsers still didn't implemented it (eg Firefox). 但是请注意,通过CSS设置svg元素的尺寸是SVG2的一项新功能,并且所有浏览器仍未实现它(例如Firefox)。 So here is an SVG1 compliant version, but there the vw / vh units won't work. 因此,这里是SVG1兼容版本,但是那里的vw / vh单位不起作用。

 <svg width="500" height="500" viewBox="0 0 500 500"> <defs> <filter id="blurMe"> <feGaussianBlur in="SourceGraphic" stdDeviation="5" /> </filter> <mask id="myMask"> <rect width="500" height="500" fill="black"/> <rect y="100" fill="white" width="50" height="50" x="35" y="35" rx="5" ry="5" filter="url(#blurMe)"/> </mask> </defs> <image xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg' id='background-image' width="500" height="500" style="opacity:0.3"/> <image xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg' id='main-image' width="500" height="500" mask="url(#myMask)"/> </svg> 

And you could even make this all with a single image, by setting the background's fill color to some shade of gray: 通过将背景的填充颜色设置为某种灰色阴影,您甚至可以只用一张图像就可以完成所有操作:

 <svg width="500" height="500" viewBox="0 0 500 500"> <defs> <filter id="blurMe"> <feGaussianBlur in="SourceGraphic" stdDeviation="5" /> </filter> <mask id="myMask"> <rect width="500" height="500" fill="#333"/> <rect y="100" fill="white" width="50" height="50" x="35" y="35" rx="5" ry="5" filter="url(#blurMe)"/> </mask> </defs> <image xlink:href='https://i.postimg.cc/hvH4yn2Q/map.jpg' id='main-image' width="500" height="500" mask="url(#myMask)"/> </svg> 

Here is the interactive version with a single image. 这是带有单个图像的交互式版本

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM