我想我对自己的问题有一个答案。它似乎有效但对我来说似乎是一个 hack 。我担心黑客,因为他们有在错误的时间失败的习惯。
我很感谢对此问题的一些看法"解决方案"以及可能出现的问题。有关详细信息,请参阅下面的更新#2。
目标:我想在一个"框"中将三个画布叠加在一起。引导网格,以便我可以独立绘制每个画布。
问题:第一个画布(下面称为backgroundCanvas)适合网格框,但分层画布(middleCanvas和topCanvas)不适合。当我在不同角落和中心的画布上绘制X时,可以看到红色X(写入backgroundCanvas)适合自举框(有黑色边框)但黑色和白色Xs (分别写入middleCanvas和topCanvas)与右下角的框不匹配,它们的中心也不与背景的中心对齐。我在下面链接的图像中突出显示了绿色椭圆的这些问题区域 Screen Capture Showing Issue
可以在开发人员控制台日志中看到鼠标单击画布目标topCanvas并从中输出。这些确认正在检测网格框外部的topCanvas上的点击。
HTML使用position:relative作为第一个画布(适合的画布)和position:absolute作为其他画布(不合适)。这是我在开始将其移植到Meteor和Bootstrap之前在实际应用程序中分层画布的方式。更改其他画布也使用position:relative确实使它们适合网格,但它们不是分层的 - 它们是顺序的。
环境:这是使用Chrome的Windows 10上的Meteor应用程序。
复制:我将代码削减到生成和演示问题所需的最低限度。代码由main.html,main.css和main.js组成,它们插在下面。
为了重现这一点,我试图创建一个jsFiddle,但不知道如何为Meteor应用程序做到这一点。一些互联网智慧表明它还不可能,但如果我错了,请告诉我。
要重现,以下步骤应该足够了:
守则: main.html中
<head>
<title>Canvas Size</title>
</head>
<body>
<h1>Welcome to My Troubles</h1>
{{> theGrid}}
</body>
<template name="theGrid">
<div class="container">
<div class="row">
<div class="col-md-6" style="border: 1px solid black; ">
{{> sheet}}
</div> <!-- /col-md-6 -->
</div> <!-- /row -->
</div>
</template>
<template name="sheet">
<div id="sheetView" >
<!-- Overlap three canvasses. -->
{{>sheetBackground}}
{{>sheetMiddle}}
{{>sheetTop}}
</div>
</template>
<template name="sheetBackground">
<canvas id="backgroundCanvas" class="playingArea" style="z-index: 0; position:relative; left: 0px; top: 0px; " width="400" height="600" >
HTML 5 Canvas not supported by your browser.
</canvas>
</template>
<template name="sheetMiddle">
<canvas id="middleCanvas" class="playingArea" style="z-index: 1; position: absolute; left: 0px; top: 0px; " width="400" height="600">
HTML 5 Canvas not supported by your browser.
</canvas>
</template>
<template name="sheetTop">
<canvas id="topCanvas" class="playingArea" style="z-index: 2; position: absolute; left: 0px; top: 0px; " width="400" height="600">
HTML 5 Canvas not supported by your browser.
</canvas>
</template>
的main.css :
#backgroundCanvas {
background-color: lightgrey;
}
.playingArea, #sheetView {
width: 100%;
height: auto;
}
main.js :
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import './main.html';
// Render the backgroundCanvas when system signals onRendered.
// This only gets called when the thing is first rendered. Not when resized.
Template.sheetBackground.onRendered( function() {
let context = $( '#backgroundCanvas' )[0].getContext( "2d" );
drawX( context, 399, 1, 30, "red", 9 );
drawX( context, 200, 300, 30, "red", 15 );
drawX( context, 1, 599, 30, "red", 9 );
} );
Template.sheetMiddle.onRendered( function() {
let context = $( '#middleCanvas' )[0].getContext( "2d" );
drawX( context, 1, 1, 30, "black", 9 );
drawX( context, 200, 300, 30, "black", 9 );
drawX( context, 399, 599, 30, "black", 9 );
} );
Template.sheetTop.onRendered( function() {
let context = $( '#topCanvas' )[0].getContext( "2d" );
drawX( context, 1, 1, 24, "white", 3 );
drawX( context, 200, 300, 24, "white", 3 );
drawX( context, 399, 599, 24, "white", 3 );
} );
Template.sheetTop.events( {
'mousedown': function( event ) {
let canvasPos = windowPointToCanvasPoint( event.clientX, event.clientY, $( '#topCanvas' )[0] );
console.log( "sheet.js: mousedown: "
+ "clientXY=<" + event.clientX + "," + event.clientY + "> "
+ "canvasXY=<" + Math.floor(canvasPos.x) + "," + Math.floor(canvasPos.y) + "> "
);
},
} );
export function drawLine( context, startX, startY, endX, endY ) {
context.beginPath();
context.moveTo( startX, startY );
context.lineTo( endX, endY );
context.stroke();
context.closePath();
}
function drawX( context, centerX, centerY, size, colour, thickness ) {
context.save();
context.strokeStyle = colour;
context.lineWidth = thickness;
// Not correct. Total line length will actually be Math.hypot( size, size );
var lineLen = size / 2;
drawLine( context, centerX - lineLen, centerY - lineLen, centerX + lineLen, centerY + lineLen );
drawLine( context, centerX - lineLen, centerY + lineLen, centerX + lineLen, centerY - lineLen );
context.restore();
}
function windowPointToCanvasPoint( windowX, windowY, canvas ) {
var boundRect = canvas.getBoundingClientRect();
var canvasX = ( windowX - boundRect.left ) * ( canvas.width / boundRect.width );
var canvasY = ( windowY - boundRect.top ) * ( canvas.height / boundRect.height );
return { "x": canvasX, "y": canvasY };
}
我在这里阅读(https://css-tricks.com/absolute-positioning-inside-relative-positioning/),除非包含在具有相对定位的另一个元素中,否则绝对定位将元素相对于文档的主体定位。所以我修改了上面的一些HTML,为包含所有画布的div添加了相对定位,并将第一个画布更改为绝对定位。
<template name="sheet">
<div id="sheetView" style="position: relative; ">
<p>dummy text to force bootstrap row height to be more visible</p>
<!-- Overlap three canvasses. -->
{{>sheetBackground}}
{{>sheetMiddle}}
{{>sheetTop}}
</div>
</template>
<template name="sheetBackground">
<canvas id="backgroundCanvas" class="playingArea" style="z-index: 0; position: absolute; left: 0px; top: 0px; " width="400" height="600" >
HTML 5 Canvas not supported by your browser.
</canvas>
</template>
现在,至少,画布彼此对齐,并且随着列宽度因调整大小而缩小,画布缩小以适合列。
问题:引导行的高度不适应画布。它(可能)高1px。为了使这一点更加明显,我添加了一些虚拟文本(参见上面的HTML),它至少强制行高度为1段 - 现在你可以看到不在画布周围的边框。
如果我在行中添加第二列,当我调整到小屏幕尺寸时,第二列与画布重叠而不是在下面。请参阅和。
问题:我可以用某种方式强制行高,还是比我在这里尝试更好的解决方案?
代码:我已将包含新HTML的代码放入此Dropbox文件夹:https://www.dropbox.com/sh/bduhc8cjgjtile4/AAA7C41nSbJ9qtVNqizF1wx0a?dl=0。我没有为此更新更改.js或.css。
我可以通过在与重叠画布相同的行/列框中插入一个段落来控制Bootstrap行的高度。画布仍然绝对定位,但段落高度控制为与画布高度相同。
修改后代码的片段就在这里。请注意顶部附近的HTML段落以及相应的CSS更改。
main.html中
<template name="sheet">
<div id="sheetView" style="position: relative; ">
<p id="hackyHeightPara">Dummy text allowing CSS to force bootstrap row height.</p>
<!-- Overlap three canvasses. -->
{{>sheetBackground}}
{{>sheetMiddle}}
{{>sheetTop}}
</div>
</template>
<template name="sheetBackground">
<canvas id="backgroundCanvas" class="playingArea" style="z-index: 0; position: absolute; left: 0px; top: 0px; " width="400" height="600" >
HTML 5 Canvas not supported by your browser.
</canvas>
</template>
的main.css
#hackyHeightPara {
height: 525px; /* Set to control row height */
}
.playingArea, #sheetView {
width: auto; /* Swapped from width:100% and height:auto */
height: 100%;
}
思考?