How to scroll an image
The basic idea to scroll an image with Red is to modify the image offset inside the image container (classically a base face).
Such technique is simple due to the existence of draw. Draw is a dialect (DSL) of Red language that provides a simple declarative way to specify 2D drawing operations. Such operations are expressed as lists commands.
In our case, translate operation is really nice since translate sets the origin for drawing commands and can also be used with image.
Make a draw block
First we define a block of draw commands such as drawBlk: compose [translate 0x0 image] where 0x0 is the initial offset of the image.
Then, when the image to scroll is loaded, we add the image in the block and affect the draw block to the draw facet of the image container (here, canvas face).
img1: load image_file_name
append drawBlk img1
canvas/draw: drawBlk
canvas/draw: drawBlk
Lastly, we need to update the image offset according to the value of both horizontal and vertical sliders we use to scroll the image. This is done by the updateSlider function which calculates the x and y offset of the image. Canvas face must be considered as a box on the image with a 0x0 left-upper coordinates. This is why, we use negate in order to correctly scroll the image in x and y according to slider value as well as image and canvas size.Then, we just update the offset value inside the draw block with drawBlk/2: xy since the offset of the image is the second element of the block.
Code example
Red [
Title: "Scroll Image"
Author: "Francois Jouen"
File: %scrollImage.red
Needs: 'View
]
xy: 0x0
margins: 10x10
isFile: false
loadImage: does [
isFile: false
tmp: request-file
xy: 0x0
drawBlk: compose [translate 0x0 image]
if not none? tmp [
img1: load tmp
append drawBlk img1
canvas/draw: drawBlk
f/text: form img1/size
isFile: true
;shows sliders if necessary
either img1/size/x > 640 [hSlider/visible?: true] [hSlider/visible?: false]
either img1/size/y > 480 [vSlider/visible?: true] [vSlider/visible?: false]
;sets sliders position and updates sliders to get a centered image
vSlider/data: 50%
hSlider/data: 50%
updateSlider/x
updateSlider/y
]
]
updateSlider: function [/x /y] [
case [
x [xy/x: to integer! negate hSlider/data * max 0 img1/size/x - canvas/size/x]
y [xy/y: to integer! negate vSlider/data * max 0 img1/size/y - canvas/size/y]
]
;shows image offset value
f2/text: form xy
;updates draw block with image offset value
drawBlk/2: xy
]
; ***************** Test Program ****************************
view win: layout [
title "Image Scrolling"
origin margins space margins
style btn: button -1x-1
style txt: text middle -1x20
btn 60 "Load" [loadImage]
txt "Image size"
f: field 120
txt "Image offset"
f2: field 120 "0x0"
pad 80x0
btn 60 "Quit" [Quit]
return
canvas: base 640x480 black
vSlider: slider 16x480 [if isFile [updateSlider/y]]
return
hSlider: slider 640x16 [if isFile [updateSlider/x]]
]
Aucun commentaire:
Enregistrer un commentaire