Copy link to clipboard
Copied
Hello everyone,
Ok then from the top.
I have a rectangle and I want it to scale at a set angle/percentage, from the corner I am dragging.
As you can see, I want to be able to drag each corner, independent of each other corner, and for the whole rectangle to scale in the dragged fixed angle direction, As though its scaling to a fix percentage of the original size.
Using the image attached as an illustration, if I drag point A then the rectangle will only scale along the blue line direction.
If the user then clicks on another corner, and starts to drag it, then the rectangle will scale from the point clicked, along a theoretical angle. And so on as the user moves around each corner.
This one has be stumped so any help would be appreciated.
Thanks in advance.
1 Correct answer
you can use the following function to change your reg point. ie, when a corner is clicked change the rectangle's reg point to that corner and then adjust the rectangle's scaleX and scaleY properties.
function changeRegPtF(dobj:DisplayObjectContainer,x:Number,y:Number):void {
var r:Rectangle = dobj.getRect(dobj);
for (var i:int=0; i<dobj.numChildren; i++) {
dobj.getChildAt(i).x-=r.x+x;
dobj.getChildAt(i).y-=r.y+y;
}
dobj.x+=r.x+x;
dobj.y+=r.y+y;
}
Copy link to clipboard
Copied
you can use the following function to change your reg point. ie, when a corner is clicked change the rectangle's reg point to that corner and then adjust the rectangle's scaleX and scaleY properties.
function changeRegPtF(dobj:DisplayObjectContainer,x:Number,y:Number):void {
var r:Rectangle = dobj.getRect(dobj);
for (var i:int=0; i<dobj.numChildren; i++) {
dobj.getChildAt(i).x-=r.x+x;
dobj.getChildAt(i).y-=r.y+y;
}
dobj.x+=r.x+x;
dobj.y+=r.y+y;
}
Copy link to clipboard
Copied
Hi kglad,
Sorry to ask as Im very new to Flash, do you have a more detailed example?
Thanks
Copy link to clipboard
Copied
i don't have a more detailed example in my resource files. i could create that but 90% of the work i've already done and posted in the changeRegPtF function.
Copy link to clipboard
Copied
Here is an adaptation of an old code I found in my libraries that does similar things.
There are both timeline and class variations.
Read comments.
Timeline:
import flash.display.Graphics;
import flash.display.GraphicsPathWinding;
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.MouseEvent;
// rectangle container
var container:Sprite;
// rectangle visual
var rectangle:Shape;
/**
* rectangle Graphicts
* @see updateRectangle()
*/
var rectGraphics:Graphics;
// rectanlge aspect ratio as width / height
var ratio:Number = 2 / 3;
// handle that is currently dragged
var currentHandle:MovieClip;
// collection of handles
var handles:Vector.<MovieClip>;
/**
* commands for rectangle drawing
* @see updateRectangle()
*/
var commands:Vector.<int>;
/**
* coordinates for rectangle drawing
* @see updateRectangle()
*/
var coord:Vector.<Number>;
// flags whether ractangle aspect ratio must be preserved
var preserveRatio:Boolean = true;
/**
* used for rectangle width calculations
* @see invalidateToRatio()
*/
var rw:Number = 0;
/**
* used for rectangle height calculations
* @see invalidateToRatio()
*/
var rh:Number = 0;
init();
function init():void
{
commands = new Vector.<int>();
commands.push(1, 2, 2, 2, 2);
coord = new Vector.<Number>();
drawRect();
}
function drawRect():void
{
initContainer()
initRect();
container.addChild(rectangle);
var initWidth:Number = 100;
var initHeight:Number = 150;
ratio = initWidth / initHeight;
drawHandles();
handles[1].x = initWidth;
handles[2].x = initWidth;
handles[2].y = initHeight;
handles[3].y = initHeight;
updateRectangle();
}
function initContainer():void
{
container = new Sprite();
container.x = container.y = 100;
addChild(container);
}
function initRect():void
{
rectangle = new Shape();
rectGraphics = rectangle.graphics;
}
/**
* Populates hadles collection.
*/
function drawHandles():void
{
handles = new Vector.<MovieClip>();
for (var i:int = 0; i < 4; i++)
{
var h:MovieClip = handle;
h.index = i;
container.addChild(h);
handles.push(h);
}
}
/**
* Draws individual handle.
*/
function get handle():MovieClip
{
var h:MovieClip = new MovieClip();
h.graphics.beginFill(0xffffff * Math.random());
h.graphics.drawRect(-5, -5, 10, 10);
h.graphics.endFill();
h.buttonMode = true;
h.useHandCursor = true;
h.addEventListener(MouseEvent.MOUSE_DOWN, onHandleDown);
return h;
}
function onHandleDown(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, onHandleUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onHandleMove);
currentHandle = MovieClip(e.currentTarget);
}
function onHandleMove(e:MouseEvent):void
{
/**
* place current handle to mouse position -
* may be recalculated later due to ratio
*/
currentHandle.x = container.mouseX;
currentHandle.y = container.mouseY;
switch (currentHandle.index)
{
case 0:
if (preserveRatio)
invalidateToRatio(2, 0, 2, 0, 2, 2, -1, -1);
placeDependentHandles(3, 1);
break;
case 1:
if (preserveRatio)
invalidateToRatio(1, 0, 2, 1, 0, 2, 1, -1);
placeDependentHandles(2, 0);
break;
case 2:
if (preserveRatio)
invalidateToRatio(2, 0, 2, 0, 0, 0, 1, 1);
placeDependentHandles(1, 3);
break;
case 3:
if (preserveRatio)
invalidateToRatio(3, 2, 3, 2, 0, 0, -1, -1);
placeDependentHandles(0, 2);
break;
}
updateRectangle();
e.updateAfterEvent();
}
/**
* Places dependent handles relative to current handle position.
* @param ix index of handle that must bo positioned to the current handle x
* @param iy index of handle that must bo positioned to the current handle y
*/
function placeDependentHandles(ix:int, iy:int):void
{
handles[ix].x = currentHandle.x;
handles[iy].y = currentHandle.y;
}
/**
* Calculates hadles positions based on rectangle aspect ratio.
*
* @param wi1 index of handle which x position is used as largests to claculate current width
* @param wi2 index of handle which x position is used as smalles to claculate current width
* @param hi1 index of handle which y position is used as largests to claculate current height
* @param hi2 index of handle which y position is used as smalles to claculate current height
* @param xi index of handle which x position is used as base for adding adjusted width
* @param yi index of handle which y position is used as base for adding adjusted height
* @param wm mutliplier used to add or subtract width
* @param hm mutliplier used to add or subtract height
*/
function invalidateToRatio(wi1:int, wi2:int, hi1:int, hi2:int, xi:int, yi:int, wm:int, hm:int):void
{
rw = handles[wi1].x - handles[wi2].x;
rh = handles[hi1].y - handles[hi2].y;
// reltionships of current ratio to actual ratio defines current handle x/y position calculations
rw / rh >= ratio ? currentHandle.x = handles[xi].x + wm * rh * ratio : currentHandle.y = handles[yi].y + hm * rw / ratio;
}
/**
* Rerdraws rectangle based on handles positions.
*/
function updateRectangle():void
{
for (var i:int = 0; i < 4; i++)
{
coord[i + i] = handles.x;
coord[i + i + 1] = handles.y;
}
coord[8] = handles[0].x;
coord[9] = handles[0].y;
rectGraphics.clear();
rectGraphics.lineStyle(1);
rectGraphics.drawPath(commands, coord, GraphicsPathWinding.NON_ZERO);
}
function onHandleUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onHandleUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onHandleMove);
}
As Class:
package
{
import flash.display.Graphics;
import flash.display.GraphicsPathWinding;
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.MouseEvent;
public class DynamicRectangle extends Sprite
{
// rectangle container
private var container:Sprite;
// rectangle visual
private var rectangle:Shape;
/**
* rectangle Graphicts
* @see updateRectangle()
*/
private var rectGraphics:Graphics;
// rectanlge aspect ratio as width / height
private var ratio:Number = 2 / 3;
// handle that is currently dragged
private var currentHandle:MovieClip;
// collection of handles
private var handles:Vector.<MovieClip>;
/**
* commands for rectangle drawing
* @see updateRectangle()
*/
private var commands:Vector.<int>;
/**
* coordinates for rectangle drawing
* @see updateRectangle()
*/
private var coord:Vector.<Number>;
// flags whether ractangle aspect ratio must be preserved
private var preserveRatio:Boolean = true;
/**
* used for rectangle width calculations
* @see invalidateToRatio()
*/
private var rw:Number = 0;
/**
* used for rectangle height calculations
* @see invalidateToRatio()
*/
private var rh:Number = 0;
public function DynamicRectangle()
{
init();
}
private function init():void
{
commands = new Vector.<int>();
commands.push(1, 2, 2, 2, 2);
coord = new Vector.<Number>();
drawRect();
}
private function drawRect():void
{
initContainer()
initRect();
container.addChild(rectangle);
var initWidth:Number = 100;
var initHeight:Number = 150;
ratio = initWidth / initHeight;
drawHandles();
handles[1].x = initWidth;
handles[2].x = initWidth;
handles[2].y = initHeight;
handles[3].y = initHeight;
updateRectangle();
}
private function initContainer():void
{
container = new Sprite();
container.x = container.y = 100;
addChild(container);
}
private function initRect():void
{
rectangle = new Shape();
rectGraphics = rectangle.graphics;
}
/**
* Populates hadles collection.
*/
private function drawHandles():void
{
handles = new Vector.<MovieClip>();
for (var i:int = 0; i < 4; i++)
{
var h:MovieClip = handle;
h.index = i;
container.addChild(h);
handles.push(h);
}
}
/**
* Draws individual handle.
*/
private function get handle():MovieClip
{
var h:MovieClip = new MovieClip();
h.graphics.beginFill(0xffffff * Math.random());
h.graphics.drawRect(-5, -5, 10, 10);
h.graphics.endFill();
h.buttonMode = true;
h.useHandCursor = true;
h.addEventListener(MouseEvent.MOUSE_DOWN, onHandleDown);
return h;
}
private function onHandleDown(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, onHandleUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onHandleMove);
currentHandle = MovieClip(e.currentTarget);
}
private function onHandleMove(e:MouseEvent):void
{
/**
* place current handle to mouse position -
* may be recalculated later due to ratio
*/
currentHandle.x = container.mouseX;
currentHandle.y = container.mouseY;
switch (currentHandle.index)
{
case 0:
if (preserveRatio)
invalidateToRatio(2, 0, 2, 0, 2, 2, -1, -1);
placeDependentHandles(3, 1);
break;
case 1:
if (preserveRatio)
invalidateToRatio(1, 0, 2, 1, 0, 2, 1, -1);
placeDependentHandles(2, 0);
break;
case 2:
if (preserveRatio)
invalidateToRatio(2, 0, 2, 0, 0, 0, 1, 1);
placeDependentHandles(1, 3);
break;
case 3:
if (preserveRatio)
invalidateToRatio(3, 2, 3, 2, 0, 0, -1, -1);
placeDependentHandles(0, 2);
break;
}
updateRectangle();
e.updateAfterEvent();
}
/**
* Places dependent handles relative to current handle position.
* @param ix index of handle that must bo positioned to the current handle x
* @param iy index of handle that must bo positioned to the current handle y
*/
private function placeDependentHandles(ix:int, iy:int):void
{
handles[ix].x = currentHandle.x;
handles[iy].y = currentHandle.y;
}
/**
* Calculates hadles positions based on rectangle aspect ratio.
*
* @param wi1 index of handle which x position is used as largests to claculate current width
* @param wi2 index of handle which x position is used as smalles to claculate current width
* @param hi1 index of handle which y position is used as largests to claculate current height
* @param hi2 index of handle which y position is used as smalles to claculate current height
* @param xi index of handle which x position is used as base for adding adjusted width
* @param yi index of handle which y position is used as base for adding adjusted height
* @param wm mutliplier used to add or subtract width
* @param hm mutliplier used to add or subtract height
*/
private function invalidateToRatio(wi1:int, wi2:int, hi1:int, hi2:int, xi:int, yi:int, wm:int, hm:int):void
{
rw = handles[wi1].x - handles[wi2].x;
rh = handles[hi1].y - handles[hi2].y;
// reltionships of current ratio to actual ratio defines current handle x/y position calculations
rw / rh >= ratio ? currentHandle.x = handles[xi].x + wm * rh * ratio : currentHandle.y = handles[yi].y + hm * rw / ratio;
}
/**
* Rerdraws rectangle based on handles positions.
*/
private function updateRectangle():void
{
for (var i:int = 0; i < 4; i++)
{
coord[i + i] = handles.x;
coord[i + i + 1] = handles.y;
}
coord[8] = handles[0].x;
coord[9] = handles[0].y;
rectGraphics.clear();
rectGraphics.lineStyle(1);
rectGraphics.drawPath(commands, coord, GraphicsPathWinding.NON_ZERO);
}
private function onHandleUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onHandleUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onHandleMove);
}
}
}
Copy link to clipboard
Copied
Hi Andrei1,
Thats exactly what I was looking for. Thank you
And thank you Kglad for your help too.
Copy link to clipboard
Copied
you're welcome.

