A Cinder application can receive several touch events.
The available touch event handlers that get called by touch interaction are listed in the following table:
Method |
Usage |
---|---|
This is called when new touches are detected | |
This is called when existing touches move | |
This is called when existing touches are removed |
All of the preceding methods receive a ci::app::TouchEvent
object as a parameter with a std::vector
of ci::app::TouchEvent::Touch
objects with information about each touch detected. Since many devices can detect and respond to several touches simultaneously, it is possible and common for a touch event to contain several touches.
It is not mandatory to implement all of the preceding event handlers; you can use the ones your application requires specifically.
Cinder applications can respond to touch events on any touch-enabled device running Windows 7, OS X, or iOS.
Implement the necessary touch event handlers according to the touch events you want to respond to. For example, to respond to all available touch events (touches added, touches moved, and touches removed), you would need to declare and implement the following methods:
void touchesBegan( TouchEvent event ); void touchesMoved( TouchEvent event ); void touchesEnded( TouchEvent event );
We will learn how to work with the ci::app::TouchEvent
class to understand touch events. Perform the following steps to do so:
const std::vector<TouchEvent::Touch>& touches = event.getTouches();
Iterate through the container to access each individual element.
for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){ const TouchEvent::Touch& touch = *it; //do something with the touch object }
getPos
method that returns a Vec2f
value with its position or using the getX
and getY
methods to receive the x and y coordinates separately, for example:for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){ const TouchEvent::Touch& touch = *it; vec2f pos = touch.getPos(); float x = touch.getX(); float y = touch.getY(); }
getId
method returns a uint32_t
value with a unique ID for the touch
object. This ID is persistent throughout the lifecycle of the touch, which means you can use it to keep track of a specific touch as you access it on the different touch events.For example, to make an application where we draw lines using our fingers, we can create std::map
that associates each line, in the form of a ci::PolyLine<Vec2f>
object, with a uint32_t
key with the unique ID of a touch.
We need to include the file with std::map
and PolyLine
to our project by adding the following code snippet to the beginning of the source file:
#include "cinder/polyline.h" #include <map>
std::map< uint32_t, PolyLine<Vec2f> > mLines;
touchesBegan
method we create a new line for each detected touch and map it to the unique ID of each touch:const std::vector<TouchEvent::Touch>& touches = event.getTouches(); for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){ const TouchEvent::Touch& touch = *it; mLines[ touch.getId() ] = PolyLine<Vec2f>(); }
touchesMoved
method, we add the position of each touch to its corresponding line:const std::vector<TouchEvent::Touch>& touches = event.getTouches(); for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){ const TouchEvent::Touch& touch = *it; mLines[ touch.getId() ].push_back( touch.getPos() ); }
touchesEnded
method, we remove the line that corresponds to a touch being removed:const std::vector<TouchEvent::Touch>& touches = event.getTouches(); for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){ const TouchEvent::Touch& touch = *it; mLines.erase( touch.getId() ); }
draw
method:gl::clear( Color::black() ); gl::color( Color::white() ); for( std::map<uint32_t, PolyLine<Vec2f> >::iterator it = mLines.begin(); it != mLines.end(); ++it ){ gl::draw( it->second ); }
The following is a screenshot of our app running after drawing some lines:
A Cinder application responds internally to the system calls for any touch event. It will then create a ci::app::TouchEvent
object with information about the event and call the corresponding event handler in our application's class. The way to respond to touch events becomes uniform across the Windows and Mac platforms.
The ci::app::TouchEvent
class contains only one accessor method that returns a const
reference to a std::vector<TouchEvent::Touch>
container. This container has one ci::app::TouchEvent::Touch
object for each detected touch and contains information about the touch.
The ci::app::TouchEvent::Touch
object contains information about the touch including position and previous position, unique ID, the time stamp, and a pointer to the native event object which maps to UITouch
on Cocoa Touch and TOUCHPOINT
on Windows 7.
At any time, it is also possible to get a container with all active touches by calling the getActiveTouches
method. It returns a const
reference to a std::vector<TouchEvent::Touch>
container. It offers flexibility when working with touch applications as it can be accessed outside the touch event methods.
For example, if you want to draw a solid red circle around each active touch, you can add the following code snippet to your draw
method:
const std::vector<TouchEvent::Touch>&activeTouches = getActiveTouches(); gl::color( Color( 1.0f, 0.0f, 0.0f ) ); for( std::vector<TouchEvent::Touch>::const_iterator it = activeTouches.begin(); it != activeTouches.end(); ++it ){ const TouchEvent::Touch& touch = *it; gl::drawSolidCircle( touch.getPos(), 10.0f ); }
3.139.86.18