两个 html 画布在浏览器 window 上水平居中
Two html canvases on top of each other centered horizontally on browser window
我试图在彼此之上使用两个 html5 canvas 对象,以便将其中一个用作静态背景,将另一个用作所有动作发生。
目的是背景比前景大canvas,而且是静态图片,所以把背景投影一次,不用一直渲染,这样可以节省资源。
我希望这两个对象始终水平居中于浏览器 window 的中心(即使 window 已调整大小),我需要一些帮助 CSS.目前这两个 canvas 高度相同但宽度不同。
让我指出,每次浏览器 window 调整大小时,canvases 都会调整大小(按高度缩放),因此场景的垂直方向上没有任何部分 clipped/cropped,但横向上,没有这样的限制。
因此,当浏览器 window 的宽度小于 canvases 时,它们会按比例左右裁剪,并保持在页面中间居中。
我的代码几乎完成了,因为它缩放所有对象并根据浏览器 window 大小裁剪场景,但我找不到将 canvases 水平居中的方法。
如果你想在 JS Bin 中测试代码,我建议选择实时预览模式(单击最右边的箭头按钮)以全屏查看结果,然后使用 window尺寸。
下面是当前输出和所需输出的可视化结果
提前致谢!
下面的作品,我在下面包含了一个片段实现。
canvas#front, canvas#back {
position: absolute;
/* Use calc to make sure that browser without transform support
* (that therefore also dont support calc) don't
* actually move your elements. */
left: calc(50%);
top: calc(50%);
/* Don't forget to prefix. */
transform: translate(-50%,-50%);
z-index: 1;
}
canvas#back { z-index: 0; }
document.documentElement.style.overflow = 'hidden';
window.addEventListener('resize', function(){resizeCanvas();}, true);
var sscale = 1.0;
canvas_back = document.getElementById("canvas_back");
stage2 = new createjs.Stage(canvas_back);
stage2.autoClear = true;
my_ticker2 = createjs.Ticker.on("tick",stage2);
this.back = new createjs.Bitmap("http://i.imgur.com/VcDqpBW.png");
stage2.addChild(this.back);
canvas_front = document.getElementById("canvas_front");
stage = new createjs.Stage(canvas_front);
stage.autoClear = true;
createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED; createjs.Ticker.framerate = 120;
my_ticker = createjs.Ticker.on("tick",stage);
this.ob1 = new createjs.Bitmap("http://i.imgur.com/3toyiJo.png");
this.ob1.x=Math.floor(canvas_front.width/2);
this.ob1.y = Math.floor(canvas_front.height/2);
stage.addChild(this.ob1);
resizeCanvas();
function resizeCanvas()
{
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;//window.screen.availHeight;
console.log("SCREEN_WIDTH, SCREEN_HEIGHT, canvas_back.height", SCREEN_WIDTH, SCREEN_HEIGHT, canvas_back.height);
ratio = (SCREEN_HEIGHT/canvas_back.height);
sscale = (sscale*ratio); console.log("ratio,sscale : ", ratio,sscale);
stage.scaleX = sscale;
stage.scaleY = sscale;
canvas_back.width = Math.min(canvas_back.width*ratio);
canvas_back.height = Math.min(canvas_back.height*ratio);
console.log("canvas width/height : " , canvas_back.width, canvas_back.height);
stage2.scaleX = sscale;
stage2.scaleY = sscale;
canvas_front.width = Math.min(canvas_front.width*ratio);
canvas_front.height = Math.min(canvas_front.height*ratio);
/*if(canvas_back.width > SCREEN_WIDTH)
{ */
console.log("canvas width bigger than screen width");
document.documentElement.scrollLeft = ((document.body.scrollWidth - document.body.clientWidth) / 2);
document.body.scrollLeft = ((document.body.scrollWidth - document.body.clientWidth) / 2);
/*}*/
}
*{
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
#canvas_back, #canvas_front {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script type="text/javascript" src="https://code.createjs.com/createjs-2015.05.21.min.js"></script>
</head>
<body>
<canvas id="canvas_back" height="256" width="512"> asdf </canvas>
<canvas id="canvas_front" height="256" width="384"> asdf </canvas>
</body>
</html>
请记住,我还高度简化了您的 HTML 以仅包含 canvasses,这是为了避免任何混淆,但该技术应该有效。 Lastyle,在定义width
和height
时,只能以%
为单位,否则直接使用数字,因为它会自动使用pixels
。它看起来更干净。
就像@Rvervuurt 所说的那样,如果它不使用 canvas
的任何功能,您不妨将其绘制为静态图像并将其渲染为背景图像,以 [=22= 为中心] - 覆盖代码仍然有效,但您的页面会更活泼一些,因为根本没有 canvas 可跟踪。
更新:使用<img />
and/orbackground-image
下面是使用简单图像或背景图像的实现。我稍微简化了您的代码(将 canvas 简单地绘制成一个正方形,以使所有内容尽可能明显)。
var cf = document.getElementById('canvas_front');
cf.width = 100;
cf.height = 100;
var ctx = cf.getContext('2d');
ctx.rect(0,0,100,100);
ctx.stroke();
* { margin: 0;padding: 0; }
html, body { height: 100%; }
#canvas_front, #img_back {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
z-index: 2;
}
#canvas_back { display: none; }
#img_back { z-index: 1; }
#bg_back {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: yellow;
background-position: 50% 50%;
background-size: cover;
z-index: 0;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="bg_back" style='background-image: url(https://placeholdit.imgix.net/~text?txtsize=75&bg=880000&txtclr=green&txt=1000×1000&w=1000&h=1000);'></div>
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=A+Large+Background&w=1000&h=800" id="img_back" height="256" width="512" />
<canvas id="canvas_front" height="256" width="384"></canvas>
</body>
</html>
我试图在彼此之上使用两个 html5 canvas 对象,以便将其中一个用作静态背景,将另一个用作所有动作发生。
目的是背景比前景大canvas,而且是静态图片,所以把背景投影一次,不用一直渲染,这样可以节省资源。
我希望这两个对象始终水平居中于浏览器 window 的中心(即使 window 已调整大小),我需要一些帮助 CSS.目前这两个 canvas 高度相同但宽度不同。
让我指出,每次浏览器 window 调整大小时,canvases 都会调整大小(按高度缩放),因此场景的垂直方向上没有任何部分 clipped/cropped,但横向上,没有这样的限制。 因此,当浏览器 window 的宽度小于 canvases 时,它们会按比例左右裁剪,并保持在页面中间居中。
我的代码几乎完成了,因为它缩放所有对象并根据浏览器 window 大小裁剪场景,但我找不到将 canvases 水平居中的方法。
如果你想在 JS Bin 中测试代码,我建议选择实时预览模式(单击最右边的箭头按钮)以全屏查看结果,然后使用 window尺寸。
下面是当前输出和所需输出的可视化结果
提前致谢!
下面的作品,我在下面包含了一个片段实现。
canvas#front, canvas#back {
position: absolute;
/* Use calc to make sure that browser without transform support
* (that therefore also dont support calc) don't
* actually move your elements. */
left: calc(50%);
top: calc(50%);
/* Don't forget to prefix. */
transform: translate(-50%,-50%);
z-index: 1;
}
canvas#back { z-index: 0; }
document.documentElement.style.overflow = 'hidden';
window.addEventListener('resize', function(){resizeCanvas();}, true);
var sscale = 1.0;
canvas_back = document.getElementById("canvas_back");
stage2 = new createjs.Stage(canvas_back);
stage2.autoClear = true;
my_ticker2 = createjs.Ticker.on("tick",stage2);
this.back = new createjs.Bitmap("http://i.imgur.com/VcDqpBW.png");
stage2.addChild(this.back);
canvas_front = document.getElementById("canvas_front");
stage = new createjs.Stage(canvas_front);
stage.autoClear = true;
createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED; createjs.Ticker.framerate = 120;
my_ticker = createjs.Ticker.on("tick",stage);
this.ob1 = new createjs.Bitmap("http://i.imgur.com/3toyiJo.png");
this.ob1.x=Math.floor(canvas_front.width/2);
this.ob1.y = Math.floor(canvas_front.height/2);
stage.addChild(this.ob1);
resizeCanvas();
function resizeCanvas()
{
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;//window.screen.availHeight;
console.log("SCREEN_WIDTH, SCREEN_HEIGHT, canvas_back.height", SCREEN_WIDTH, SCREEN_HEIGHT, canvas_back.height);
ratio = (SCREEN_HEIGHT/canvas_back.height);
sscale = (sscale*ratio); console.log("ratio,sscale : ", ratio,sscale);
stage.scaleX = sscale;
stage.scaleY = sscale;
canvas_back.width = Math.min(canvas_back.width*ratio);
canvas_back.height = Math.min(canvas_back.height*ratio);
console.log("canvas width/height : " , canvas_back.width, canvas_back.height);
stage2.scaleX = sscale;
stage2.scaleY = sscale;
canvas_front.width = Math.min(canvas_front.width*ratio);
canvas_front.height = Math.min(canvas_front.height*ratio);
/*if(canvas_back.width > SCREEN_WIDTH)
{ */
console.log("canvas width bigger than screen width");
document.documentElement.scrollLeft = ((document.body.scrollWidth - document.body.clientWidth) / 2);
document.body.scrollLeft = ((document.body.scrollWidth - document.body.clientWidth) / 2);
/*}*/
}
*{
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
#canvas_back, #canvas_front {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script type="text/javascript" src="https://code.createjs.com/createjs-2015.05.21.min.js"></script>
</head>
<body>
<canvas id="canvas_back" height="256" width="512"> asdf </canvas>
<canvas id="canvas_front" height="256" width="384"> asdf </canvas>
</body>
</html>
请记住,我还高度简化了您的 HTML 以仅包含 canvasses,这是为了避免任何混淆,但该技术应该有效。 Lastyle,在定义width
和height
时,只能以%
为单位,否则直接使用数字,因为它会自动使用pixels
。它看起来更干净。
就像@Rvervuurt 所说的那样,如果它不使用 canvas
的任何功能,您不妨将其绘制为静态图像并将其渲染为背景图像,以 [=22= 为中心] - 覆盖代码仍然有效,但您的页面会更活泼一些,因为根本没有 canvas 可跟踪。
更新:使用<img />
and/orbackground-image
下面是使用简单图像或背景图像的实现。我稍微简化了您的代码(将 canvas 简单地绘制成一个正方形,以使所有内容尽可能明显)。
var cf = document.getElementById('canvas_front');
cf.width = 100;
cf.height = 100;
var ctx = cf.getContext('2d');
ctx.rect(0,0,100,100);
ctx.stroke();
* { margin: 0;padding: 0; }
html, body { height: 100%; }
#canvas_front, #img_back {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
z-index: 2;
}
#canvas_back { display: none; }
#img_back { z-index: 1; }
#bg_back {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: yellow;
background-position: 50% 50%;
background-size: cover;
z-index: 0;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="bg_back" style='background-image: url(https://placeholdit.imgix.net/~text?txtsize=75&bg=880000&txtclr=green&txt=1000×1000&w=1000&h=1000);'></div>
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=A+Large+Background&w=1000&h=800" id="img_back" height="256" width="512" />
<canvas id="canvas_front" height="256" width="384"></canvas>
</body>
</html>