Curved motion scroller
January 3, 1999
by Pat McClellan
Dear Multimedia Handyman,
I am trying to create a text scroller that has a curved path. All the examples I have seen use a staight scroller... I dont know if this is possible but it would be very nice to have.
Christian
Dear Christian,
I love a nice challenge like this! We'll be combining two distinct concepts here. The first is to create basic scroll functionality. The second task is to create a sprite that can be dragged only along the arc of a circle. This is the example graphic you sent:
Imagine the little red scroller ball moving up and down along the curved side of the text window. Now, picture a large circle superimposed over that motion. I've illustrated it with a blue line below.
Once we've pictured the circle, then it's easy to see the radius of that circle. I've drawn it at a purple line. Now, as you move the red scroller ball, it always represents one end of that radius, so we always know exactly how far it is from the origin (center of the circle.)
Now, picture a right triangle in which the radius line is the hypotenuse. We know that the locV of the scroller ball sprite will stay the same as the mouseV (the vertical location of the mouse). If we know the locV of the origin, then the vertical side of our triangle will simply be the origin minus the mouseV.
That means that we now know the lengths of 2 sides of a right triangle. What we really need to know is that third side length, because that will give us the locH of the scroller ball sprite. Luckily, Pythagoras -- a geometry pioneer and Lingo devotee -- came up with a simple formula, as follows:
a2 + b2 = c2
This formula tells us that the length of the hypotenuse is the square root of the sum of the square of each side. In our case, we know the hypotenuse length (same as the radius), so we'll swap the formula around.
a2 = c2 - b2
Using this formula and the diagram above, think of a as the green line, b as the gold line, and c as the purple line.
Now that you have the concept under your belt, let's look at a demo and make some behaviors. Typically, in describing the components of a scroller, the part you drag up and down is called the "thumb". So, that's what we'll start calling the red scroller ball in our example.
We'll need to have certain bits of data input when the behavior is dropped on the thumb. Thinking back to our geometry diagram, those include:
- the locH and locV of our imaginary origin point
- the radius of our imaginary circle
- the locV representing the top limit of the thumb's range of motion
- the locV representing the bottom limit of the thumb's range of motion
- the name of the text or field cast member
- the sprite number of the field or text sprite
The code for generating this dialog box is the getPropertyDescriptionList handler below.
-- scrollThumb behavior (curved) -- copyright © 1999, ZZP Online, LLC property pOriginH, pOriginV, pRadius, pMySprite, ¬ pTop, pBottom, pFieldMem, pFieldSpriteNum,¬ pScrollFactor, pThumbMargin on getPropertyDescriptionList me set pdlist to [:] addprop pdlist, #pOriginH, [#comment:"Origin ¬ locH", #format:#integer, #default:0] addprop pdlist, #pOriginV, [#comment:"Origin ¬ locV", #format:#integer, #default:0] addprop pdlist, #pRadius, [#comment:"Radius ¬ (pixels)",#format:#integer, #default:0] addprop pdlist, #pTop, [#comment:"Top limit ¬ locV", #format:#integer, #default:0] addprop pdlist, #pBottom, [#comment:"Bottom ¬ limit locV", #format:#integer, #default:0] addprop pdlist, #pFieldMem, [#comment:"Field ¬ Member Name", #format:#string, #default:""] addprop pdlist, #pFieldSpriteNum, [#comment:¬ "Field spriteNum", #format:#integer, #default:10] return pdlist end getPropertyDescriptionList
Based on that information, the behavior can quickly calculate some of the other data we'll need to use. Specifically, we'll need to calculate the height of the text or field member and the height of the text displayed on stage. This will tell us the scroll range for the text. Then, we need to compare that scroll range to the range of motion for the thumb (bottom limit - top limit). By dividing the scroll range by the thumb's range, we'll get a "scrollFactor". For example, if the scrollFactor is 3, then that means that the text will need to scroll 3 pixels for every pixel of thumb motion. Here's the handler that does that calculation.
on beginSprite me set pMySprite = the spriteNum of me set displayHeight = the height of sprite ¬ pFieldSpriteNum set scrollRange = the height of member pFieldMem ¬ - displayHeight set thumbRange = (pBottom - pTop) * 1.00 set pScrollFactor = scrollRange/thumbRange set pThumbMargin = (the height of sprite pMySprite)/2 set the scrollTop of member pFieldMem to 1 end
When the user mouses down on the thumb, and for the duration of the mouse being held down, we need to repeatedly set the locV of the sprite to the mouseV (within the top and bottom limits of its range). We also need to use the pythagorean theorum to calculate the locH. That will take care of moving the thumb along the arc of our circle. Let's not forget to scroll the text. To do that, I'll call a separate handler called "scroll". This handler will simply look at how far down the scroller is from the top. Multiplying this distance by our (previously caluculated) scrollFactor will tell us what the scrollTop should be for the text.
on mouseDown me repeat while the stillDown if the mouseV > pTop and the mouseV ¬ < pBottom then set b = the mouseV - pOriginV pythag me, b end if end repeat end on pythag me, b set c = pRadius -- for Pythagorean clarity set a = sqrt((c * c) - (b * b)) set the locH of sprite pMySprite = pOriginH + a set the locV of sprite pMySprite = pOriginV + b scroll me updateStage end on scroll me set thumbPos = the locV of sprite pMySprite - pTop set the scrollTop of member pFieldMem = ¬ thumbPos * pScrollFactor end
Finally, we'll need to deal with our up and down scroller arrows. This handler is still part of our thumb behavior. It will receive a message from the arrows telling it which way to scroll and how much.
on arrowScroll me, scrollincr set currentV = the locV of sprite pMySprite set b = currentV - pOriginV set b = b + scrollincr set newV = pOriginV + b if (newV < pTop + pThumbMargin) and scrollincr ¬ < 0 then set newV = pTop else if (newV > pBottom - pThumbMargin) and ¬ scrollincr > 0 then set newV = pBottom end if set b = newV - pOriginV pythag me b end -- end of scroll thumb behavior
And here's the behavior that you'll need to put on the arrows in order to send the message to the scroll thumb. You'll need to specify the speed at which the arrows will move the thumb up and down.
-- up/down arrow scroll behavior (curved) -- copyright © 1999, ZZP Online, LLC property pWhichArrow, pSpeed, pMouseFlag, ¬ pThumbSprite, pScrollincr on getPropertyDescriptionList me set arrowList = [#UP, #DOWN] set pdlist to [:] addprop pdlist, #pThumbSprite, [#comment:¬ "Thumb spriteNum:", #format:#integer, #default:0] addprop pdlist, #pWhichArrow, [#comment:"Which ¬ arrow?", #format:#symbol, #default:#UP, ¬ #range: arrowList] addprop pdlist, #pSpeed, [#comment:"Scroll speed",¬ #format:#integer, #default:5, #range:[#max:10, ¬ #min:1]] return pdlist end getPropertyDescriptionList on beginSprite me if pWhichArrow = #UP then set pScrollincr = pSpeed * -1 else set pScrollincr = pSpeed end if end on mouseDown me set pMouseFlag = #clicked end on mouseUp me set pMouseFlag = #notClicked end on mouseUpOutside me set pMouseFlag = #notClicked end mouseUpOutside on exitFrame me if pMouseFlag = #clicked then sendSprite(pThumbSprite, #arrowScroll,¬ pScrollincr) end if end -- end arrows behavior
That's the whole thing. Note that this behavior works for motion along the right half of a circular arc. For motion along the left side, you'd need to subtract the pythagorean values from the origin -- instead of adding them as I did in this behavior. You'd also want to change things if you need motion in the 180 degree arc representing the top or bottom of the circle.
Good luck with your project.
A Director movie for this behavior is available for download in Mac or PC format.
Once you understand these concepts, you should read Darryl Plant's work on Bezier curves. Eric Woods also has some cool examples.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.