Я, конечно, знаю, что готовых реализаций эффекта лупы для ActionScript существует довольно много, но реализация данного эффекта от Barbara Kaskosz мне показалась довольно интересной. Не идеальной, но интересной. Естественно, вам, почти наверняка, придётся внести некоторые изменения в код, но всё же основа эффекта уже готова и работает.
Итак, код. К счастью или к сожалению, код процедурный. Но зато он снабжён комментариями автора и понять его не составит большого труда.
Код ActionScript 3.0:
/*
ActionScript 3 Effect by Barbara Kaskosz.
www.flashandmath.com
Last modified: September 30, 2008.
*/
/*
Below, we comment the portion of the code whcih you can change to easily customize
the applet.
*/
//'board' its the main conatiner in which the image resides. The position
//of 'board' will detrmine the position of your picture within the main movie.
var board:Sprite=new Sprite();
this.addChild(board);
board.x = 0;
board.y = 0;
var loader:Loader;
//The text field that displays loading information. To customize its
//apearance, got to setUpLoadBox function at the end of the script.
var infoBox:TextField;
var image:Bitmap;
var imageData:BitmapData;
var glass:Sprite=new Sprite();
//The size of the magnifying glass. You can change the values as you wish.
var glassWidth:int = 150;
var glassHeight:int = 150;
var doDrag:Boolean = false;
var picWidth:Number;
var picHeight:Number;
var dataWidth:Number;
var dataHeight:Number;
/*
'shrinkFactor' is the factor by which your original (high resolution) image
will be scaled down for display. The reciprocal of shrinkFactor is the magnifying
factor. 'shrinkFactor has to be less than 1 for the mangnifying effect to occur.
*/
var shrinkFactor:Number = 1 / 4;
var magFactor:Number = 1 / shrinkFactor;
setUpLoadBox();
startApp();
function startApp():void
{
loader=new Loader();
//Replace Kazanie_Skargi by the name of your image or the address of your image.
loader.load(new URLRequest("magnifyingeffect.jpg"));
//Replace 187 by the size of your high resolution image. Although it
//will show only for a second or so. In progress display, the total size will
//be determined automatically.
infoBox.text = "Loading: 0 KB of 187 KB";
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,initPic);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,updateInfo);
}
function updateInfo(e:ProgressEvent):void
{
infoBox.text = "Loading: " + String(Math.floor(e.bytesLoaded / 1024)) + " KB of " + String(Math.floor(e.bytesTotal / 1024)) + " KB.";
}
function initPic(e:Event):void
{
image = Bitmap(loader.content);
imageData = image.bitmapData;
dataWidth = image.width;
dataHeight = image.height;
image.scaleX = shrinkFactor;
image.scaleY = shrinkFactor;
picWidth = image.width;
picHeight = image.height;
board.addChild(image);
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,initPic);
loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,updateInfo);
loader = null;
infoBox.text = "";
infoBox.visible = false;
board.addChild(glass);
glass.filters=[ new DropShadowFilter() ];
board.filters=[ new DropShadowFilter() ];
setUpListeners();
}
function drawInGlass(a:Number,b:Number):void
{
var curBd:BitmapData;
var curBmp:Bitmap;
var xbeg:Number = a - glassWidth / 2;
var ybeg:Number = b - glassHeight / 2;
if (xbeg<0)
{
xbeg = 0;
}
if (ybeg<0)
{
ybeg = 0;
}
if (xbeg>dataWidth-glassWidth)
{
xbeg = dataWidth - glassWidth;
}
if (ybeg>dataHeight-glassHeight)
{
ybeg = dataHeight - glassHeight;
}
curBmp = new Bitmap(new BitmapData(glassWidth,glassHeight));
curBmp.bitmapData.copyPixels(imageData,new Rectangle(xbeg,ybeg,glassWidth,glassHeight),new Point(0,0));
curBd = curBmp.bitmapData;
glass.graphics.clear();
glass.graphics.lineStyle();
glass.graphics.beginBitmapFill(curBd);
glass.graphics.drawRect(0,0,glassWidth,glassHeight);
glass.graphics.endFill();
}
function glassClear():void
{
glass.graphics.clear();
}
function setUpListeners():void
{
board.addEventListener(MouseEvent.ROLL_OUT,boardOut);
board.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);
board.addEventListener(MouseEvent.MOUSE_DOWN,boardDown);
board.addEventListener(MouseEvent.MOUSE_UP,boardUp);
}
function boardOut(e:MouseEvent):void
{
doDrag = false;
glassClear();
Mouse.show();
}
function boardDown(e:MouseEvent):void
{
var locX:Number = board.mouseX;
var locY:Number = board.mouseY;
glass.x = locX - glassWidth / 2;
glass.y = locY - glassHeight / 2;
drawInGlass(magFactor*locX,magFactor*locY);
doDrag = true;
Mouse.hide();
}
function boardUp(e:MouseEvent):void
{
doDrag = false;
glassClear();
Mouse.show();
}
function boardMove(e:MouseEvent):void
{
var locX:Number = board.mouseX;
var locY:Number = board.mouseY;
var goodCoords:Point = getGoodCoords(locX,locY);
if (doDrag)
{
glass.x = goodCoords.x - glassWidth / 2;
glass.y = goodCoords.y - glassHeight / 2;
locX = goodCoords.x;
locY = goodCoords.y;
drawInGlass(magFactor*locX,magFactor*locY);
e.updateAfterEvent();
}
}
function getGoodCoords(a:Number,b:Number):Point
{
var goodCoords=new Point();
goodCoords.x = a;
goodCoords.y = b;
if (a < glassWidth/(2*magFactor))
{
goodCoords.x = glassWidth / (2 * magFactor);
}
if (a > picWidth-glassWidth/(2*magFactor))
{
goodCoords.x = picWidth - glassWidth / (2 * magFactor);
}
if (b < glassHeight/(2*magFactor))
{
goodCoords.y = glassHeight / (2 * magFactor);
}
if (b > picHeight-glassHeight/(2*magFactor))
{
goodCoords.y = picHeight - glassHeight / (2 * magFactor);
}
return goodCoords;
}
function setUpLoadBox():void
{
var infoFormat:TextFormat=new TextFormat();
infoBox=new TextField();
board.addChild(infoBox);
infoBox.x = 0;
infoBox.y = 0;
infoBox.type = TextFieldType.DYNAMIC;
infoBox.autoSize = TextFieldAutoSize.LEFT;
infoBox.wordWrap = false;
infoBox.border = false;
infoBox.background = false;
infoBox.mouseEnabled = false;
infoFormat.color = 0xCC0000;
infoFormat.size = 14;
infoFormat.font = "Arial";
infoBox.defaultTextFormat = infoFormat;
}
Что делает код? Данный код загружает внешнее изображение (magnifyingeffect.jpg) и помещает его на сцену флеш-ролика. Затем мы может зажать левую клавишу мышки над любым участком загруженного изображения и появится лупа, которая увеличит данный участок изображения. Попробуйте сами:
Но есть одно важное условие. Дело в том, что само изображение должно быть изначально достаточно большим и качественным, иначе эффект достигнут не будет. То есть код загружает изображение с высоким разрешением, масштабирует (уменьшает) его до тех пор, пока оно не влезет на сцену флеш-ролика. А с помощью лупы мы фактически получаем фрагмент картинки, взятый от исходного высококачественного изображения. Надеюсь, сумел донести смысл:-)
Размеры лупы можно настраивать. За это в коде отвечают две переменные:
- glassWidth - ширина лупы;
- glassHeight - высота лупы.
Изменять можно и форму лупы. Для этого надо просто изменить форму спрайта glass. Для примера сделаем лупу круглой.
Код ActionScript 3.0:
/*
ActionScript 3 Effect by Barbara Kaskosz.
www.flashandmath.com
Last modified: September 30, 2008.
*/
/*
Below, we comment the portion of the code whcih you can change to easily customize
the applet.
*/
//'board' its the main conatiner in which the image resides. The position
//of 'board' will detrmine the position of your picture within the main movie.
var board:Sprite=new Sprite();
this.addChild(board);
board.x = 0;
board.y = 0;
var loader:Loader;
//The text field that displays loading information. To customize its
//apearance, got to setUpLoadBox function at the end of the script.
var infoBox:TextField;
var image:Bitmap;
var imageData:BitmapData;
var glass:Sprite=new Sprite();
//The size of the magnifying glass. You can change the values as you wish.
var glassWidth:int = 150;
var glassHeight:int = 150;
var doDrag:Boolean = false;
var picWidth:Number;
var picHeight:Number;
var dataWidth:Number;
var dataHeight:Number;
/*
'shrinkFactor' is the factor by which your original (high resolution) image
will be scaled down for display. The reciprocal of shrinkFactor is the magnifying
factor. 'shrinkFactor has to be less than 1 for the mangnifying effect to occur.
*/
var shrinkFactor:Number = 1 / 4;
var magFactor:Number = 1 / shrinkFactor;
setUpLoadBox();
startApp();
function startApp():void
{
loader=new Loader();
//Replace Kazanie_Skargi by the name of your image or the address of your image.
loader.load(new URLRequest("magnifyingeffect.jpg"));
//Replace 187 by the size of your high resolution image. Although it
//will show only for a second or so. In progress display, the total size will
//be determined automatically.
infoBox.text = "Loading: 0 KB of 187 KB";
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,initPic);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,updateInfo);
}
function updateInfo(e:ProgressEvent):void
{
infoBox.text = "Loading: " + String(Math.floor(e.bytesLoaded / 1024)) + " KB of " + String(Math.floor(e.bytesTotal / 1024)) + " KB.";
}
function initPic(e:Event):void
{
image = Bitmap(loader.content);
imageData = image.bitmapData;
dataWidth = image.width;
dataHeight = image.height;
image.scaleX = shrinkFactor;
image.scaleY = shrinkFactor;
picWidth = image.width;
picHeight = image.height;
board.addChild(image);
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,initPic);
loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,updateInfo);
loader = null;
infoBox.text = "";
infoBox.visible = false;
board.addChild(glass);
glass.filters=[ new DropShadowFilter() ];
board.filters=[ new DropShadowFilter() ];
setUpListeners();
}
function drawInGlass(a:Number,b:Number):void
{
var curBd:BitmapData;
var curBmp:Bitmap;
var xbeg:Number = a - glassWidth / 2;
var ybeg:Number = b - glassHeight / 2;
if (xbeg<0)
{
xbeg = 0;
}
if (ybeg<0)
{
ybeg = 0;
}
if (xbeg>dataWidth-glassWidth)
{
xbeg = dataWidth - glassWidth;
}
if (ybeg>dataHeight-glassHeight)
{
ybeg = dataHeight - glassHeight;
}
curBmp = new Bitmap(new BitmapData(glassWidth,glassHeight));
curBmp.bitmapData.copyPixels(imageData,new Rectangle(xbeg,ybeg,glassWidth,glassHeight),new Point(0,0));
curBd = curBmp.bitmapData;
glass.graphics.clear();
glass.graphics.lineStyle();
glass.graphics.beginBitmapFill(curBd);
glass.graphics.drawCircle(glassWidth/2,glassWidth/2,glassWidth/2);
glass.graphics.endFill();
}
function glassClear():void
{
glass.graphics.clear();
}
function setUpListeners():void
{
board.addEventListener(MouseEvent.ROLL_OUT,boardOut);
board.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);
board.addEventListener(MouseEvent.MOUSE_DOWN,boardDown);
board.addEventListener(MouseEvent.MOUSE_UP,boardUp);
}
function boardOut(e:MouseEvent):void
{
doDrag = false;
glassClear();
Mouse.show();
}
function boardDown(e:MouseEvent):void
{
var locX:Number = board.mouseX;
var locY:Number = board.mouseY;
glass.x = locX - glassWidth / 2;
glass.y = locY - glassHeight / 2;
drawInGlass(magFactor*locX,magFactor*locY);
doDrag = true;
Mouse.hide();
}
function boardUp(e:MouseEvent):void
{
doDrag = false;
glassClear();
Mouse.show();
}
function boardMove(e:MouseEvent):void
{
var locX:Number = board.mouseX;
var locY:Number = board.mouseY;
var goodCoords:Point = getGoodCoords(locX,locY);
if (doDrag)
{
glass.x = goodCoords.x - glassWidth / 2;
glass.y = goodCoords.y - glassHeight / 2;
locX = goodCoords.x;
locY = goodCoords.y;
drawInGlass(magFactor*locX,magFactor*locY);
e.updateAfterEvent();
}
}
function getGoodCoords(a:Number,b:Number):Point
{
var goodCoords=new Point();
goodCoords.x = a;
goodCoords.y = b;
if (a < glassWidth/(2*magFactor))
{
goodCoords.x = glassWidth / (2 * magFactor);
}
if (a > picWidth-glassWidth/(2*magFactor))
{
goodCoords.x = picWidth - glassWidth / (2 * magFactor);
}
if (b < glassHeight/(2*magFactor))
{
goodCoords.y = glassHeight / (2 * magFactor);
}
if (b > picHeight-glassHeight/(2*magFactor))
{
goodCoords.y = picHeight - glassHeight / (2 * magFactor);
}
return goodCoords;
}
function setUpLoadBox():void
{
var infoFormat:TextFormat=new TextFormat();
infoBox=new TextField();
board.addChild(infoBox);
infoBox.x = 0;
infoBox.y = 0;
infoBox.type = TextFieldType.DYNAMIC;
infoBox.autoSize = TextFieldAutoSize.LEFT;
infoBox.wordWrap = false;
infoBox.border = false;
infoBox.background = false;
infoBox.mouseEnabled = false;
infoFormat.color = 0xCC0000;
infoFormat.size = 14;
infoFormat.font = "Arial";
infoBox.defaultTextFormat = infoFormat;
}
Проверим, изменилась ли форма нашей лупы:
Ну, не знаю как у вас, а у меня всё работает правильно:-)
Исходник к данному уроку под Adobe Flash CS5.5 скачать можно здесь.