View Full Version : about drawview ----- only a line
a_bing220
10-19-2006, 12:51 AM
code can say more ,i believe
---------------code-------------------------
<canvas debug="true">
<drawview width="100" height="100" bgcolor="yellow">
<attribute name="linecolor" value="red"/>
<method event="oninit" >
this.redraw();
</method>
<method name="redraw" >
this.clear();
this.beginPath();
this.moveTo(0, 0);
this.lineTo(width,height);
this.lineWidth = 10;
this.strokeStyle = this.linecolor;
this.stroke();
</method>
<method event="onclick">
if(red==linecolor) this.setAttribute("linecolor",blue);
else this.setAttribute("linecolor",red);
this.redraw();
</method>
</drawview>
</canvas>
---------------code-------------------------
<<purpose>>
--every time when i click the line ,it changes its color
i should say it seems to be right, you know why?
as every time when i click the yellow area , it also change the line color ,this is not what I want;
can someone help me , I know you can ,look forwarding ....
jks_pdx
10-19-2006, 07:33 AM
The reason you line changes color each time you click on the view is that your on click handler is for the whole view, not just the drawn area.
Your possible fixes for this are:
1) Make the draw view just the size of the line, and have another view behind it to show the background color.
2) In the onclick handler use the getMouse function to determine the mouse location, and do your own test to see if that mouse location is in the drawn area
3) create a static swf file that defines a shape that outlines the drawn area, and set this as the 'clickregion' of your view.
There may be other ways to fix this as well. Personally I suggest option 1, since that is the way OpenLaszlo is meant to work.
a_bing220
10-19-2006, 05:43 PM
Thanks for your answering my question,after my consideration ,I think:
---option 1, I also think it reasonable
but How can you make the drawview just the size of the line, it seems impossible,since in lzx the <view> and <drawview> is always square,right?
---------------------------------------------------
---option 2 is also the "drawn area" question
could you do me a favor ,and show me the code solution ...
jks_pdx
10-23-2006, 07:59 AM
I was thinking about vertical and horizontal lines when I suggested changing the view size. As long as you have irregular shapes you want to catch the click on, you're limited to defining a clickrgn or doing the trig to figure out if the point is inside or outside.
Here's your sample updated to respond to clicks the way you want.
<canvas debug="true">
<drawview width="100" height="100" bgcolor="yellow">
<attribute name="linecolor" value="red"/>
<method event="oninit" >
this.redraw();
</method>
<method name="redraw" >
this.clear();
this.beginPath();
this.moveTo(0, 0);
this.lineTo(width,height);
this.lineWidth = 10;
this.strokeStyle = this.linecolor;
this.stroke();
</method>
<method event="onclick">
<![CDATA[
var x = this.getMouse('x');
var y = this.getMouse('y');
// using some trig we find that
// the max diff that will be in a 10 pixel wide line
// is Math.sqrt(50) which is aproximately 7
if (Math.abs(x-y) <= 7)
{
if(red==linecolor) this.setAttribute("linecolor",blue);
else this.setAttribute("linecolor",red);
this.redraw();
}
]]>
</method>
</drawview>
</canvas>
a_bing220
10-24-2006, 07:05 PM
you really help me in that case. thank you !
But in my App, the line is created dynamicly between two nodes whose position is also random ,so I can't use *.swf file and the Attribute-clickregion.
Your suggestion is not generic enough, as the line sometimes vertical ,sometimes horizontal sometimes sloping.
if I change my code like below, you solution doesn't work.
code:
_________________________________________________
<method name="redraw" >
.....
this.lineTo(width,height/2);
.....
</method>
_________________________________________________
I'm really lost...
jks_pdx
10-24-2006, 08:53 PM
You are quite correct that my solution was specific to a 45 degree line.
The math gets a little more complicated, but it is quite possible to calculate for an abitray straight line and an arbitrary point if the point is on the line.
GraphicsGems is a great source for sample code to solve these kinds of problems, and here is exactly this function you need:
http://www.acm.org/pubs/tog/GraphicsGems/gems/PntOnLine.c
Adapting from c to JavaScript, we get the following code sample:
<canvas debug="true">
<drawview width="100" height="100" bgcolor="yellow">
<attribute name="linecolor" value="red"/>
<method event="oninit" >
this.redraw();
</method>
<method name="redraw" >
this.clear();
this.beginPath();
this.moveTo(0, 0);
this.lineTo(width,height);
this.lineWidth = 1;
this.strokeStyle = this.linecolor;
this.stroke();
</method>
<method event="onclick">
<![CDATA[
var x = this.getMouse('x');
var y = this.getMouse('y');
if (canvas.pointOnLine(0,0,this.width,this.height,x,y ))
{
if(red==linecolor) this.setAttribute("linecolor",blue);
else this.setAttribute("linecolor",red);
this.redraw();
}
]]>
</method>
</drawview>
<method name='pointOnLine' args='startX,startY,endX,endY,pointX,pointY'>
<![CDATA[
if ((startX == endX) && (startY == endY))
{
if ((pointX == startX) && (pointY == startY))
return true;
else
return false;
}
if ( Math.abs((endY-startY)*(pointX-startX)-(pointY-startY)*(endX-startX)) >=
(Math.max(Math.abs(endX-startX), Math.abs(endY-startY))))
return false;
if (((endX<startX)&&(startX<pointX)) || ((endY<startY)&&(startY<pointY)))
return false;
if (((pointX<startX)&&(startX<endX)) || ((pointY<startY)&&(startY<endY)))
return false;
if (((startX<endX)&&(endX<pointX)) || ((startY<endY)&&(endY<pointY)))
return false;
if (((pointX<endX)&&(endX<startX)) || ((pointY<endY)&&(endY<startY)))
return false;
return true;
]]>
</method>
</canvas>
Although, having done this, I now realize that pointOnLine does not account for thickness, requiring you to click very precisely on the line.
Adding the line thickness to the calculation is a little tricky, but it certainly can be done. But that's not really an OpenLaszlo question, more of a general mathematical question.
vBulletin® v3.8.4, Copyright ©2000-2012, Jelsoft Enterprises Ltd.