在HTML上绘制画布并在屏幕大小上保留Aspect

时间:2017-01-21 13:12:43

标签: javascript html css css3 canvas

背景

这是一个非常难的问题,我现在已经苦苦挣扎了几天。我试图以幻灯片格式显示课程。所以课程由不同的幻灯片组成。现在覆盖在每张幻灯片的顶部的是一个适合屏幕大小的画布元素。

canvas.width  = document.body.clientWidth;
canvas.height = document.body.clientHeight;

这允许教师在画布上绘制笔记并突出显示课程的各个部分。

问题

幻灯片的内容由HTML组成,加载幻灯片时看起来像这样。

当我调整页面大小时......

enter image description here

所以这里的问题是画布'图像'根据CSS页面的宽高比调整大小。

#theCanvas {
    position:fixed;
    top:0;
    right:0;
    bottom:0;
    left:0;
}

但实际的HTML保持相同的大小,但重新排列其换行点,不好。

我尝试过什么

首先,我使用CSS根据窗口的宽度和高度调整所有HTML元素的大小:

h1 {
    font-family: 'Open Sans Condensed', sans-serif;
    color: #222222;
    font-weight: 200;
    font-size: 5.9vw;
}

h2 {
    font-family: 'Open Sans Condensed', sans-serif;
    color: #222222;
    font-weight: 200;
    font-size: 3.0vh;
}

h4 {
    font-family: 'Open Sans Condensed', sans-serif;
    color: #444444;
    font-weight: 200;
    font-size: 2vmin;
}

p {
    font-family: 'Open Sans Condensed';
    font-size: 2vmin;
    font-weight: 200;
}

接下来我使用以下方法保存并调整画布图像的大小:

window.onresize = function(event) {

    var data = canvas.toDataURL();

    // resize the canvas
    canvas.width = document.body.clientWidth;
    canvas.height = document.body.clientHeight;
    //alert($(container).width());

    // scale and redraw the canvas content
    var img=new Image();

    img.width = document.body.clientWidth;
    img.height = document.body.clientHeight;

    img.onload=function(){
        context.drawImage(img,0,0,img.width,img.height);
    }
    img.src=data;

};

全屏(1920px宽度)的结果

enter image description here

单击调整大小窗口按钮(1200px)

enter image description here

非常接近。

问题

现在当我拖动窗口的一角来调整大小时:

enter image description here

问题

1 - 当我手动调整窗口角落时,为什么window.onresize函数不会触发?

(奖金问题)我是否以正确的方式解决这个问题,或者是否需要在HTML元素上覆盖画布以进行交互式课程的麻烦呢?

2 个答案:

答案 0 :(得分:7)

我想我误解了你的问题。

如果您希望手绘内容与html元素匹配,那么您需要确保HTML元素永远不会更改布局并始终保持相同的相对大小。在您的示例中,已经 NOT 的情况。你已经得到了这个" 25m"在左上方"欢迎"在中间,当你将页面拖得更高时,这2个元素的分离量与元素的其他大小不成比例,所以你已经要求的东西基本上不可能了。

您可以将SVG用于所有文本,这样就可以将其缩放到任意大小,而普通HTML文本也可以。换句话说,如果你使用SVG使页面变得非常高大,你会得到高而细的文本,所有的位置和大小都与原始位置和大小成正比,而HTML的文本也不会拉伸,你将大小设置为vh的各种设置,但这只是意味着浏览器将选择大小,而不是按比例缩放文本。

示例:原始所需显示

enter image description here

将窗口更改为高大(font-size: 10vh;

enter image description here

请注意,字体未拉伸,因此相对尺寸和距离为" 25m"和欢迎"不再匹配

使用preserveAspectRatio="none"

对SVG执行相同操作

enter image description here

现在请注意" 25m"和#34;欢迎"也高大瘦弱。这意味着如果你在画布上画了两个框,那么在缩放后两个框仍然会匹配。没有那些东西是不匹配的。

以上是

的HTML版本



body { margin: 0; }
.center {
  position: absolute;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20vh;
}

<div id="time">25m</div>
<div class="center">
  <div>Welcome</div>
</div>
&#13;
&#13;
&#13;

和SVG版本

&#13;
&#13;
body { margin: 0; }
#foo {
  width: 100vw;
  height: 100vh;
  display: block;
}
&#13;
<svg 
     id="foo" 
     width="100%" 
     height="100%" 
     viewBox="0 0 640 480" 
     version="1.1" 
     xmlns="http://www.w3.org/2000/svg" 
     preserveAspectRatio="none" 
     xmlns:xlink="http://www.w3.org/1999/xlink" 
     xml:space="preserve" 
     style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
    <text x="187px" y="240px" style="font-family:'ArialMT', 'Arial', sans-serif;font-size:64px;">W<tspan x="246px 282px " y="240px 240.084px ">el</tspan>come</text>
    <text x="19px" y="35px" style="font-family:'ArialMT', 'Arial', sans-serif;font-size:16px;">25m</text>
</svg>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您可以在没有任何调整大小事件的情况下响应画布。当你需要在画布上绘制某些东西时,你需要将一个点从窗口坐标转换为画布坐标。

#theCanvas {
   max-width: 100%;
   height: auto;
}

#theCanvas {
   max-height: 100%;
   width: auto;
}

=============================================== ============================

 var actualCanvasSize = canvas.getBoundingClientRect();
 var initialCanvasSize = {width:canvas.width, height:canvas.height};

你怎么看?

但是如果你想通过调整大小事件来做到这一点。有一个用于检测HTML元素调整大小的库。这个lib使用了一些css3技巧和窍门。并且工作完美,它更有用,可以通过窗口调整大小来解决您的问题。但是您需要将画布放在div中,然后将调整大小的侦听器附加到div。 github.com/sdecima/javascript-detect-element-resize