Multilayer Canvas Goes Beyond the Bootstrap Mesh

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> <!-- /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 };  
}

# 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>
    <!-- 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 - , .

, , . . Two columns side by side Two columns sewn with one narrow layout.

: - , , ?

: 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>
        <!-- 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%;
}

?

+4

Source: https://habr.com/ru/post/1684499/


All Articles