- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在绘制一个复杂的形状,由 6 条细线和两条粗线组成。
在代码中,我打开 8 个路径来执行此操作:
context.save();
context.lineWidth=2;
var TAB_ABSTAND=10;
var TAB_SAITENZAHL=6;
var TAB_SEITENDICKE=10;
for(var i=0;i<TAB_SAITENZAHL;i++)
{
context.beginPath();
context.moveTo(this.clickedX, this.clickedY+(i*TAB_ABSTAND));
context.lineTo(this.clickedX+this.width, this.clickedY+(i*TAB_ABSTAND));
context.stroke();
}
context.lineWidth=TAB_SEITENDICKE;
context.beginPath();
context.moveTo(this.clickedX, this.clickedY-1);
context.lineTo(this.clickedX, this.clickedY+TAB_ABSTAND*(TAB_SAITENZAHL-1)+1);
context.stroke();
context.beginPath();
context.moveTo(this.clickedX+this.width, this.clickedY-1);
context.lineTo(this.clickedX+this.width, this.clickedY+TAB_ABSTAND*(TAB_SAITENZAHL-1)+1);
context.stroke();
context.restore();
在 Canvas onmousedown 事件中,我想识别是否已单击该形状(或数组中的其他形状之一)来实现拖动。
有没有办法使用 isPointInPath(x,y) 方法来识别“形状”中的其中一条线是否已被单击?
我想要做的是实现一种维护可拖动对象列表的机制。
我发现了什么:
1.) beginPath 是唯一一个以某种方式中断路径的上下文方法,即 isPointInPath 方法无法识别先前的路径
2.) 在具有大笔划的单行上(即 context.lineWidth=10),当 isPointInPath 方法只是没有曲线的单行时,isPointInPath 方法不会返回 true
3.) closePath 将最后一条线的端点绘制到第一条线的起点,但它不会中断路径,因此后面的Stroke() 始终对之前的lineTo 和moveTo 方法生效关闭路径
4.) 如果不调用 beginPath() 而不抚摸其余路径,似乎不可能画出更大的线
5.) moveTo(x,y) 确实跳转到另一个位置,但另一个位置可以是 isPointInPath 方法返回 true 的路径,当它不仅由一行组成时(请参见 1.))。
6.) 为了可视化路径,fill() 方法很有用
那么,当我想识别“线”(绘制为矩形)是否在路径中时,我应该始终使用矩形来绘制线吗?
最佳答案
如何对由多个路径组成的形状进行 HitTest
此形状由 2 条路径组成:路径 1= 4 条红色细线,路径 2= 2 条蓝色粗线。
首先,以下是有关路径的信息,可解释您的观察结果发生的原因
beginPath
is the only context method that interrupts the path in a way, that the previous path is not recognized by the isPointInPath method
您可以定义多个路径,但是 isPointInPath
只会测试最后定义的路径。
路径由一组路径命令组成,如下所示:
beginPath
开头命令moveTo
定义其形状, lineTo
等命令。beginPath
结尾命令。因此,在您的问题代码中,只会测试最后一个 moveTo+lineTo 。
context.beginPath();
context.moveTo(this.clickedX+this.width, this.clickedY-1);
context.lineTo(this.clickedX+this.width, this.clickedY+TAB_ABSTAND*(TAB_SAITENZAHL-1)+1);
On a single line with big stroke (i.e. context.lineWidth=10) the isPointInPath method is not returning true when it is just a single line without curves.
从数学上讲,一行不占据空间。因此,您无法测试任何点是否“在”单行中。
在大多数浏览器(尤其是 IE/Edge 除外)中,您可以使用新的 isPointInStroke
方法来测试一个点是否在一条直线内。为了跨浏览器兼容性,您必须将单行“加厚”到路径中,以便您可以对该加厚路径内的点进行 HitTest 。
closePath
draws the endpoint of the last line to the beginning point of the first line, but it is not interupting the path, so that a later stroke() always takes effect on the lineTo and moveTo-methods before the closePath
恕我直言,closePath
名字不好。它不会关闭(不完成)路径。它不是 beginPath 的“左大括号”的“右大括号”。相反,它只是直接从路径中的当前点画一条线回到路径中的第一个点。
It seems to be impossible to draw a bigger line without calling beginPath() without stroking the rest of the pathes
您只能将一种样式应用于一条路径。因此,如果您在一组路径命令中定义多个 lineWidth,则最后一个 lineWidth 获胜,并且整个路径将使用最后一个 linewidth 进行描边。
moveTo(x,y)
really jumps to another position, but the other position can be a path that returns true for the isPointInPath method, when it not only consists of one line (see 1.)).
moveTo
相当于“拿起笔”并将其移动到纸上的新位置而不结束当前的路径命令集。
例如:假设您以 beginPath
开始路径然后使用 moveTo
绘制 3 个独立的三 Angular 形将他们分开。然后所有 3 个三 Angular 形都将包含在路径中,并且所有 3 个三 Angular 形都将使用 isPointInPath
进行测试。 .
To visualize pathes the fill() method is useful
.fill
和.stroke
将命令上下文将当前路径直观地绘制到 Canvas 上。他们没有完成路径——只有下一个beginPath
将完成当前路径。因此,如果您定义了三 Angular 形的 2 条边、笔画(),再次定义三 Angular 形的第 3 条边和笔划(),则前 2 条边将被描边两次,第三边将被描边一次。
重要信息:您可以定义路径并使用 isPointInPath
对其进行测试。无需实际抚摸(或填充)测试路径。这意味着您可以单独重新定义 + isPointInPath
你的每条路径都无需在 Canvas 上重新绘制。您还可以定义由多个路径组成的单个形状,并使用 isPointInPath 对该多路径形状进行 HitTest 。
因此,要测试 mousedown 事件中的哪些形状(形状==路径),您可以重新定义每个多路径并使用 context.isPointInPath(mouseX,mouseY)
进行测试。 .
要实际绘制形状,您需要多种样式(细线与粗线),因此您必须单独绘制路径,因为每个路径只能获得 1 个样式。
这里是示例代码和演示:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
var isDown=false;
var startX,startY;
var shapes=[];
//
var path1=[
{x:150,y:100},
{x:50,y:100},
{x:25,y:75},
{x:50,y:50},
{x:150,y:50}
];
path1.linewidth=1;
path1.strokestyle='red';
//
var path2=[
{x:150,y:50},
{x:225,y:75},
{x:150,y:100}
];
path2.linewidth=5;
path2.strokestyle='blue';
var shape1=[path1,path2];
shape1.fill='green';
//
shapes.push(shape1);
// draw both parts of the path onto the canvas
draw(path1);
draw(path2);
$("#canvas").mousedown(function(e){handleMouseDown(e);});
function define(shape){
ctx.beginPath();
for(j=0;j<shape.length;j++){
var p=shape[j];
ctx.moveTo(p[0].x,p[0].y);
for(var i=1;i<p.length;i++){
ctx.lineTo(p[i].x,p[i].y);
}
}
}
//
function draw(path){
ctx.beginPath();
ctx.moveTo(path[0].x,path[0].y);
for(var i=1;i<path.length;i++){
ctx.lineTo(path[i].x,path[i].y);
}
ctx.lineWidth=path.linewidth;
ctx.strokeStyle=path.strokestyle;
ctx.stroke();
}
//
function dot(x,y,fill){
ctx.beginPath();
ctx.arc(x,y,2,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=fill;
ctx.fill();
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get mouseX,mouseY
var mx=parseInt(e.clientX-offsetX);
var my=parseInt(e.clientY-offsetY);
//
var dotcolor='red';
for(var i=0;i<shapes.length;i++){
define(shapes[i]);
if(ctx.isPointInPath(mx,my)){dotcolor=shapes[i].fill;}
}
dot(mx,my,dotcolor);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Click inside and outside the multi-path shape<br>Inside clicks become green dots.</h4>
<canvas id="canvas" width=300 height=300></canvas>
关于javascript - HTML5 Canvas : Use context. isPointInPath(x, y) 用于具有更多路径的复杂形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34924326/
问题故障解决记录 -- Java RMI Connection refused to host: x.x.x.x .... 在学习JavaRMI时,我遇到了以下情况 问题原因:可
我正在玩 Rank-N-type 并尝试输入 x x .但我发现这两个函数可以以相同的方式输入,这很不直观。 f :: (forall a b. a -> b) -> c f x = x x g ::
这个问题已经有答案了: How do you compare two version Strings in Java? (31 个回答) 已关闭 8 年前。 有谁知道如何在Java中比较两个版本字符串
这个问题已经有答案了: How do the post increment (i++) and pre increment (++i) operators work in Java? (14 个回答)
下面是带有 -n 和 -r 选项的 netstat 命令的输出,其中目标字段显示压缩地址 (127.1/16)。我想知道 netstat 命令是否有任何方法或选项可以显示整个目标 IP (127.1.
我知道要证明 : (¬ ∀ x, p x) → (∃ x, ¬ p x) 证明是: theorem : (¬ ∀ x, p x) → (∃ x, ¬ p x) := begin intro n
x * x 如何通过将其存储在“auto 变量”中来更改?我认为它应该仍然是相同的,并且我的测试表明类型、大小和值显然都是相同的。 但即使 x * x == (xx = x * x) 也是错误的。什么
假设,我们这样表达: someIQueryable.Where(x => x.SomeBoolProperty) someIQueryable.Where(x => !x.SomeBoolProper
我有一个字符串 1234X5678 我使用这个正则表达式来匹配模式 .X|..X|X. 我得到了 34X 问题是为什么我没有得到 4X 或 X5? 为什么正则表达式选择执行第二种模式? 最佳答案 这里
我的一个 friend 在面试时遇到了这个问题 找到使该函数返回真值的 x 值 function f(x) { return (x++ !== x) && (x++ === x); } 面试官
这个问题在这里已经有了答案: 10年前关闭。 Possible Duplicate: Isn't it easier to work with foo when it is represented b
我是 android 的新手,我一直在练习开发一个针对 2.2 版本的应用程序,我需要帮助了解如何将我的应用程序扩展到其他版本,即 1.x、2.3.x、3 .x 和 4.x.x,以及一些针对屏幕分辨率
为什么案例 1 给我们 :error: TypeError: x is undefined on line... //case 1 var x; x.push(x); console.log(x);
代码优先: # CASE 01 def test1(x): x += x print x l = [100] test1(l) print l CASE01 输出: [100, 100
我正在努力温习我的大计算。如果我有将所有项目移至 'i' 2 个空格右侧的函数,我有一个如下所示的公式: (n -1) + (n - 2) + (n - 3) ... (n - n) 第一次迭代我必须
给定 IP 字符串(如 x.x.x.x/x),我如何或将如何计算 IP 的范围最常见的情况可能是 198.162.1.1/24但可以是任何东西,因为法律允许的任何东西。 我要带198.162.1.1/
在我作为初学者努力编写干净的 Javascript 代码时,我最近阅读了 this article当我偶然发现这一段时,关于 JavaScript 中的命名空间: The code at the ve
我正在编写一个脚本,我希望避免污染 DOM 的其余部分,它将是一个用于收集一些基本访问者分析数据的第 3 方脚本。 我通常使用以下内容创建一个伪“命名空间”: var x = x || {}; 我正在
我尝试运行我的test_container_services.py套件,但遇到了以下问题: docker.errors.APIError:500服务器错误:内部服务器错误(“ b'{” message
是否存在这两个 if 语句会产生不同结果的情况? if(x as X != null) { // Do something } if(x is X) { // Do something } 编
我是一名优秀的程序员,十分优秀!