简体   繁体   English

检查点是否在复杂 Path2D 绘制的形状内

[英]Check if point is inside of shape drawn by a complex Path2D

I want to check if a given point is inside of the space drawn inside of a irregular path - inside of the brain (the path is below).我想检查给定点是否在不规则路径内部绘制的空间内 - 大脑内部(路径在下方)。

I don't seem to be able to use CanvasRenderingContext2D.isPointInPath(path, x, y) because it only returns true if the point is literally inside the path (the white outline).我似乎无法使用CanvasRenderingContext2D.isPointInPath(path, x, y)因为它仅在该点实际上位于路径内(白色轮廓)时才返回 true。

I also don't think I can use the odd polygon rule, given that it is possible for a point not to be in the edge and its line still hit the shape wall an even number of times...我也不认为我可以使用奇数多边形规则,因为一个点可能不在边缘并且它的线仍然会偶数次撞击形状墙......

形状

As you're working with a SVG, here's a workaround which doesn't involve any abstract calculations.当您使用 SVG 时,这里有一个不涉及任何抽象计算的解决方法。

(1) (1)

Make the inside of your shape, thus the area you want to detect a color completely different from the rest of the shape or any other visuals.使您的形状内部,即您想要检测颜色的区域与形状的 rest 或任何其他视觉效果完全不同。 In your case for example it would be nothing (or black) to red.例如,在您的情况下,红色将是什么(或黑色)。

This is controlled by the svg's fill attribute, which takes a hex #ff0000 or a rgb value rgb(255,0,0) .这由 svg 的fill属性控制,该属性采用十六进制#ff0000或 rgb 值rgb(255,0,0) Well for reasons that will be important later we make it a rgba(255,0,0,1) value though it ignores the alpha value.好吧,出于稍后重要的原因,我们将其rgba(255,0,0,1)值,尽管它忽略了 alpha 值。

As we don't want the fill to be visible, we also need to set the fill-opacity value to 0.005 .由于我们不希望填充可见,我们还需要将fill-opacity值设置为0.005 This is the lowest value possible and equals the CanvasRenderingContext2D value of 1 in a range from 0-255.这是可能的最低值,等于 CanvasRenderingContext2D 值 1,范围为 0-255。

(2) (2)

Now we need to turn the svg into an Image object that can be drawn onto a canvas.现在我们需要将 svg 转换为可以绘制到 canvas 上的图像 object。 This can be done using the following lines:这可以使用以下行来完成:

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let img = new Image();
img.onload = function(e) {
    ctx.drawImage(e.currentTarget, canvas.width / 2 - 50, canvas.height / 2 - 50, 100, 100);
}
img.src = 'data:image/svg+xml;charset=utf8,' + encodeURIComponent(svg);

svg is just a string representation of your svg's data. svg只是 svg 数据的字符串表示形式。

(3) (3)

The final step involves getting the pixel color at a specific position on the canvas.最后一步是获取 canvas 上特定 position 的像素颜色。 For this we utilize the .getImageData(x, y, width, height) method, which returns an object consisting of a Uint8ClampedArray which holds four values per pixel.为此,我们使用.getImageData(x, y, width, height)方法,该方法返回一个 object,其中包含一个Uint8ClampedArray ,每个像素保存四个值。 If we set both width and height to 1 we get exactly the four color components for a single pixel - red , green , blue and alpha .如果我们将widthheight都设置为 1,我们将准确地获得单个像素的四种颜色分量—— redgreenbluealpha

Now we simply compare the color with the red we've used in step (1) and if it's equal, we know it's inside the shape.现在我们只需将颜色与我们在步骤(1)中使用的红色进行比较,如果相等,我们就知道它在形状内部。

