Transformables are widgets which are capable of a number of behaviours, the most basic of which are moving, resizing and rotating, all in response to user interaction. Beyond these simple behaviours transformables also persist their state, can be landed into a dropzone, can trigger actions and can be cloned.
Moving transformables (moveables) are cross platform due to their click-and-drag nature but because resizing transformables (pinchables) and rotating transformables (rotatables) require gestures they rely on a platform/device that can handle multi touch events.
In the examples the transformables are all specified with an <img>
tag inside, this usually makes sense for a transformable although it is not a strict requirement as styling could be used to give the transformable an appearance.
Simple Behaviours
The basic transformable behaviours, although not a strict requirement it is recommended to always specify these parameters by convention for each transformable.
- Moveable
- The widget can be clicked-and-dragged around the screen with a single touch.
- Pinchable
- The widget can shrink/grow based on a pinch/flare two finger gesture.
- Rotatable
- The widget can rotate based on a two finger touch and rotate gesture.
Complex Behaviours
More transformable behaviours.
- State persistance
- Interactions with a transformable will persist across pages. The RESET_PAGE event can usually be used to clear this persistance.
- Using dropzones
- An element can be specified as a dropzone for the transformable. Additional actions can also be specified that will fire when the transformable is dropped either in the dropzone or not in the dropzone. The transformable can additionally be specified to require full or partial placement within the dropzone.
- Cloneables
- Transformables can also be specified to be cloneable, along with a clone limit.
HTML Parameters
The following parameters are required
- data-widget="TRANSFORMABLE" Required
- Transformable identifier.
The following parameters are optional (defaults are listed in braces)
- id="{{id}}" Optional
- It is usually preferable to include a unique ID but it is not strictly necessary.
- data-moveable="{{false}}" Optional
- Specifies that the transformable can be moved (click-and-drag or touch-and-drag).
- data-pinchable="{{false}}" Optional
- Specifies that the transformable can be shrunk/grown with a gesture.
- data-rotatable="{{false}}" Optional
- Specifies that the transformable can be rotated with a gesture.
- data-cloneable-count="{{0}}" Optional
- If the clone count is greater than 0 then the transformable can be cloned - note that these clones are in addition to the original transformable so a clone count of 5 will end with 6 total transformables.
- data-dropzone-target="{{id}}" Optional
- ID of the element to specify as a dropzone for the transformable.
- data-drop-action-target="{{id}}" Optional
- ID of the button widget element that will be fired when the transformable is dropped (not into the specified dropzone or if the dropzone is not specified).
- data-dropzone-action-target="{{id}}" Optional
- ID of the button widget element that will be fired when the transformable is dropped into its dropzone.
- data-lock-in-dropzone="{{false}}" Optional
- Specifies that the transformable will lock into its dropzone (i.e. loses its interactivity) when dropped. It will stay where it is when dropped.
- data-center-in-dropzone="{{false}}" Optional
- Specifies that the transformable will transition to the center of its dropzone when dropped in the dropzone.
- data-dropzone-overlaps-completely="{{false}}" Optional
- Specifies that the transformable should be dropped completely into its dropzone to successfully complete, if it is not then it will transition back to its original position.
Examples
Standard Moveable
The following example shows the most basic markup required to create a moving transformable. The transformable can be moved via a click-and-drag (or touch-and-drag). The convention of explicitly specifying movement, pinching and rotating is adhered to as good practise.
The styling is not a strict requirement and is left inline for brevity.
- id Optional
- A unique id for the HTML element.
- data-widget="TRANSFORMABLE" Required
- Animation widget identifier.
- data-moveable="true" Required
- Specifies a moveable transformable.
- data-pinchable="{{bool}}" Optional
- Specifies a pinchable (sizing) transformable.
- data-rotatable="{{bool}}" Optional
- Specifies a rotatable transformable.
<div id="uniqueid1" style="position:absolute; left:40px; top:120px;"
data-widget="TRANSFORMABLE"
data-moveable="true"
data-pinchable="false"
data-rotatable="false" >
<img src="../assets/transformable_image.png" />
</div>
Transformable with dropzone
The following example shows a transformable with a dropzone. Note that the dropzone element requires an ID for the transformable to be able to reference it.
The styling is not a strict requirement and is left inline for brevity.
- data-dropzone-target="{{id}}" Required
- Specifies the id of the dropzone element.
<!-- The Transformable -->
<div id="uniqueid1" style="position:absolute; left:40px; top:120px;"
data-widget="TRANSFORMABLE"
data-moveable="true"
data-pinchable="false"
data-rotatable="false"
data-dropzone-target="uniqueid2">
<img src="../assets/transformable_image.png" />
</div>
<!-- The Dropzone -->
<div id="uniqueid4" style="position:absolute; left:18px; top:412px; width:988px; height:292px;"></div>
Transformable with Dropzone and Actions
The following example shows a transformable that fires actions when it is dropped. The action targets specified in the markup reference buttons which then fire audio events. The audio and button widgets are positioned offscreen and whilst the buttons reference only one action they could just as easily reference a number of different actions meaning that complex emergent behaviour can be created from only a few basic markup elements.
The styling is not a strict requirement and is left inline for brevity.
- data-dropzone-target="{{id}}" Required
- Specifies the id of the dropzone element.
- data-drop-action-target="{{id}}" Required
- Fires an action when the transformable is dropped.
- data-dropzone-action-target="{{id}}" Required
- Fires an action when the transformable is dropped into its dropzone.
<!-- The Transformable -->
<div id="uniqueid1" style="position:absolute; left:40px; top:120px;"
data-widget="TRANSFORMABLE"
data-moveable="true"
data-pinchable="false"
data-rotatable="false"
data-dropzone-target="uniqueid2"
data-drop-action-target="buttonid1"
data-dropzone-action-target="buttonid2">
<img src="../assets/transformable_image.png" />
</div>
<!-- The Dropzone -->
<div id="uniqueid4" style="position:absolute; left:18px; top:412px; width:988px; height:292px;"></div>
<!-- Button buttonid1 - plays success audio - positioned offscreen -->
<div id="buttonid1" data-action="PLAY_MEDIA" data-widget="BUTTON" data-target="audioid1"
style="position:absolute;left:-9999px;">
<!--button-->
<img src="../assets/play.png" />
</div>
<!-- The audio that is fired by buttonid1 - positioned offscreen -->
<div id="audioid1" data-widget="AUDIO" data-src="../assets/fail.mp3"
data-audio-type="inline"
style="position:absolute;left:-9999px;" >
</div>
<!-- Button buttonid2 - plays failure audio - positioned offscreen -->
<div id="buttonid2" data-action="PLAY_MEDIA" data-widget="BUTTON" data-target="audioid2"
style="position:absolute;left:-9999px;">
<!--button-->
<img src="../assets/play.png" />
</div>
<!-- The audio that is fired by buttonid2 - positioned offscreen -->
<div id="audioid2" data-widget="AUDIO" data-src="../assets/success.wav"
data-audio-type="inline"
style="position:absolute;left:-9999px;">
</div>
Standard Cloneable
The following example shows a basic example of a cloneable. So long as the clone count is greater than 0 the transformable can be cloned. Clones will respond to dropzones and will restack on to the original if they are dropped outside of their required dropzone.
Note that the clones are in addition to the original so that a clone count of 5 will result in 6 final transformables (5 clones + 1 original).
The styling is not a strict requirement and is left inline for brevity.
- data-cloneable-count="{{number}}" Required
- The number of clones that can be created
<div id="uniqueid1" style="position:absolute; left:40px; top:120px;"
data-widget="TRANSFORMABLE"
data-moveable="true"
data-pinchable="false"
data-rotatable="false"
data-cloneable-count="5" >
<img src="../assets/transformable_image.png" />
</div>
Complex Example - using a slideshow
Widgets can interact with each other which means that they can be placed inside of each other and used in conjunction to provide more complex resulting behaviours. A slideshow can be used as a selector for transformables, for example.
The following example shows a slideshow that contains 6 transformables, 3 on the first slide and 3 on the second. Each transformable is a cloneable and has a dropzone and will transition back to their original position and restack if they are not dropped into their dropzone. Additionally they are all specified to require being dropped completely into their dropzone (no overlaps) and they will be locked-in once dropped into their dropzone (i.e. non-actionable).
The slideshow is specified with touch-interaction=false
so that touch/click events do not interfere with the transformables, this means that buttons are included to control the slideshow.
Note that the widget specification is included for the first transformable, but is omitted from the subsequent transformables for brevity. Also, due to the nature of slideshow styling each transformable is positioned relative to the slide it is placed on.
- data-cloneable-count="{{number}}" Optional
- The number of clones that can be created
- data-dropzone-target="{{id}}" Optional
- Specifies the id of the dropzone element.
- data-dropzone-overlaps-completely="{{bool}}" Optional
- Must be placed entirely into dropzone.
- data-lock-in-dropzone="{{bool}}" Optional
- Can not be moved once dropped in dropzone.
<!-- The slideshow of transformables -->
<div id="uniqueid3" class="slideshow border" data-widget="SLIDESHOW" data-touch-interaction="false" data-transition="SLIDE">
<ul id="uniqueid4">
<li id="uniqueid1">
<div id="unique1-1" style="position:absolute; left:20px; top:20px;"
data-widget="TRANSFORMABLE"
data-moveable="true"
data-pinchable="true"
data-rotatable="true"
data-cloneable-count="5"
data-dropzone-overlaps-completely="true"
data-lock-in-dropzone="true"
data-dropzone-target="uniqueid7">
<img src="../assets/image.png" />
</div>
<div id="unique1-2" style="position:absolute; left:366px; top:20px;"
data-widget="TRANSFORMABLE" >
<img src="../assets/image.png" />
</div>
<div id="unique1-3" style="position:absolute; left:712px; top:20px;"
data-widget="TRANSFORMABLE" >
<img src="../assets/image.png" />
</div>
</li>
<li id="uniqueid2">
<div id="unique2-1" style="position:absolute; left:20px; top:20px;"
data-widget="TRANSFORMABLE" >
<img src="../assets/image.png" />
</div>
<div id="unique2-2" style="position:absolute; left:366px; top:20px;"
data-widget="TRANSFORMABLE" >
<img src="../assets/image.png" />
</div>
<div id="unique2-3" style="position:absolute; left:712px; top:20px;"
data-widget="TRANSFORMABLE" >
<img src="../assets/image.png" />
</div>
</li>
</ul>
</div>
<!-- Previous Slide Button -->
<div id="uniqueid5" data-action="PREVIOUS_SLIDE" data-target="uniqueid3" data-widget="BUTTON"
style="position:absolute; left:0px; top:226px;">
<img class="icon" src="../assets/scrollarrow.png" style="-webkit-transform:rotate(-90deg);"/>
</div>
<!-- Next Slide Button -->
<div id="uniqueid6" data-action="NEXT_SLIDE" data-target="uniqueid3" data-widget="BUTTON"
style="position:absolute; left:988px; top:226px;">
<img class="icon" src="../assets/scrollarrow.png" style="-webkit-transform:rotate(90deg);"/>
</div>
<!-- The Dropzone -->
<div id="uniqueid7" class="border" style="position:absolute; left:18px; top:412px; width:988px; height:292px;"></div>
- Source:
- widgets/Transformable/TransformableWidget.js, line 2
Extends
- PR.BaseWidget
Methods
-
checkInDropzone( ) → {Boolean}
-
Checks to see if the widget is overlapping it's dropzone
Returns:
Booleanreturns true if there is an overlap or if there is no dropzone
- Source:
- widgets/Transformable/TransformableWidget.js, line 779
-
checkOverlap( rectA, rectB ) → {Boolean}
-
Utility function - checks for an overlap between 2 rectangles
Parameters:
Name Type Description rectA
rectB
Returns:
Booleantrue if they overlap, false if not
- Source:
- widgets/Transformable/TransformableWidget.js, line 836
-
checkOverParent( ) → {Boolean}
-
Checks to see if the widget is overlapping its parent
Returns:
Booleantrue if it is, false otherwise
- Source:
- widgets/Transformable/TransformableWidget.js, line 806
-
deleteElement( ) → {Boolean}
-
Removes event listeners and the associated element from the DOM
Returns:
Booleanwas the removal successful
- Source:
- widgets/Transformable/TransformableWidget.js, line 441
-
gestureChange( e )
-
Fired when a two finger gesture changes (pinch, expand or rotate)
Parameters:
Name Type Description e
event the event which fires this function
- Source:
- widgets/Transformable/TransformableWidget.js, line 662
-
gestureEnd( e )
-
Fired when the two finger gesture ends
Parameters:
Name Type Description e
event the event which fires this function
- Source:
- widgets/Transformable/TransformableWidget.js, line 686
-
gestureStart( e )
-
Fired when a two finger gesture is heard (i.e. pinch or rotate)
Touch and move will still be fired to allow movement whist scaling or rotatingParameters:
Name Type Description e
event the event which fires this function
- Source:
- widgets/Transformable/TransformableWidget.js, line 640
-
getAbsPos( ) → {coord}
-
Returns the absolute position on screen of the element associated with this widget with respect to
the 0,0 position of the document bodyReturns:
coordx and y on-screen coords of the widget
- Source:
- widgets/Transformable/TransformableWidget.js, line 1074
-
getAbsPosDOMSearch( ) → {coord}
-
Recursively searches the DOM tree adding up offsets to give the screen position of the HTML element associated
with this widget - DEPRECATEDReturns:
coordx and y coords of the widget on-screen
- Source:
- widgets/Transformable/TransformableWidget.js, line 1053
-
getActionWidget( node )
-
Gets the action widget that is associated with the node
Parameters:
Name Type Description node
HTMLElement node to find in the active widget list
Returns:
the associated widget or null if not found
- Source:
- widgets/Transformable/TransformableWidget.js, line 1028
-
getNewCloneNum_( ) → {Number}
-
Finds an unused number in the active clones array and returns it
Returns:
Number- Source:
- widgets/Transformable/TransformableWidget.js, line 1228
-
getParentId_( ) → {String}
-
Returns the id of parent that is associated with this widget
Returns:
String- Source:
- widgets/Transformable/TransformableWidget.js, line 1186
-
initVars_( )
-
Initialize the variables, fetch the attribute values from the mark up and assign them to instance variables.
- Source:
- widgets/Transformable/TransformableWidget.js, line 378
-
loadState( state )
-
Loads a state into the widget
Parameters:
Name Type Description state
Object a JSON string describing the state of the widget to be loaded in
- Source:
- widgets/Transformable/TransformableWidget.js, line 1286
-
moveToCenter_( )
-
This function snaps the widget into the center of the dropzone
- Source:
- widgets/Transformable/TransformableWidget.js, line 976
-
moveToCenterEnd_( )
-
This function is fired when a clone has snapped back to it's original position (i.e. the position of its parent)
It is called after unsuccessfully finding its desired dropzone- Source:
- widgets/Transformable/TransformableWidget.js, line 1009
-
moveToParentEnd_( )
-
This function is fired when a clone has snapped back to it's original position (i.e. the position of its parent)
It is called after unsuccessfully finding its desired dropzone- Source:
- widgets/Transformable/TransformableWidget.js, line 884
-
saveState( )
-
Saves the current state of the object and returns it as an object
- Source:
- widgets/Transformable/TransformableWidget.js, line 1252
-
setCloneActive_( )
-
Finds the passed clone in the activeClone array and registers it has been added
- Source:
- widgets/Transformable/TransformableWidget.js, line 1213
-
setCloneInactive_( )
-
Finds the passed clone in the activeClone array and registers it has been removed
- Source:
- widgets/Transformable/TransformableWidget.js, line 1200
-
touchEnd( e )
-
Fired when the touch ends - mouseup or touchend
Parameters:
Name Type Description e
event the event which fires this function
- Source:
- widgets/Transformable/TransformableWidget.js, line 557
-
touchMove( e )
-
Fired when a move event is heard - mousemove or touchmove
Parameters:
Name Type Description e
event the event which fires this function
- Source:
- widgets/Transformable/TransformableWidget.js, line 525
-
touchStart( e )
-
Fired when a touch is started - mousedown or touchstart
Parameters:
Name Type Description e
event the event which fires this function
- Source:
- widgets/Transformable/TransformableWidget.js, line 467