【问题标题】:Aligning SVG Clip Path on top of image在图像顶部对齐 SVG 剪辑路径
【发布时间】:2021-03-19 16:53:46
【问题描述】:

编辑 1:我当前问题的快速代码笔:https://codepen.io/zuffdaddy/pen/QWGewKr 看到剪辑路径很大而图像很小吗?这两者如何对齐?

原文:

简介: 我正在为潜艇模拟器游戏制作 Attack Disc。

圆盘有多个可以旋转的圆环,到目前为止,我已经完成了那个部分,但是有一些重叠的透明塑料部件位于圆环顶部并且也可以旋转。

问题: 问题是在顶部旋转的塑料件是复杂的形状(image of the shape here)。用户需要能够单击它们以操纵它们下方的环但也能够单击它们来旋转它们)

SVG 剪辑路径似乎是可行的方法但我无法让 svg 剪辑路径与图像对齐

请忽略 JS,这是我从另一个问题中提取的临时轮换脚本,将在最终确定时重写。

///////////////////////////////
// -------  rotate  -------- //
///////////////////////////////

(function() {
  var init, rotate, start, stop,
    active = false,
    angle = 0,
    rotation = 0,
    startAngle = 0,
    center = {
      x: 0,
      y: 0
    },
    R2D = 180 / Math.PI,
    rot = document.getElementById('attack_disc');

  init = function() {
    rot.addEventListener("mousedown", start, false);
    $(document).bind('mousemove', function(event) {
      if (active === true) {
        event.preventDefault();
        rotate(event);
      }
    });
    $(document).bind('mouseup', function(event) {
      event.preventDefault();
      stop(event);
    });
  };

  start = function(e) {
    e.preventDefault();
    var bb = this.getBoundingClientRect(),
      t = bb.top,
      l = bb.left,
      h = bb.height,
      w = bb.width,
      x, y;
    center = {
      x: l + (w / 2),
      y: t + (h / 2)
    };
    x = e.clientX - center.x;
    y = e.clientY - center.y;
    startAngle = R2D * Math.atan2(y, x);
    return active = true;
  };

  rotate = function(e) {
    e.preventDefault();
    var x = e.clientX - center.x,
      y = e.clientY - center.y,
      d = R2D * Math.atan2(y, x);
    rotation = d - startAngle;
    return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
  };

  stop = function() {
    angle += rotation;
    return active = false;
  };

  init();

}).call(this);

(function() {
  var init, rotate, start, stop,
    active = false,
    angle = 0,
    rotation = 0,
    startAngle = 0,
    center = {
      x: 0,
      y: 0
    },
    R2D = 180 / Math.PI,
    rot = document.getElementById('course_disc');

  init = function() {
    rot.addEventListener("mousedown", start, false);
    $(document).bind('mousemove', function(event) {
      if (active === true) {
        event.preventDefault();
        rotate(event);
      }
    });
    $(document).bind('mouseup', function(event) {
      event.preventDefault();
      stop(event);
    });
  };

  start = function(e) {
    e.preventDefault();
    var bb = this.getBoundingClientRect(),
      t = bb.top,
      l = bb.left,
      h = bb.height,
      w = bb.width,
      x, y;
    center = {
      x: l + (w / 2),
      y: t + (h / 2)
    };
    x = e.clientX - center.x;
    y = e.clientY - center.y;
    startAngle = R2D * Math.atan2(y, x);
    return active = true;
  };

  rotate = function(e) {
    e.preventDefault();
    var x = e.clientX - center.x,
      y = e.clientY - center.y,
      d = R2D * Math.atan2(y, x);
    rotation = d - startAngle;
    return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
  };

  stop = function() {
    angle += rotation;
    return active = false;
  };

  init();

}).call(this);

