SVG:在悬停时将填充颜色应用于“蒙面”图像

时间:2022-11-20 22:47:14

I'm using clipPath to apply different "masking" effects to an image.

我正在使用clipPath对图像应用不同的“蒙版”效果。

How can I fill the clipped image with a color on hover? I've tried using :hover in CSS, but that didn't seem to work, unless I was targeting the incorrect element.

如何在悬停时用彩色填充剪裁的图像?我尝试过使用:将鼠标悬停在CSS中,但这似乎不起作用,除非我的目标是不正确的元素。

I'm using jQuery in this project, so if a JS solution is needed, I can lean on jQuery.

我在这个项目中使用jQuery,所以如果需要JS解决方案,我可以依靠jQuery。

Here's the HTML that I'm working with:

这是我正在使用的HTML:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
  <defs>
    <clipPath id="ellipse">
      <ellipse cx="50" cy="35.5" rx="49.5" ry="35" />
    </clipPath>
    <clipPath id="hexagon">
      <polygon points="25, 0  75, 0 100, 43.30127018922193 75, 86.60254037844386  25, 86.60254037844386  0, 43.30127018922193"/>
    </clipPath>
    <clipPath id="rectangle">
      <rect x="0" y="0" width="100" height="70"></rect>
    </clipPath>
  </defs>
  <g>
    <image preserveAspectRatio="none" x="0" y="0" width="100%" height="100%" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Bucephala-albeola-010.jpg/800px-Bucephala-albeola-010.jpg" id="clippy" clip-path="url(#hexagon)">
  </g>
</svg>

2 个解决方案

#1


7  

You might want to use a filter effect for giving the image some color on hover (see Tinkerbin):

您可能希望使用滤镜效果在悬停时为图像提供一些颜色(请参阅Tinkerbin):

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
  <style type="text/css">
    image:hover {
      filter:url(#Matrix);
    }
  </style>
  <defs>
    <clipPath id="ellipse">
      <ellipse cx="50" cy="35.5" rx="49.5" ry="35" />
    </clipPath>
    <clipPath id="hexagon">
      <polygon points="25, 0  75, 0 100, 43.30127018922193 75, 86.60254037844386  25, 86.60254037844386  0, 43.30127018922193"/>
    </clipPath>
    <clipPath id="rectangle">
      <rect x="0" y="0" width="100" height="70"></rect>
    </clipPath>
    <filter id="Matrix" filterUnits="objectBoundingBox" 
            x="0%" y="0%" width="100%" height="100%">
      <feColorMatrix type="matrix" in="SourceGraphic"
           values="1 0 0 0 .5 
                   .1 .9 0 0 0 
                   .1 0 .9 0 0 
                   0 0 0 1 0"/>
    </filter>
  </defs>
  <g>
    <image preserveAspectRatio="none" x="0" y="0" width="100%" height="100%" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Bucephala-albeola-010.jpg/800px-Bucephala-albeola-010.jpg" id="clippy" clip-path="url(#hexagon)">
  </g>
</svg>

Edit: Some explanation about the filter:

编辑:有关过滤器的一些说明:

The applied filter changes the color of every rastered pixel. It takes its original color value, applies the matrix specified by <feColorMatrix> to the color vector, and the resulting color vector becomes the displayed color.

应用的滤镜会更改每个光栅像素的颜色。它采用原始颜色值,将 指定的矩阵应用于颜色矢量,得到的颜色矢量成为显示的颜色。

How does the matrix work?

矩阵如何工作?

The matrix consists of four rows. The first row calculates the new red component, the second the green one, third blue, fourth alpha.

矩阵由四行组成。第一行计算新的红色组件,第二行计算绿色组件,第三行计算蓝色,第四行。

What's the meaning of the five numbers in each row? The first number is multiplied by the original color's red component, the second by the green one, third blue, fourth alpha. All four products are summed up, and the fifth value in the row is added as well (as a constant that does not depend on any of the original color components).

每行五个数字的含义是什么?第一个数字乘以原始颜色的红色分量,第二个数字乘以绿色,第三个蓝色,第四个alpha。总结了所有四个产品,并且还添加了行中的第五个值(作为不依赖于任何原始颜色分量的常量)。

Let's have a look at the above example: Let's assume we have a grey pixel with color values like

让我们看一下上面的例子:让我们假设我们有一个颜色值为灰色的像素

rgba(25%,25%,25%,1)

What would be the resulting red value? The first row that calculates the red value is

结果红色值会是什么?计算红色值的第一行是

1 0 0 0 .5

We calculate the following:

我们计算如下:

  1*r   + 0*g   + 0*b   + 0*a + .5
= 1*.25 + 0*.25 + 0*.25 + 0*1 + .5 = .75

This means, the resulting red component for the pixel is 75%. The other components are calculated analogously.

这意味着,像素的最终红色分量为75%。其他组件类似地计算。

#2


1  

Not sure if this is exactly what you want. Mouse events aren't sent to areas outside a cliparea. Quick & dirty, works in IE9, haven't tested in FF for example.

不确定这是否正是你想要的。鼠标事件不会发送到cliparea之外的区域。快速和脏,在IE9中工作,没有在FF测试例如。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
    <script type="application/ecmascript">
        function fillit(evt) {
            document.getElementById('fillarea').setAttribute('display', 'visible');
        }

        function emptyit(evt) {
            document.getElementById('fillarea').setAttribute('display', 'none');
        }
    </script>
    <defs>
        <clipPath id="ellipse">
            <ellipse cx="50" cy="35.5" rx="49.5" ry="35" />
        </clipPath>
        <clipPath id="hexagon">
            <polygon points="25, 0  75, 0 100, 43.30127018922193 75, 86.60254037844386  25, 86.60254037844386  0, 43.30127018922193" />
        </clipPath>
        <clipPath id="rectangle">
            <rect x="0" y="0" width="100" height="70"></rect>
        </clipPath>
    </defs>
    <g>
        <image preserveAspectRatio="none" x="0" y="0" width="100%" height="100%" 
               xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Bucephala-albeola-010.jpg/800px-Bucephala-albeola-010.jpg" 
               id="clippy" clip-path="url(#hexagon)" onmouseover="fillit(evt)" />
        <rect x="0" y="0" width="100%" height="100%" fill="red" display="none" 
              id="fillarea" clip-path="url(#hexagon)" onmouseout="emptyit(evt)" />
    </g>
</svg>

#1


7  

You might want to use a filter effect for giving the image some color on hover (see Tinkerbin):

您可能希望使用滤镜效果在悬停时为图像提供一些颜色(请参阅Tinkerbin):

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
  <style type="text/css">
    image:hover {
      filter:url(#Matrix);
    }
  </style>
  <defs>
    <clipPath id="ellipse">
      <ellipse cx="50" cy="35.5" rx="49.5" ry="35" />
    </clipPath>
    <clipPath id="hexagon">
      <polygon points="25, 0  75, 0 100, 43.30127018922193 75, 86.60254037844386  25, 86.60254037844386  0, 43.30127018922193"/>
    </clipPath>
    <clipPath id="rectangle">
      <rect x="0" y="0" width="100" height="70"></rect>
    </clipPath>
    <filter id="Matrix" filterUnits="objectBoundingBox" 
            x="0%" y="0%" width="100%" height="100%">
      <feColorMatrix type="matrix" in="SourceGraphic"
           values="1 0 0 0 .5 
                   .1 .9 0 0 0 
                   .1 0 .9 0 0 
                   0 0 0 1 0"/>
    </filter>
  </defs>
  <g>
    <image preserveAspectRatio="none" x="0" y="0" width="100%" height="100%" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Bucephala-albeola-010.jpg/800px-Bucephala-albeola-010.jpg" id="clippy" clip-path="url(#hexagon)">
  </g>
</svg>

Edit: Some explanation about the filter:

编辑:有关过滤器的一些说明:

The applied filter changes the color of every rastered pixel. It takes its original color value, applies the matrix specified by <feColorMatrix> to the color vector, and the resulting color vector becomes the displayed color.

应用的滤镜会更改每个光栅像素的颜色。它采用原始颜色值,将 指定的矩阵应用于颜色矢量,得到的颜色矢量成为显示的颜色。

How does the matrix work?

矩阵如何工作?

The matrix consists of four rows. The first row calculates the new red component, the second the green one, third blue, fourth alpha.

矩阵由四行组成。第一行计算新的红色组件,第二行计算绿色组件,第三行计算蓝色,第四行。

What's the meaning of the five numbers in each row? The first number is multiplied by the original color's red component, the second by the green one, third blue, fourth alpha. All four products are summed up, and the fifth value in the row is added as well (as a constant that does not depend on any of the original color components).

每行五个数字的含义是什么?第一个数字乘以原始颜色的红色分量,第二个数字乘以绿色,第三个蓝色,第四个alpha。总结了所有四个产品,并且还添加了行中的第五个值(作为不依赖于任何原始颜色分量的常量)。

Let's have a look at the above example: Let's assume we have a grey pixel with color values like

让我们看一下上面的例子:让我们假设我们有一个颜色值为灰色的像素

rgba(25%,25%,25%,1)

What would be the resulting red value? The first row that calculates the red value is

结果红色值会是什么?计算红色值的第一行是

1 0 0 0 .5

We calculate the following:

我们计算如下:

  1*r   + 0*g   + 0*b   + 0*a + .5
= 1*.25 + 0*.25 + 0*.25 + 0*1 + .5 = .75

This means, the resulting red component for the pixel is 75%. The other components are calculated analogously.

这意味着,像素的最终红色分量为75%。其他组件类似地计算。

#2


1  

Not sure if this is exactly what you want. Mouse events aren't sent to areas outside a cliparea. Quick & dirty, works in IE9, haven't tested in FF for example.

不确定这是否正是你想要的。鼠标事件不会发送到cliparea之外的区域。快速和脏,在IE9中工作,没有在FF测试例如。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
    <script type="application/ecmascript">
        function fillit(evt) {
            document.getElementById('fillarea').setAttribute('display', 'visible');
        }

        function emptyit(evt) {
            document.getElementById('fillarea').setAttribute('display', 'none');
        }
    </script>
    <defs>
        <clipPath id="ellipse">
            <ellipse cx="50" cy="35.5" rx="49.5" ry="35" />
        </clipPath>
        <clipPath id="hexagon">
            <polygon points="25, 0  75, 0 100, 43.30127018922193 75, 86.60254037844386  25, 86.60254037844386  0, 43.30127018922193" />
        </clipPath>
        <clipPath id="rectangle">
            <rect x="0" y="0" width="100" height="70"></rect>
        </clipPath>
    </defs>
    <g>
        <image preserveAspectRatio="none" x="0" y="0" width="100%" height="100%" 
               xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Bucephala-albeola-010.jpg/800px-Bucephala-albeola-010.jpg" 
               id="clippy" clip-path="url(#hexagon)" onmouseover="fillit(evt)" />
        <rect x="0" y="0" width="100%" height="100%" fill="red" display="none" 
              id="fillarea" clip-path="url(#hexagon)" onmouseout="emptyit(evt)" />
    </g>
</svg>