mercredi 19 avril 2017

How to scroll an image

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 

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]]
]

Result







Aucun commentaire:

Enregistrer un commentaire