Можно ли улучшить производительность этой техники рисования? - PullRequest
1 голос
/ 22 октября 2010

В настоящее время я работаю над инструментом, созданным моим коллегой, и хотел бы улучшить производительность. По сути, это инструмент для рисования на экране, который использует комбинацию Sprites и класса Graphics для рисования отрезка линии каждый раз, когда мышь перемещается, когда кнопка мыши нажата. Вот бит рисования:

// on MouseMove
protected function drawLine(e:MouseEvent):void {
        if (currentTool.thickness > 0){
            //pen
            var line:Sprite = new Sprite();

            line.graphics.lineStyle(currentTool.thickness, currentColour);
            line.graphics.moveTo(lastKnownPoint.x, lastKnownPoint.y);
            line.graphics.lineTo(e.localX, e.localY);
            inkLayer.addChild(line);
            lastKnownPoint.x = e.localX;
            lastKnownPoint.y = e.localY;
            e.updateAfterEvent();
        } else {
            //eraser
            var inkChildren:int = inkLayer.numChildren;
            for (var i:uint = inkChildren; i > 0; i--){
                if (toolCursor.hitTestObject(inkLayer.getChildAt(i - 1))){
                    inkLayer.removeChildAt(i - 1);
                }
            }
        }
    }

Как вы можете видеть, он проверяет, является ли свойство 'толщина' линии, и рисует, если оно есть, и стирает, если это не так.

Я действительно думал об использовании техники, подобной блиттингу, здесь, где она обращается к растровому изображению, но я не уверен, что это дало бы прирост производительности, который я хочу, или если бы действительно был какой-то способ получить функция ластика.

Есть идеи, как лучше это сделать? Сам рисунок хорошо работает - это не проблема, это производительность последующих «нарисованных» спрайтов.

Ответы [ 3 ]

2 голосов
/ 22 октября 2010

Недавно я решил похожую проблему и не мог придумать эффективный способ реализации ластика с векторами.Поэтому я сделал растровое изображение, чтобы стереть рисунки.Это работает так: когда пользователь выбирает цветное перо, а он удерживает левую кнопку, рисует линии для спрайта.Когда левая кнопка отпущена, спрайт сбрасывается в BitmapData, и доска перерисовывается с использованием этого растрового изображения.Когда пользователь выбирает ластик, он рисует толстые черные линии на спрайте (они невидимы при альфа = 0).После каждого перемещения затронутая часть спрайта сбрасывается в BitmapData в режиме стирания, и это отражается на доске.Для поддержки масштабирования я сделал растровое изображение большим и подключил к нему BlurFilter.Это не идеально, но работает достаточно быстро.

Редактировать: некоторый код, не проверенный после вырезки, но должен дать идею:

public class DrawingBoard extends Sprite {
    //...vars declaration
    public function DrawingBoard(width:int, height:int, bitmapWidth:int = 1000, bitmapHeight:int = 1000)
    {
        super();
        scrollRect = new Rectangle(0, 0, width, height);

        downMatrix = new Matrix();
        downMatrix.scale(bitmapWidth / width, bitmapHeight / height);

        upMatrix = new Matrix();
        upMatrix.scale(width / bitmapWidth, height / bitmapHeight);

        bitmap = new BitmapData(bitmapWidth, bitmapHeight, true, 0x00000000);

        //on canvas we draw vector pencils and eraser traces before flush
        canvas = new Sprite();
        addChild(canvas);

        filters = [new BlurFilter(3, 3)];
    }

        //external control api
    public function moveTo(point:Point):void {
        canvas.graphics.moveTo(point.x, point.y);
        var lineWidth:Number = 4 / parent.scaleX;
        canvas.graphics.lineStyle(lineWidth, currentColor, 0.8, false, LineScaleMode.NORMAL);
    }

    public function lineTo(point:Point):void {
        canvas.graphics.lineTo(point.x, point.y);
    }

    public function eraserLineTo(point:Point):void {
        canvas.graphics.lineStyle(eraserSize, 0, 1.0);
        canvas.graphics.lineTo(point.x, point.y);
        flush(BlendMode.ERASE);
        canvas.graphics.moveTo(point.x, point.y);
    }

    public function flush(blendMode:String = null):void {
                    //draw temporary vectors to bitmap
        bitmap.draw(canvas, downMatrix, null, blendMode, null, true);
                    //update board
        var bounds:Rectangle = canvas.getBounds(this);
        with (graphics) {
            beginBitmapFill(bitmap, upMatrix);
            drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
            endFill();
        }
                    //erase temporary vectors
        canvas.graphics.clear();
    }
}
0 голосов
/ 22 октября 2010

Вы можете оптимизировать это, проверив в начале метода, являются ли lastKnownPoint.x и lastKnownPoint.y одинаковыми значениями или в пределах определенного расстояния (возможно, 2 или 3 пикселя). Если они есть, вы просто возвращаетесь, ничего не делая. Поэкспериментируйте и найдите расстояние, на котором вы получите хороший баланс между производительностью и плавностью линии.

0 голосов
/ 22 октября 2010

Во время рисования вы заметите, что кривые больше не являются резкими ... и они будут состоять из больших и больших линий. Обходной путь - не создавать миллионы маленьких строк и добавлять их как дочерние, а записывать их в один и тот же контейнер, используя copyBitmapData.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...