Select and change line color in html5 canvas?

I wrote this code to draw random graphs. I tried in vain to find how I can select a row on the graph so that I can apply the prim algorithm when you select the rows and see if they find the minimum tree.

function draw(n,rep){ var cvs=document.getElementsByTagName('canvas')[0]; /** * @type CanvasRenderingContext2D **/ var ctx=cvs.getContext('2d'); ctx.beginPath(); var randomX=[]; var randomY=[]; ctx.lineWidth=2; ctx.font = '3'+' Arial'; var weights=[]; var lastRandomx=Math.random()*200; var lastRandomy=Math.random()*200; for (var i = 0; i <n ; i++) { var cwidth = cvs.width; var cheight = cvs.height; randomX[i] = Math.random()*cwidth*2/3; randomY[i] = Math.random()*cheight*2/3; weights[i]=Math.round(Math.random()*20); ctx.fillRect(randomX[i],randomY[i],5,5); ctx.moveTo(lastRandomx,lastRandomy); ctx.lineTo(randomX[i],randomY[i]); lastRandomx=randomX[i]; lastRandomy=randomY[i]; } for (var i = 0; i < rep; i++) { var rand=Math.round(rep*Math.random()); ctx.lineTo(randomX[rand],randomY[rand]); } ctx.closePath(); ctx.stroke(); }; 

I found this on stackoverflow and it helps a little. How to select lines that are drawn on HTML5 canvas? . I was wondering if there is pre-written code so that I don't have to write it from scratch.

I thought if I could find the location of the mouse while moving it and each time check if the location of the mouse is in the line, as here Search if the point is on the line . Please help and suggest if there is any pre-written code, because I am limited in time. Thank you in advance.

+4
source share
2 answers

You need to scroll through the linear array for each line segment:

The basic principle is to add a line to the path, and then check if (x, y) is in that line:

 ctx.beginPath(); ctx.moveTo(x1, y1); // start of line ctx.lineTo(x2, y2); // end of line // this will test the point against the line (lineWidth matters) if (ctx.isPointInStroke(x, y)) { // draw line segment in f.ex. different color here ctx.strokeStyle = "red"; ctx.stroke(); // we already have a line segment on the path } 

There is no need to actually draw a line, just rearrange the path. Take if necessary.

Here is a complete example:

 var ctx = canvas.getContext("2d"), lines = [], // store line segments for demo count = 10, // max 10 lines for demo i = 0; for(; i < count; i++) { var x = Math.random() * canvas.width; // random point for end points var y = Math.random() * canvas.height; if (i) ctx.lineTo(x, y); // if not first line, add lineTo else ctx.moveTo(x, y); // start point lines.push({ // store point to create a poly-line x: x, y: y }); } ctx.lineWidth = 5; ctx.lineJoin = "round"; ctx.strokeStyle = "blue"; ctx.stroke(); // ..and draw line // here we use the principle canvas.onclick = function(e) { var r = canvas.getBoundingClientRect(), // adjust to proper mouse position x = e.clientX - r.left, y = e.clientY - r.top, i = 0 // for each line segment, build segment to path and check for(; i < count - 1; i++) { ctx.beginPath(); // new segment ctx.moveTo(lines[i].x, lines[i].y); // start is current point ctx.lineTo(lines[i+1].x, lines[i+1].y); // end point is next if (ctx.isPointInStroke(x, y)) { // x,y is on line? ctx.strokeStyle = "red"; // stroke red for demo ctx.stroke(); break; } } } 
 <canvas id=canvas width=500 height=500></canvas> 

To increase sensitivity, simply add a second (and third) line slightly offset from the first line. You can also use transformations: translate to the beginning (start point), find the angle, rotate, add a rectangle representing the sensitivity region, and check.

To perform the verification, internal compiled code is used (i.e. DirectX on Windows). This way you don't have to deal with math, etc. And get a quick result.

+6
source

You can use math to determine which line is closest to the mouse.

Here is a sample code and a demo version:

 // canvas related variables var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var cw=canvas.width; var ch=canvas.height; var $canvas=$("#canvas"); var canvasOffset=$canvas.offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top; ctx.lineWidth=2; // linear interpolation -- needed in setClosestLine() var lerp=function(a,b,x){ return(a+x*(ba)); }; // vars to track which line is closest to the mouse var closestLineIndex=-1; var closestX,closestY; // make some random lines and save them in lines[] var n=5; var lines=[]; var randomX=function(){return(Math.random()*cw*.67);} var randomY=function(){return(Math.random()*ch*.67);} var lastX=randomX(); var lastY=randomY(); for(var i=0;i<n;i++){ var x=Math.random()*cw*.67; var y=Math.random()*ch*.67; var dx=x-lastX; var dy=y-lastY; var line={ x0:lastX, y0:lastY, x1:x, y1:y, weight:Math.round(Math.random()*20), // precalc often used values dx:dx, dy:dy, dx2dy2:dx*dx+dy*dy, }; lines.push(line); lastX=x; lastY=y; } redraw(); $("#canvas").mousedown(function(e){handleMouseDown(e);}); $("#canvas").mousemove(function(e){handleMouseMove(e);}); ////////////////////////////// function setClosestLine(mx,my) { closestLineIndex=-1; var minDistanceSquared=100000000; // examine each line & // determine which line is closest to the mouse (mx,my) for(var i=0;i<lines.length;i++){ var line=lines[i]; var dx=line.x1-line.x0; var dy=line.y1-line.y0; var t=((mx-line.x0)*line.dx+(my-line.y0)*line.dy)/line.dx2dy2; var x=lerp(line.x0, line.x1, t); var y=lerp(line.y0, line.y1, t); var dx1=mx-x; var dy1=my-y; var distSquared=dx1*dx1+dy1*dy1; if(distSquared<minDistanceSquared){ minDistanceSquared=distSquared; closestLineIndex=i; closestX=x; closestY=y; } } }; function redraw(){ // clear the canvas ctx.clearRect(0,0,cw,ch); // draw all lines ctx.strokeStyle='black'; for(var i=0;i<lines.length;i++){ var line=lines[i]; ctx.beginPath(); ctx.moveTo(line.x0,line.y0); ctx.lineTo(line.x1,line.y1); ctx.stroke(); } // draw the line closest to the mouse in red if(closestLineIndex<0){return;} var line=lines[closestLineIndex]; ctx.strokeStyle='red'; ctx.beginPath(); ctx.moveTo(line.x0,line.y0); ctx.lineTo(line.x1,line.y1); ctx.stroke(); ctx.fillText("Index:"+closestLineIndex+", weight:"+line.weight,10,15); } function handleMouseMove(e){ e.preventDefault(); e.stopPropagation(); mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); setClosestLine(mouseX,mouseY); redraw(); } 
 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>Closest line is drawn in red<br>Closest line weight is reported top-left</h4> <canvas id="canvas" width=300 height=300></canvas> 
+3
source

Source: https://habr.com/ru/post/1381924/


All Articles