Ако преоразмеря своето платно, моят createJS текст става размазан

Използвам createJS за рисуване вътре в платното. Моето платно е настроено да заема прозореца на браузъра, поддържайки пропорциите с помощта на функцията resize().

Това е кодът:

    mytext = new createjs.Text("Lorem ipsum dolor sit amet 2","19px Calibri","#073949");
    mytext.x = 450
    mytext.y = 300;
    stage.addChild(mytext);  

    resize = function() {
                var canvas = document.getElementById('canvas');
                var canvasRatio = canvas.height / canvas.width;

                var windowRatio = window.innerHeight / window.innerWidth;
                var width;
                var height;

                if (windowRatio < canvasRatio) {
                    height = window.innerHeight - 35;
                    width = height / canvasRatio;
                } else {
                    width = window.innerWidth;
                    height = width * canvasRatio;
                }

                canvas.style.width = width + 'px';
                canvas.style.height = height + 'px';    
    }()

Това, което се случва, е, че текстът се размазва (намаляване на качеството), когато платното се преоразмерява.

http://i.imgur.com/RQOSajs.png срещу http://i.imgur.com/Xwhf5c5.png

Как мога да разреша този проблем?


person Condward    schedule 28.09.2015    source източник
comment
Бихте ли могли да съхраните размера на оригиналното платно width и height, след което в зависимост от преоразмеряването да изчислите новите мащаби, след което да преначертаете всички елементи правилно с новата ширина и височина? Например. оригинална ширина = 400 оригинална височина = 400, след преоразмеряване ширината вече е 800, а височината вече е 600. Стартирайте функцията за рисуване по този начин. `mytext.x = 400 * (canvas.width / originalWidth); след това направете същото за височината и размера на шрифта   -  person Canvas    schedule 28.09.2015
comment
Опитвах се да избегна това решение, защото вече създадох много игри с тонове текст и изображения и трябваше да създам функция за преоразмеряване за всяка игра и също така да компенсирам промяната на координатите. Но ако това е единственото решение, ще трябва да го приложа.   -  person Condward    schedule 28.09.2015


Отговори (5)


Тъй като използвате CreateJS, можете просто да преоразмерите платното и да мащабирате целия етап, за да преначертаете всичко в новия размер:

// just showing width to simplify the example:
var newWidth = 800;
var scale = newWidth/myCanvas.width;
myCanvas.width = newWidth;
myStage.scaleX = myStage.scaleY = scale;
myStage.update(); // draw at the new size.
person gskinner    schedule 30.09.2015

Отговорът на @Adam е правилен, що се отнася до мащабирането на платното. Вие НЕ искате да мащабирате с CSS, тъй като той ще разтегне вашето платно, вместо да промени размерите му в пиксели. Вместо това задайте ширината и височината на платното, като използвате JavaScript.

stage.canvas.width = window.innerWidth;
stage.canvas.height = window.innerHeight;

Както посочихте в коментара си, това ще промени само размера на платното, а не ще препозиционира или мащабира вашето съдържание. Ще трябва да направите това ръчно. Това е доста просто. Като цяло препоръчвам да поставите вашия слушател за „преоразмеряване“ в JavaScript във вашия HTML файл, а не в рамков скрипт.


Първо определете мащаба въз основа на размера на прозореца и размера на вашето съдържание. Можете да използвате exportRoot.nominalBounds.width и exportRoot.nominalBounds.height, които са границите на първия кадър. Ако искате да мащабирате нещо друго, използвайте неговото nominalBounds вместо това.

Имайте предвид, че nominalBounds се добавя към всички филмови клипове, експортирани от Flash/Animate. Ако активирате граници на няколко кадъра и искате да ги използвате, ще трябва да промените подхода си.

Основната идея е да използвате оригиналния, немащабиран размер на вашето съдържание.

var bounds = exportRoot.nominalBounds;
// Uses the larger of the width or height. This will "fill" the viewport.
// Change to Math.min to "fit" instead.
var scale = Math.max(window.innerWidth / bounds.width, window.innerHeight / bounds.height);
exportRoot.scaleX = exportRoot.scaleY = scale;

След това можете да го центрирате, ако искате.

exportRoot.x = *window.innerWidth - bounds.width*scale)/2;
exportRoot.y = *window.innerHeight - bounds.height*scale)/2;

Ето кратка проба на адаптивно платно, използващо проста форма като съдържание за мащабиране: http://jsfiddle.net/lannymcnie/4yy08pax/

Правене на това с експортиране на Flash/Animate CC се е случвало няколко пъти, така че е в списъка ми с бъдещи демонстрации на EaselJS, които да включа в createjs. com и в EaselJS GitHub.

Надявам се това да помогне.

person Lanny    schedule 29.09.2015
comment
Използвах вашия подход exportRoot, но той мащабира само обектите, които са били поставени на екрана във Flash CC, всички обекти, които добавям с stage.addChild() не мащабират. - person Condward; 29.09.2015
comment
Да, ще трябва да мащабирате и позиционирате всички обекти, които искате да бъдат засегнати. Ако просто се насочите към exportRoot, това ще мащабира само exportRoot. Моята препоръка е да поставите всички деца в контейнер на сцената и да го мащабирате/позиционирате. - person Lanny; 29.09.2015
comment
Сега имам нов проблем. Преоразмеряването с активен tween ще го прецака. - person Condward; 30.09.2015

Разгледайте моя jsfiddle: https://jsfiddle.net/CanvasCode/ecr7o551/1/

По принцип просто съхранявате оригиналния размер на платното и след това го използвате, за да изработите нови позиции и размери

html

<canvas id="canvas" width="400" height="400">
    Canvas was unable to start up.
</canvas>

<button onclick="resize()">Click me</button>

javascript

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

var originalWidth = canvas.width;
var originalHeight = canvas.height;

render = function()
{
    context.fillStyle = "#DDD";
    context.fillRect(0,0, originalWidth * (canvas.width / originalWidth), originalHeight * (canvas.height / originalHeight));

    context.fillStyle = "#000";
    var fontSize = 48 * (canvas.width / originalWidth);
    context.font = fontSize+"px serif";
    context.fillText("Hello world", 100 * (canvas.width / originalWidth), 200 * (canvas.height / originalHeight));   
}

resize = function()
{
    canvas.width = 800;
    canvas.height = 600;
    render();
}

render();
person Canvas    schedule 28.09.2015
comment
Ще използвам вашия отговор като решение. Ще бъде много сложно да се приложи в моята ситуация, но мисля, че това е единственият вариант, който имам. - person Condward; 28.09.2015
comment
Да, ако трябва да го внедрите в средата на изграждането или в края, това може да причини някои проблеми, но сега знаете и знанието е половината от битката :) - person Canvas; 28.09.2015

Елементът canvas HTML5 работи с два различни размера

  • Визуален размер на екрана, контролиран чрез CSS, както задавате с canvas.style.width/height
  • Размер на пикселния буфер за чертежа, контролиран чрез числови пикселни атрибути за ширина и височина на елемента canvas.

Браузърът ще разтегне буфера, за да пасне на размера на екрана, така че ако двете стойности не са в съотношение 1:1, текстът ще изглежда размазан.

Опитайте да добавите следните редове към вашия код

canvas.width = width;
canvas.height = height;   
person Adam    schedule 28.09.2015
comment
но след това текстът не се мащабира с платното. - person Condward; 28.09.2015
comment
Можете ли да публикувате самостоятелен пример, jsfiddle и т.н., за да мога да погледна по-добре... - person Adam; 28.09.2015
comment
Мисля, че няма да работи в Jsfiddle, защото използвам Adobe Flash за изграждане на HTML5 файла и използва библиотеките createJS и movieclip. Но целият код е тук: pastebin.com/xbYUi3ew - person Condward; 28.09.2015

Създадох функция за преоразмеряване на всички елементи на екрана след преоразмеряване на платното. Той запазва първоначалните координати и мащаби за елементите с оригинална ширина от 900 px и след това ги променя според текущото съотношение на ширината спрямо първоначалното съотношение на ширината. Текстът вече не е размазан/с лошо качество.

    resize = function() {
            var canvas = document.getElementById('canvas');
            var canvasRatio = canvas.height / canvas.width;

            var windowRatio = window.innerHeight / window.innerWidth;
            var width;
            var height;

            if (windowRatio < canvasRatio) {
                height = window.innerHeight;
                width = height / canvasRatio;
            } else {
                width = window.innerWidth;
                height = width * canvasRatio;
            }

            canvas.width = width;
            canvas.height = height;
            reziseElements();

        };


    reziseElements = function()
            {
                var canvrat = canvas.width / 900;

                 //Simplified
                stage.scaleX = stage.scaleY = canvrat;

                //Old Version
                /*for (i=0; i<stage.numChildren ;i++)
                {
                    currentChild = stage.getChildAt(i);

                    if (typeof currentChild.oscaleX == 'undefined')
                    {
                        currentChild.oscaleX = currentChild.scaleX;
                        currentChild.ox = currentChild.x;
                        currentChild.oy = currentChild.y;
                    }
                }   


                for (i=0; i<stage.numChildren ;i++)
                {
                    currentChild = stage.getChildAt(i);
                    currentChild.scaleX = currentChild.scaleY = currentChild.oscaleX * canvrat      
                    currentChild.x = currentChild.ox * canvrat
                    currentChild.y = currentChild.oy * canvrat
                }   */
            }
person Condward    schedule 28.09.2015
comment
Вместо да мащабирате всичките си елементи, поставете ги в контейнер и го мащабирайте. Ако използвате експортирането на Flash CC, трябва да можете просто да насочите към exportRoot, което създава. - person Lanny; 28.09.2015