Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Проверить закрашена линия (или прямоугольник) (http://www.flasher.ru/forum/showthread.php?t=212636)

art_maestro 29.03.2016 22:22

Проверить закрашена линия (или прямоугольник)
 
Здравствуйте.

Задача такая. Есть ряд линий (или прямоугольников) белого цвета. Пользователю необходимо закрасить эти прямоугольники. Не по нажатию по линии, а именно заштриховать (например, в красный цвет). Как проверить, была ли область (прямоугольник или линия) полностью закрашена или нет?

Спасибо!

Zebestov 29.03.2016 23:37

Вложений: 1
Код AS3:

import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Shape;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import flash.geom.Matrix;
import flash.display.StageScaleMode;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
 
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.frameRate = 60;
 
var background:Shape = new Shape();
background.graphics.beginFill(0xa0a0a0);
background.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
addChild(background);
 
var tf:TextField = new TextField();
tf.width = stage.stageWidth;
tf.height = 30;
tf.y = 10;
tf.defaultTextFormat = new TextFormat('Arial', 20, 0xffffff, true, null, null, null, null, TextFormatAlign.CENTER);
tf.text = '0%';
addChild(tf);
 
var rectToFill:BitmapData = new BitmapData(300, 200, false, 0xffffff);
var rectToFillBmp:Bitmap = new Bitmap(rectToFill);
rectToFillBmp.x = (stage.stageWidth - rectToFillBmp.width) / 2;
rectToFillBmp.y = (stage.stageHeight - rectToFillBmp.height) / 2;
addChild(rectToFillBmp);
 
var canvas:Shape = new Shape();
addChild(canvas);
 
var mtx:Matrix = new Matrix();
mtx.translate(-rectToFillBmp.x, -rectToFillBmp.y);
 
var brushPosition:Point = new Point();
 
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
 
function onMouseDown(event:MouseEvent):void {
        //brushPosition.x = event.stageX;
        //brushPosition.y = event.stageY;
        canvas.graphics.moveTo(event.stageX, event.stageY);
        canvas.graphics.lineStyle(40, 0xff0000);
 
        stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpOrLeave);
        stage.addEventListener(Event.MOUSE_LEAVE, onMouseUpOrLeave);
}
 
function onMouseMove(event:MouseEvent):void {
        canvas.graphics.lineTo(event.stageX, event.stageY);
}
 
function onMouseUpOrLeave(event:MouseEvent):void {
        stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUpOrLeave);
        stage.removeEventListener(Event.MOUSE_LEAVE, onMouseUpOrLeave);
 
        // Срисовываем нашу мазанину с холста в "прямоугольник".
        rectToFill.draw(canvas, mtx, null, null, null, true);
        canvas.graphics.clear();
 
        // Берем самое яркое (255-е) значение "синего" (который по индексу 2)
        // вектора гистограммы нашего "прямоугольника". Так как мы рисуем красным,
        // под закрашенными пикселями тухнут зеленые и синие значения.
        // Вот мы и ждем, когда распространение синих точек сведется со значения
        // 60000 (ширина умноженная на высоту прямоугольника, его площадь в квадратных
        // пикселях, так сказать) до нуля.
        var ratio:Number = (1 - rectToFill.histogram()[2][255] / 60000) * 100;
 
        if (ratio == 100) {
                tf.text = int(ratio) + '% (готово!)';
        } else if (ratio  >= 90) {
                tf.text = int(ratio) + '% (почти)';
        } else if (ratio  >= 70) {
                tf.text = int(ratio) + '% (еще немножечко)';
        } else {
                tf.text = int(ratio) + '%';
        }
}

Fill.swf   (2.0 Кб)

art_maestro 30.03.2016 00:54

Спасибо огромное! Буду разбираться.

ALeXVoz 30.03.2016 01:11

rectToFill.histogram() - не знал о такой функции =)

Zebestov 30.03.2016 13:45

Забыл прокомментировать, зачем ждать полного отсутствия синего (как в примере) вместо наличия тотального красного. Это сделано с заделом на то, что цвет закрашивания может быть любым оттенком, собранным из двух оставшихся цветов (красный, зеленый, желтый, оранжевый, салатовый и т.д.). Точно так же можно проверять гистограмму на красный или синий цвет, тогда можно закрашивать синим, зеленым, бирюзовым (если будем проверять отсутствие красного), или синим, сиреневым, малиновым, красным, бордовым (в случае проверки зеленого канала).

ZackMercury 20.06.2016 23:50

Zebestov, тогда лучше брать константу цвета закраски, и сравнивать с её компонентами или с её инверсией при надобности.

Zebestov 21.06.2016 00:00

ZackMercury, можешь показать кодом? Что-то я не понял, как это применить к приведенному выше алгоритму.

ZackMercury 21.06.2016 00:28

Берём это:
Цитата:

function onMouseDown(event:MouseEvent):void {
//brushPosition.x = event.stageX;
//brushPosition.y = event.stageY;
canvas.graphics.moveTo(event.stageX, event.stageY);
canvas.graphics.lineStyle(40, 0xff0000);

stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpOrLeave);
stage.addEventListener(Event.MOUSE_LEAVE, onMouseUpOrLeave);
}
Выносим в константу(так положено):
Код AS3:

const BRUSH_COLOR:uint = 0xFF0000;

Код AS3:

function onMouseDown(event:MouseEvent):void {
        //brushPosition.x = event.stageX;
        //brushPosition.y = event.stageY;
        canvas.graphics.moveTo(event.stageX, event.stageY);
        canvas.graphics.lineStyle(40, BRUSH_COLOR);
 
        stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpOrLeave);
        stage.addEventListener(Event.MOUSE_LEAVE, onMouseUpOrLeave);
}

Смотрим, что возвращает метод histogram:
Цитата:

This method returns a Vector object containing four Vector.<Number> instances (four Vector objects that contain Number objects). The four Vector instances represent the red, green, blue and alpha components in order. Each Vector instance contains 256 values that represent the population count of an individual component value, from 0 to 255.
Значит, мы можем брать статистику конкретного цвета, а не сравнивать отдельные компоненты.
Код AS3:

var ratio:Number = (rectToFill.histogram()[0][BRUSH_COLOR >> 16 & 0xFF] / (rectToFill.width*rectToFill.height) * 100;
var ratio2:Number = (rectToFill.histogram()[1][BRUSH_COLOR >> 8 & 0xFF] / (rectToFill.width*rectToFill.height)) * 100;
var ratio3:Number = (rectToFill.histogram()[2][BRUSH_COLOR & 0xFF] / (rectToFill.width*rectToFill.height)) * 100;
if (ratio == 100 && ratio2 == 100 && ratio3 == 100) {
        tf.text = int(ratio) + '% (готово!)';
} else if (ratio  >= 90 && ratio2 >= 90 && ratio3 >= 90) {
        tf.text = int(ratio) + '% (почти)';
} else if (ratio  >= 70 && ratio3 >= 70 && ratio4 >= 70) {
        tf.text = int(ratio) + '% (еще немножечко)';
} else {
        tf.text = int(ratio) + '%';
}

К сожалению, у меня нет сейчас Flash-среды нужной версии, в которой я смог бы протестировать код.
Ну и да, конечно в таком случае лучше вынести результат выполнения histogram в отдельную переменную.
UPD: забыл поменять с инверсии, сча...


Часовой пояс GMT +4, время: 03:13.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.