Here's a working example (hover your mouse over the image):这是一个工作示例(将鼠标悬停在图像上):

 let hitColor = 'rgba(255,0,0,1)'; let svg = `<?xml version="1.0" encoding="iso-8859-1"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 511.989 511.989" style="enable-background:new 0 0 511.989 511.989;" xml:space="preserve"> <path style="fill:${hitColor};fill-opacity:0.005" d="M489.333,255.088l-21.344-17.625l8-34.671l4-18.812l-30.656-42.141l6.656-22.53l-8-38.483 l-30.655-30.077h-39.999c0,0-22.655,12.312-16,0c6.672-12.328-33.326-36.577-33.326-36.577h-17.328l-40.663,15.483l-9.602,7.828 l-31.062-23.702h-30.672l-23.999,0.391l-20.929,23.312L150.41,50.75h-22.383l-23.998,10.654L66.694,73.295l-6.664,29.358 l-5.336,42.577l-19.999,22.891v26.516l12.397,37.623l-12.397,16.547l-18.664,22.672v41.326l18.664,29.984v36.67l23.999,55.999 c0,0,35.999,18.672,41.335,21.327c5.328,2.672,14.664,0,14.664,0l29.327,32l27.999,9.328h21.336l42.663-18.656l24.397-18.672 l10.664,24l42.257,13.328h21.344l31.998-6.656l21.719-38.671l11.609,3.999l38.67-7.999l28-28.327l10.656-46.327v-31.343 l17.718-20.156l10.281-35.171L489.333,255.088z"/> <path style="fill:#ffffff;" d="M511.973,294.009c0-24.546-12.891-46.093-32.28-58.218c7.984-11.203,12.672-24.905,12.672-39.701 c0-22.203-10.562-41.938-26.938-54.453c2.625-7.655,4.078-15.858,4.078-24.42c0-41.281-33.484-74.749-74.764-74.749 c-8.344,0-16.375,1.375-23.875,3.906C363.21,19.594,338.554,0,309.321,0c-22.266,0-41.858,11.359-53.327,28.608 C244.525,11.359,224.925,0,202.667,0c-29.233,0-53.889,19.594-61.537,46.374c-7.5-2.531-15.531-3.906-23.89-3.906 c-41.288,0-74.757,33.468-74.757,74.749c0,8.562,1.445,16.765,4.086,24.42c-16.382,12.516-26.952,32.25-26.952,54.453 c0,14.796,4.695,28.498,12.672,39.701c-19.383,12.125-32.273,33.672-32.273,58.218c0,21.327,9.727,40.374,24.984,52.952 c-2.375,8.375-3.656,17.202-3.656,26.343c0,52.53,42.194,95.185,94.537,95.966c13.405,25.406,40.069,42.719,70.787,42.719 c29.632,0,55.506-16.125,69.326-40.062c13.82,23.938,39.687,40.062,69.327,40.062c30.718,0,57.389-17.312,70.795-42.719 c52.342-0.781,94.529-43.436,94.529-95.966c0-9.141-1.281-17.968-3.656-26.343C502.238,334.383,511.973,315.336,511.973,294.009z M186.668,490.644c-32.351,0-58.663-26.312-58.663-58.654c0-16.406,7.195-31.688,18.078-42.344c2.008-1.938,3.25-4.641,3.25-7.656 c0-5.891-4.773-10.655-10.664-10.655c-2.906,0-5.547,1.156-7.469,3.047c-15.569,14.593-24.53,34.577-24.53,57.608 c0,5.265,0.516,10.421,1.492,15.405c-16.469-2-31.702-9.391-43.616-21.312c-14.102-14.094-21.867-32.844-21.867-52.78 c0-19.952,7.766-38.702,21.867-52.796c14.102-14.109,32.851-21.875,52.796-21.875c6.351,0,12.585,0.781,18.585,2.312 c0.883,0.234,1.797,0.375,2.742,0.375c5.891,0,10.664-4.78,10.664-10.671c0-5.203-3.727-9.531-8.656-10.469 c-7.477-1.875-15.289-2.875-23.335-2.875c-35.805,0-67.03,19.608-83.529,48.655c-7.734-8.422-12.469-19.641-12.469-31.952 c0-16.406,8.32-31.405,22.265-40.14l9.789-6.125c2.898-1.906,4.812-5.188,4.812-8.922c0-2.266-0.719-4.391-1.938-6.109l-6.609-9.297 c-5.695-7.999-8.711-17.452-8.711-27.326c0-13.922,6.07-26.453,15.695-35.094c13.578,18.766,35.655,30.984,60.593,30.984 c5.89,0,10.765-4.781,10.765-10.672s-4.844-10.656-10.733-10.656c-29.453,0-53.452-23.969-53.452-53.436 c0-29.453,23.968-53.422,53.421-53.422c7.679,0,14.976,1.641,21.585,4.562c2.242,33.312,29.968,59.624,63.842,59.624 c5.891,0,10.664-4.766,10.664-10.671c0-5.891-4.773-10.657-10.664-10.657c-23.522,0-42.663-19.14-42.663-42.671 c0-23.515,19.133-42.655,42.663-42.655c23.523,0,42.663,19.141,42.663,42.655v106.67h-0.016 c-0.156,5.734-4.867,10.359-10.655,10.359c-5.891,0-10.664,4.781-10.664,10.672s4.773,10.671,10.664,10.671 c3.741,0,7.335-0.656,10.671-1.828v87.451c0,17.64-14.358,31.983-31.999,31.983c-5.891,0-10.664,4.781-10.664,10.672 s4.773,10.672,10.664,10.672c12.008,0,23.086-3.969,31.999-10.672v101.357C245.33,464.332,219.011,490.644,186.668,490.644z M478.177,325.961c-16.5-29.047-47.718-48.655-83.529-48.655c-8.047,0-15.859,1-23.344,2.875c-4.922,0.938-8.656,5.266-8.656,10.469 c0,5.891,4.781,10.671,10.672,10.671c0.953,0,1.859-0.141,2.734-0.375c6-1.531,12.25-2.312,18.594-2.312 c19.938,0,38.687,7.766,52.795,21.875c14.109,14.094,21.859,32.844,21.859,52.796c0,19.937-7.75,38.687-21.859,52.78 c-11.922,11.921-27.14,19.312-43.607,21.312c0.969-4.984,1.484-10.141,1.484-15.405c0-23.031-8.953-43.016-24.531-57.608 c-1.922-1.891-4.562-3.047-7.469-3.047c-5.891,0-10.672,4.765-10.672,10.655c0,3.016,1.25,5.719,3.25,7.656 c10.891,10.656,18.094,25.938,18.094,42.344c0,32.342-26.312,58.654-58.67,58.654c-32.344,0-58.663-26.312-58.663-58.654V330.633 c8.914,6.703,19.991,10.672,31.991,10.672c5.906,0,10.672-4.781,10.672-10.672s-4.766-10.672-10.672-10.672 c-17.625,0-31.991-14.344-31.991-31.983v-87.451c3.336,1.172,6.93,1.828,10.663,1.828c5.891,0,10.672-4.78,10.672-10.671 c0-5.891-4.781-10.672-10.672-10.672c-5.78,0-10.491-4.625-10.647-10.359h-0.016V63.982c0-23.515,19.147-42.655,42.663-42.655 s42.671,19.141,42.671,42.655c0,23.531-19.155,42.671-42.671,42.671c-5.891,0-10.672,4.767-10.672,10.657 c0,5.905,4.781,10.671,10.672,10.671c33.874,0,61.607-26.312,63.842-59.624c6.609-2.922,13.906-4.562,21.578-4.562 c29.468,0,53.436,23.969,53.436,53.422c0,29.467-23.999,53.436-53.467,53.436c-5.891,0-10.719,4.766-10.719,10.656 c0,5.89,4.875,10.672,10.75,10.672c24.937,0,47.029-12.219,60.592-30.984c9.625,8.641,15.703,21.172,15.703,35.094 c0,9.874-3.016,19.327-8.719,27.326l-6.609,9.297c-1.219,1.719-1.938,3.844-1.938,6.109c0,3.734,1.922,7.016,4.812,8.922 l9.797,6.125c13.938,8.734,22.266,23.733,22.266,40.14C490.645,306.32,485.911,317.539,478.177,325.961z"/> </svg> `; let canvas = document.getElementById('canvas'); let ctx = canvas.getContext('2d'); let rect = canvas.getBoundingClientRect(); let img = new Image(); img.onload = function(e) { ctx.drawImage(e.target, canvas.width / 2 - 50, canvas.height / 2 - 50, 100, 100); canvas.addEventListener('mousemove', (e) => { let data = ctx.getImageData(e.clientX - rect.left, e.clientY - rect.top, 1, 1).data; let hit = hitColor == `rgba(${data[0]},${data[1]},${data[2]},${data[3]})`; document.getElementById('message').innerText = `inside path: ${hit}`; }); } img.src = 'data:image/svg+xml;charset=utf8,' + encodeURIComponent(svg);
 <canvas id="canvas" style="background:black;"></canvas><br> <span id="message">inside path:</span>

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

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