(function() {
  var init, rotate, start, stop,
    active = false,
    angle = 0,
    rotation = 0,
    startAngle = 0,
    center = {
      x: 0,
      y: 0
    },
    R2D = 180 / Math.PI,
    rot = document.getElementById('aob_disc');

  init = function() {
    rot.addEventListener("mousedown", start, false);
    $(document).bind('mousemove', function(event) {
      if (active === true) {
        event.preventDefault();
        rotate(event);
      }
    });
    $(document).bind('mouseup', function(event) {
      event.preventDefault();
      stop(event);
    });
  };

  start = function(e) {
    e.preventDefault();
    var bb = this.getBoundingClientRect(),
      t = bb.top,
      l = bb.left,
      h = bb.height,
      w = bb.width,
      x, y;
    center = {
      x: l + (w / 2),
      y: t + (h / 2)
    };
    x = e.clientX - center.x;
    y = e.clientY - center.y;
    startAngle = R2D * Math.atan2(y, x);
    return active = true;
  };

  rotate = function(e) {
    e.preventDefault();
    var x = e.clientX - center.x,
      y = e.clientY - center.y,
      d = R2D * Math.atan2(y, x);
    rotation = d - startAngle;
    return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
  };

  stop = function() {
    angle += rotation;
    return active = false;
  };

  init();

}).call(this);

(function() {
  var init, rotate, start, stop,
    active = false,
    angle = 0,
    rotation = 0,
    startAngle = 0,
    center = {
      x: 0,
      y: 0
    },
    R2D = 180 / Math.PI,
    rot = document.getElementById('bearing_lead_disc');

  init = function() {
    rot.addEventListener("mousedown", start, false);
    $(document).bind('mousemove', function(event) {
      if (active === true) {
        event.preventDefault();
        rotate(event);
      }
    });
    $(document).bind('mouseup', function(event) {
      event.preventDefault();
      stop(event);
    });
  };

  start = function(e) {
    e.preventDefault();
    var bb = this.getBoundingClientRect(),
      t = bb.top,
      l = bb.left,
      h = bb.height,
      w = bb.width,
      x, y;
    center = {
      x: l + (w / 2),
      y: t + (h / 2)
    };
    x = e.clientX - center.x;
    y = e.clientY - center.y;
    startAngle = R2D * Math.atan2(y, x);
    return active = true;
  };

  rotate = function(e) {
    e.preventDefault();
    var x = e.clientX - center.x,
      y = e.clientY - center.y,
      d = R2D * Math.atan2(y, x);
    rotation = d - startAngle;
    return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
  };

  stop = function() {
    angle += rotation;
    return active = false;
  };

  init();

}).call(this);
html {
  height: 100%;
  overflow: hidden;
}

body {
  background: #1c1c1c;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.wrapper {
  height: 100%;
  max-height: 960px;
  width: 100%;
  max-width: 960px;
  position: relative;
  margin: auto;
}

#attack_disc {
  background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/1.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  width: 30vw;
  max-width: 1124px;
  height: 30vw;
  max-height: 1124px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  transform-origin: 50% 50%;
  border-radius: 50%;
}

#course_disc {
  background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/2.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  width: 23vw;
  max-width: 868px;
  height: 23vw;
  max-height: 868px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  transform-origin: 50% 50%;
  border-radius: 50%;
}

#aob_disc {
  background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/3.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  width: 15.5vw;
  max-width: 592px;
  height: 15.5vw;
  max-height: 592px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  transform-origin: 50% 50%;
  border-radius: 50%;
}

#bearing_lead_disc {
  background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/4.png');
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  width: 23.5vw;
  max-width: 884px;
  height: 23.5vw;
  max-height: 884px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  clip-path: url('#my-clip-path');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <div id="attack_disc"></div>
  <div id="course_disc"></div>
  <div id="aob_disc"></div>
  <div id="bearing_lead_disc">
    <svg class="svg">
          <clipPath id="my-clip-path" clipPathUnits="objectBoundingBox"><path d="M0.501,0 C0.556,0,0.555,0.04,0.555,0.04 C0.555,0.099,0.984,0.229,0.994,0.232 S1,0.243,0.999,0.251 C0.976,0.284,0.874,0.421,0.656,0.469 C0.656,0.469,0.648,0.47,0.647,0.474 C0.646,0.48,0.572,0.984,0.57,0.992 C0.569,0.996,0.569,0.999,0.561,0.999 C0.522,1,0.516,1,0.502,1 C0.487,1,0.482,1,0.443,0.999 C0.434,0.999,0.434,0.996,0.433,0.992 C0.432,0.984,0.358,0.48,0.357,0.474 C0.356,0.47,0.347,0.469,0.347,0.469 H0.347 C0.129,0.421,0.027,0.284,0.005,0.251 C0,0.243,0,0.236,0.01,0.232 S0.449,0.099,0.449,0.04 C0.449,0.04,0.447,0,0.502,0"></path></clipPath>
        </svg>
  </div>

