如果我调整画布大小,我的 createJS 文本会变得模糊

Posted

技术标签:

【中文标题】如果我调整画布大小,我的 createJS 文本会变得模糊【英文标题】:If I resize my canvas, my createJS text becames blurry 【发布时间】:2015-12-25 14:14:19 【问题描述】:

我正在使用 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

我该如何解决这个问题?

【问题讨论】:

您能否存储原始画布widthheight 的大小,然后根据调整大小计算新比例,然后按新的宽度和高度正确重绘所有元素?例如。原始宽度 = 400 原始高度 = 400,调整大小后宽度现在是 800,高度现在是 600。像这样运行绘图函数。 `mytext.x = 400 * (canvas.width / originalWidth);然后对高度和字体大小做同样的事情 我试图避免这种解决方案,因为我已经构建了许多包含大量文本和图像的游戏,我需要为每个游戏构建一个调整大小的函数,并弥补坐标的变化。但如果这是唯一的解决方案,我将不得不应用它。 【参考方案1】:

就缩放画布而言,@Adam 的回答是正确的。您确实想要使用 CSS 进行缩放,因为它会拉伸您的画布而不是更改其像素尺寸。改为使用 javascript 设置画布的宽度和高度。

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

正如您在评论中所说,这只会更改画布大小,不会重新定位或缩放您的内容。您必须手动执行此操作。这相当简单。通常,我建议将“调整大小”侦听器放在 html 文件中的 JavaScript 中,而不是放在框架脚本中。


首先,根据窗口大小和内容大小确定比例。您可以使用exportRoot.nominalBounds.widthexportRoot.nominalBounds.height,这是第一帧的边界。如果您想扩展其他内容,请改用其nominalBounds

请注意,nominalBounds 会附加到从 Flash/Animate 导出的所有 MovieClips。如果你启用了多帧边界,并且想要使用它们,你将不得不修改你的方法。

主要思想是使用原始的、未缩放的内容大小。

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。

我希望这会有所帮助。

【讨论】:

我使用了您的 exportRoot 方法,但它仅缩放 Flash CC 中放置在屏幕上的对象,我使用 stage.addChild() 添加的所有对象都无法缩放。跨度> 是的,您必须缩放和定位您想要受影响的任何对象。如果您只针对 exportRoot,它只会缩放 exportRoot。我的建议是将所有孩子放在舞台上的容器中,并对其进行缩放/定位。 现在我有一个新问题。使用活动补间调整大小会搞砸。【参考方案2】:

由于您使用的是 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.

【讨论】:

【参考方案3】:

看看我的 jsfiddle:https://jsfiddle.net/CanvasCode/ecr7o551/1/

基本上,您只需存储原始画布大小,然后使用它来计算新的位置和大小

html

<canvas id="canvas"  >
    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();

【讨论】:

我将使用您的答案作为解决方案。在我的情况下实施起来会非常复杂,但我认为这是我唯一的选择。 是的,如果你必须在构建过程中或最后实现它,它可能会导致一些问题,但是现在你知道并且知道是成功的一半:)【参考方案4】:

HTML5 画布元素适用于两种不同的尺寸

屏幕上的视觉大小,通过 CSS 控制,就像您使用 canvas.style.width/height 设置一样 绘图的像素缓冲区大小,通过画布元素上的数字宽度和高度像素属性进行控制。

浏览器会拉伸缓冲区以适应屏幕大小,因此如果这两个值不是 1:1 的比例,文本会显得模糊。

尝试将以下几行添加到您的代码中

canvas.width = width;
canvas.height = height;   

【讨论】:

但文本不会随画布缩放。 你能发布自包含的例子,jsfiddle等,所以我可以更好地看看...... 它认为它在 Jsfiddle 中不起作用,因为我使用 Adob​​e Flash 构建 HTML5 文件,并且它使用 createJS 和movieclip 库。但整个代码在这里:pastebin.com/xbYUi3ew【参考方案5】:

我创建了一个函数来在调整画布大小后调整屏幕上所有元素的大小。它保存原始宽度为 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
                   */
            

【讨论】:

与其缩放所有元素,不如将它们放入容器中并对其进行缩放。如果您使用的是 Flash CC 导出,您应该能够只定位它创建的 exportRoot

以上是关于如果我调整画布大小,我的 createJS 文本会变得模糊的主要内容,如果未能解决你的问题,请参考以下文章

将 html 画布大小调整为所有可用宽度并向下调整到底部

在 UITableview 内的自动调整大小的标签上设置非常长的文本会破坏 NSLayoutConstraint

更改文本画布大小

如何使用 CreateJS 在画布上居中图像

我应该如何使用 createJs 创建响应式画布以适应不同的移动设备屏幕?

Chart.js画布调整大小