分层画布延伸到Bootstrap网格

时间:2017-08-25 20:26:09

标签: html css twitter-bootstrap meteor meteor-blaze

我想我对自己的问题有一个答案。它似乎有效但对我来说似乎是一个 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应用程序做到这一点。一些互联网智慧表明它还不可能,但如果我错了,请告诉我。

要重现,以下步骤应该足够了:

  1. 创建应用:meteor create canvas_size
  2. 添加Bootstrap:meteor add twbs:bootstrap
  3. 编辑代码:使用下面显示的代码或在此DropBox文件夹中替换客户端目录中生成的文件的内容:https://www.dropbox.com/sh/us4sjgycgyc44od/AADvjRreH5RfV3mldv9nKfHOa?dl=0
  4. 运行meteor:meteor
  5. 守则 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 sideTwo columns forced into one by 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%;
    }
    

    思考?

0 个答案:

没有答案