# 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.

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2019, Director Online. Article content copyright by respective authors.