I have need for a simple rotating knob.
This will be a picture of knob photo and a small dot rotating over the picture so the user gets the impression the knob is rotating.
Putting the small dot at a certain angle isn’t difficult: Adding this in a Canvas works fine.
dim x,y as double
dim r as double = 20
dim circleCenterX as integer = 100
dim circleCenterY as integer = 100
x = circleCenterX + (r*cos(angle))
y = circleCenterY + (r*sin(angle))
g.DrawString "x",circleCenterX,circleCenterY
g.DrawString "O", x, y
Now the difficulty part.
The user should be able to drag the knob dot by dragging over the canvas aka rotating knob.
And know comes the question:
What code should I put in the MouseDrag event?
I tried a lot but fail doing so. The Angle value should be from 0 to 360
So when X raises, Angle should raise to max. 360, when X lowers, Angle should raise to max. 0
[code]Function MouseDown(X As Integer, Y As Integer) As Boolean
dim angle As double = ATan2(Y-50, X-50)
diffAngle = angle - pix.Rotation
return true
End Function
Sub MouseDrag(X As Integer, Y As Integer)
dim angle As double = ATan2(Y-50, X-50)
pix.Rotation = angle - diffAngle
me.Invalidate
End Sub
Sub Paint(g As Graphics, areas() As REALbasic.Rect)
if pix = nil then
dim pic As new Picture(100, 100)
pic.Graphics.FillRoundRect(40, 0, 20, 100, 20, 20)
pix = new PixmapShape(pic)
pix.X = 50
pix.Y = 50
end
Although Wills code work fine it very difficult to attach a value to it. The angle value has erratic values depending where you click to start rotating.
So linking this with a value that has a range of 0 to 360 is not possible (I think).
Yes, of course. pix.Rotation*180/PI converts it to degrees. But thats not the issue.
The problem is that you cannot get a fixed value - it jumps erratically and it depends where you click to start rotating the knob.
So making sure 1 turn is 0 to 360 is not possible - I tried about anything.
Will make a small example and post a download link so maybe someone can find a solution for this.
Yes, already tried that.
I still trying to get this to work, unfortunately I don’t think it is possible with the current code.
Any help is appreciated.
I thought pixmapshape would roll it’s rotation value inside the range 0-2pi, but obviously it’s not. So you can do that like this
[code]Sub MouseDrag(X As Integer, Y As Integer)
angle = ATan2(Y-64, X-64) // <- subtract the center of rotation
pix.Rotation = angle - diffAngle
const tau = 6.28318530717959 //2*pi
dim units As integer = Floor(pix.Rotation / tau)
if units <> 0 then pix.Rotation = pix.Rotation - units * tau
Label1.Text = str(pix.Rotation*180/3.1415)
me.Invalidate
End Sub[/code]
units is the block of 2pi the value is in. If it’s not 0 (range 0-2pi) then the value is shifted by the number of units out of range it is.
This ‘fixes’ the Rotation value of pix but mathematically there’s no difference; you could let it go wherever and only fix the value for display. Well, I guess it depends what you’re doing. If you want to restrict the knob to only 1 turn then extra code is needed.
Like Peter said you want to subtract the point of rotation in atan2.
Also note that this is y-down orientation where angle increases clockwise. Standard math is y-up where angle increases counter-clockwise.