I think I have an answer to my question. This seems to work, but it seems like a hack to me . I worry about hacks because they have a habit of failure at the wrong time.
I would be grateful for some opinions on this "solution" and possible problems. See Update No. 2 for details.
Original question
Purpose . I want to stack three canvases on top of each other in the same “drawer” of the bootstrap grid so that I can draw each canvas independently.
Problem . The first canvas (called backgroundCanvas below) is placed inside the grid field, but layered canvases (middleCanvas and topCanvas) do not. When I draw X on the canvases in different angles and in the center, I can see that the red Xs (written in backgroundCanvas) fits into the bot box (which has a black frame), but the black and white Xs (written in middleCanvas and topCanvas respectively) are not coincide with the field in the lower right corner and their centers align with the background. I highlighted these problem areas with green ellipses in the image below.
Screen capture showing problem
The mouse clicks on the canvas topCanvas target and the output from them can be seen in the log of the developer console. They confirm that clicks on the upper canvas outside the grid field are detected.
HTML : (, ) : ( ). , Meteor Bootstrap. , : , - .
. Meteor Windows 10 Chrome.
. , . 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>
</div>
</div>
</template>
<template name="sheet">
<div id="sheetView" >
{{>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';
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;
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 };
}
# 1:
(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>
{{>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 .
# 2:
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>
{{>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;
}
.playingArea, #sheetView {
width: auto;
height: 100%;
}
?