</div>

【问题讨论】:

    标签: html css svg


    【解决方案1】:

    问题似乎是您提取了形状并将其转换为相对于自身的objectBoundingBox 坐标。因此 objectBoundingBox 坐标不再与您的攻击盘图像相关。

    您可以对剪辑路径应用变换以将其缩小到应有的位置。通过反复试验,我制定了适当的缩放比例,使其与应该剪辑的形状相匹配。

    transform="translate(0.5,1) scale(0.415,0.52) translate(-0.5,-1)"
    

    .svg {
      position: absolute;
      width: 0;
      height: 0;
    }
    .clipped {
      width: 884px;
      height: 884px;
      background: turquoise url(https://zuffdaddy.github.io/uboat-attack-disc/images/4.png);
      background-size: cover;
      -webkit-clip-path: url(#my-clip-path);
      clip-path: url(#my-clip-path);
    }
    <svg class="svg">
      <clipPath id="my-clip-path" clipPathUnits="objectBoundingBox"><path d="M0.501,0 C0.556,0,0.555,0.04,0.555,0.04 C0.555,0.099,0.984,0.229,0.994,0.232 S1,0.243,0.999,0.251 C0.976,0.284,0.874,0.421,0.656,0.469 C0.656,0.469,0.648,0.47,0.647,0.474 C0.646,0.48,0.572,0.984,0.57,0.992 C0.569,0.996,0.569,0.999,0.561,0.999 C0.522,1,0.516,1,0.502,1 C0.487,1,0.482,1,0.443,0.999 C0.434,0.999,0.434,0.996,0.433,0.992 C0.432,0.984,0.358,0.48,0.357,0.474 C0.356,0.47,0.347,0.469,0.347,0.469 H0.347 C0.129,0.421,0.027,0.284,0.005,0.251 C0,0.243,0,0.236,0.01,0.232 S0.449,0.099,0.449,0.04 C0.449,0.04,0.447,0,0.502,0" transform="translate(0.5,1) scale(0.415,0.52) translate(-0.5,-1)"></path></clipPath>
    </svg>
    
    <div class="clipped"></div>

    【讨论】:

    • 就是这样!我已经更新了我的 sn-p 以显示更正,非常感谢 Paul!
    【解决方案2】:

    Svg 最好放在 div 里面

    Svg 最好放在 div 里面,这样你就可以更好地控制形状,它也可以是缩放的。

    首先我用这个网站 (https://aydos.com/svgedit/) 修复你的路径“d”

    其次,我将 svg 放入 div 中

    第三,我将带有视图框的 svg 订购为合适的(红色有些透明),例如“bearing_lead_disc”中的背景图像链接,并使用 css pointer-events:none 忽略单击 div,然后我们可以旋转即使我们点击了形状,也会出现圆圈。

    链接:(https://codepen.io/omergal/pen/qBqzeQa)

    图片:

    ///////////////////////////////
    // -------  rotate  -------- //
    ///////////////////////////////
    
    (function() {
      var init, rotate, start, stop,
        active = false,
        angle = 0,
        rotation = 0,
        startAngle = 0,
        center = {
          x: 0,
          y: 0
        },
        R2D = 180 / Math.PI,
        rot = document.getElementById('attack_disc');
    
      init = function() {
        rot.addEventListener("mousedown", start, false);
        $(document).bind('mousemove', function(event) {
          if (active === true) {
            event.preventDefault();
            rotate(event);
          }
        });
        $(document).bind('mouseup', function(event) {
          event.preventDefault();
          stop(event);
        });
      };
    
      start = function(e) {
        e.preventDefault();
        var bb = this.getBoundingClientRect(),
          t = bb.top,
          l = bb.left,
          h = bb.height,
          w = bb.width,
          x, y;
        center = {
          x: l + (w / 2),
          y: t + (h / 2)
        };
        x = e.clientX - center.x;
        y = e.clientY - center.y;
        startAngle = R2D * Math.atan2(y, x);
        return active = true;
      };
    
      rotate = function(e) {
        e.preventDefault();
        var x = e.clientX - center.x,
          y = e.clientY - center.y,
          d = R2D * Math.atan2(y, x);
        rotation = d - startAngle;
        return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
      };
    
      stop = function() {
        angle += rotation;
        return active = false;
      };
    
      init();
    
    }).call(this);
    
    (function() {
      var init, rotate, start, stop,
        active = false,
        angle = 0,
        rotation = 0,
        startAngle = 0,
        center = {
          x: 0,
          y: 0
        },
        R2D = 180 / Math.PI,
        rot = document.getElementById('course_disc');
    
      init = function() {
        rot.addEventListener("mousedown", start, false);
        $(document).bind('mousemove', function(event) {
          if (active === true) {
            event.preventDefault();
            rotate(event);
          }
        });
        $(document).bind('mouseup', function(event) {
          event.preventDefault();
          stop(event);
        });
      };
    
      start = function(e) {
        e.preventDefault();
        var bb = this.getBoundingClientRect(),
          t = bb.top,
          l = bb.left,
          h = bb.height,
          w = bb.width,
          x, y;
        center = {
          x: l + (w / 2),
          y: t + (h / 2)
        };
        x = e.clientX - center.x;
        y = e.clientY - center.y;
        startAngle = R2D * Math.atan2(y, x);
        return active = true;
      };
    
      rotate = function(e) {
        e.preventDefault();
        var x = e.clientX - center.x,
          y = e.clientY - center.y,
          d = R2D * Math.atan2(y, x);
        rotation = d - startAngle;
        return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
      };
    
      stop = function() {
        angle += rotation;
        return active = false;
      };
    
      init();
    
    }).call(this);
    
    (function() {
      var init, rotate, start, stop,
        active = false,
        angle = 0,
        rotation = 0,
        startAngle = 0,
        center = {
          x: 0,
          y: 0
        },
        R2D = 180 / Math.PI,
        rot = document.getElementById('aob_disc');
    
      init = function() {
        rot.addEventListener("mousedown", start, false);
        $(document).bind('mousemove', function(event) {
          if (active === true) {
            event.preventDefault();
            rotate(event);
          }
        });
        $(document).bind('mouseup', function(event) {
          event.preventDefault();
          stop(event);
        });
      };
    
      start = function(e) {
        e.preventDefault();
        var bb = this.getBoundingClientRect(),
          t = bb.top,
          l = bb.left,
          h = bb.height,
          w = bb.width,
          x, y;
        center = {
          x: l + (w / 2),
          y: t + (h / 2)
        };
        x = e.clientX - center.x;
        y = e.clientY - center.y;
        startAngle = R2D * Math.atan2(y, x);
        return active = true;
      };
    
      rotate = function(e) {
        e.preventDefault();
        var x = e.clientX - center.x,
          y = e.clientY - center.y,
          d = R2D * Math.atan2(y, x);
        rotation = d - startAngle;
        return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
      };
    
      stop = function() {
        angle += rotation;
        return active = false;
      };
    
      init();
    
    }).call(this);
    
    (function() {
      var init, rotate, start, stop,
        active = false,
        angle = 0,
        rotation = 0,
        startAngle = 0,
        center = {
          x: 0,
          y: 0
        },
        R2D = 180 / Math.PI,
        rot = document.getElementById('bearing_lead_disc');
    
      init = function() {
        rot.addEventListener("mousedown", start, false);
        $(document).bind('mousemove', function(event) {
          if (active === true) {
            event.preventDefault();
            rotate(event);
          }
        });
        $(document).bind('mouseup', function(event) {
          event.preventDefault();
          stop(event);
        });
      };
    
      start = function(e) {
        e.preventDefault();
        var bb = this.getBoundingClientRect(),
          t = bb.top,
          l = bb.left,
          h = bb.height,
          w = bb.width,
          x, y;
        center = {
          x: l + (w / 2),
          y: t + (h / 2)
        };
        x = e.clientX - center.x;
        y = e.clientY - center.y;
        startAngle = R2D * Math.atan2(y, x);
        return active = true;
      };
    
      rotate = function(e) {
        e.preventDefault();
        var x = e.clientX - center.x,
          y = e.clientY - center.y,
          d = R2D * Math.atan2(y, x);
        rotation = d - startAngle;
        return rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)";
      };
    
      stop = function() {
        angle += rotation;
        return active = false;
      };
    
      init();
    
    }).call(this);
    html {
        height: 100%;
        overflow: hidden;
    }
    
    body {
        background: #1c1c1c;
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
    }
    
    .wrapper {
        height: 100%;
        max-height: 960px;
        width: 100%;
        max-width: 960px;
        position: relative;
        margin: auto;
    }
    
    #attack_disc {
        background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/1.png');
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        width: 30vw;
        max-width: 1124px;
        height: 30vw;
        max-height: 1124px;
        margin: auto;
        position: absolute;
        top: 0; left: 0; bottom: 0; right: 0;
        transform-origin:50% 50%;
        border-radius:50%;
    }
    
    #course_disc {
        background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/2.png');
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        width: 23vw;
        max-width: 868px;
        height: 23vw;
        max-height: 868px;
        margin: auto;
      position: absolute;
      top: 0; left: 0; bottom: 0; right: 0;
      transform-origin:50% 50%;
       border-radius:50%;
    }
    
    #aob_disc {
        background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/3.png');
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        width: 15.5vw;
        max-width: 592px;
        height: 15.5vw;
        max-height: 592px;
        margin: auto;
      position: absolute;
      top: 0; left: 0; bottom: 0; right: 0;
       transform-origin:50% 50%;
       border-radius:50%;
    }
    
    #bearing_lead_disc {
        background-image: url('https://zuffdaddy.github.io/uboat-attack-disc/images/4.png');
    /*   background-color: red; */
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
        width: 23.5vw;
        max-width: 884px;
        height: 23.5vw;
        max-height: 884px;
        margin: auto;
      position: absolute;
      top: 0; left: 0; bottom: 0; right: 0;
      clip-path: url('#myPath');
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="wrapper">
        <div id="attack_disc"></div>
        <div id="course_disc"></div>
        <div id="aob_disc"></div>
        <div id="bearing_lead_disc" style="pointer-events:none;">
           <svg viewBox="0 0 512 512" style="width:100%; height:100%;">
                <path style="pointer-events:all;" fill="#ff00004d" d="M255.77 26.76c20 0 19.5 18.5 19.5 18.5 0 27 155.5 86.5 159 88s3.61 5.03 1.78 8.5c-8.07 15.27-45.11 77.9-124.18 99.85 0 0-3.05.81-3.32 2.67-.38 2.6-27.27 233.45-27.88 237.47-.27 1.76-.27 2.84-3.35 2.97-14.18.56-16.1.53-21.37.53s-7.19.03-21.37-.53c-3.08-.12-3.09-1.2-3.35-2.97-.61-4.03-27.5-234.88-27.88-237.47-.27-1.86-3.32-2.69-3.32-2.69-79.01-21.98-116.01-84.57-124.08-99.84-1.83-3.47-1.72-7 1.78-8.5s159-61 159-88c0 0-.5-18.5 19.5-18.5" />
        </svg>
        </div>
      
    </div>

    【讨论】:

    • 感谢您的快速回复!我认为我对顶部的塑料透明片不够清楚。它仍然需要像下面的环一样可旋转。这就是为什么我想从中剪掉背景,这样我就可以点击它,但仍然可以点击它。另外,“d”路径出了什么问题?我不确定这个网站如何修复路径。
    • 我已经快速编写了我当前的问题,即剪贴路径与图像不对齐codepen.io/zuffdaddy/pen/QWGewKr
    • Tnx!链接更新了关于查看您的代码笔并能够旋转路径。更新是在指针事件中完成的:所有路径并更改 svg 的视图框。您还可以使用视图框,使路径具有您想要的大小和您想要的位置。关于路径“d”,我只是将其居中,以便我们可以轻松地使用它:)
    • 看着你的链接,我仍然无法拖动“bearing_lead_disc”。也许我错过了什么?
    • 你看过codepen了吗?现在我也更新了片段
    猜你喜欢
    • 2016-05-25
    • 2021-05-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2021-02-14
    • 1970-01-01
    相关资源
    最近更新 更多