在Handlebars模板中使用画布?

时间:2013-09-26 00:45:51

标签: jquery canvas handlebars.js

<canvas>绘图插入手柄模板的最佳方法是什么?请参阅以下示例。我的第一次尝试是canvas-inline辅助函数,它使用JavaScsript创建一个canvas对象然后返回它。可悲的是,我在模板中看到的只是“[object HTMLCanvasElement]”。 Handlebars需要一个HTML文本字符串!

所以,我的第一个问题是:有没有办法将现成的DOM对象返回到Handlebars对象?如果没有,这是一个简单的黑客攻击,还是完全违背了Handlebars在引擎盖下工作的方式?

我的第二次尝试是canvas-timer辅助函数。这只返回一个<canvas>字符串,但随后使用100ms超时去添加画布内容。这很有效,但我不喜欢Fragility先生现在加入团队的事实(穿着他的“I Love Magic Numbers”T恤)。

所以,如果前两个问题的答案是“不”和“否”,是否有一种很好的方法来使用后一种方法,但摆脱计时器和任意100ms的猜测?即所以Javascript代码将在<canvas>元素出现时运行,而不是之前,而不是之后。注意:我想要一些封装在辅助函数中的东西。

在这里小提琴:http://jsfiddle.net/HCQSt/

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Handlebars: canvas test</title>
<script src="js/jquery-1.10.2.js"></script>
<script src="js/handlebars.js"></script>

<!--- ******************** TEMPLATES ********************  -->

<script id="test-template" type="text/x-handlebars-template">
<h3>Hello {{world}}</h3>
{{{canvas-inline col}}}
{{{canvas-timer col}}}
</script>

<!--- ******************** ************ ********************  -->

<script language="javascript">
Handlebars.registerHelper("canvas-inline", function(col) {
var canvas  = document.createElement('canvas');
if(canvas){
    console.log(canvas);
    canvas.width=128;canvas.height=128;
    var ctx = canvas.getContext('2d');
    ctx.fillStyle = col;
    ctx.fillRect(0,80,128,16);
    ctx.fillRect(16,0,32,32);
    ctx.fillRect(80,0,32,32);
    }
else console.log("no canvas object");
return canvas;
});

Handlebars.registerHelper("canvas-timer", function(col) {
setTimeout(function(){
    //var canvas    = document.createElement('canvas');
    var canvas  = $('#xxx')[0];
    if(canvas){
        console.log(canvas);
        canvas.width=128;canvas.height=128;
        var ctx = canvas.getContext('2d');
        ctx.fillStyle = col;
        ctx.fillRect(0,80,128,16);
        ctx.fillRect(16,0,32,32);
        ctx.fillRect(80,0,32,32);
        }
    else console.log("no canvas object");
    },100);
return '<canvas id="xxx"></canvas>';
});


var T=Handlebars.compile ( $("#test-template").html() );

$(function(){   //onReady
var obj={ world:"Blue-Green Planet", col:"#f33" };
$('<div class="view" id="test1">').append(T(obj)).appendTo('#views');
});
</script>

</head>
<body>
<h1>Handlebars: canvas test</h1>

<div id="views"></div>

</body>
</html>

P.S。如果您的问题是“为什么要这样做?”,我的回答是“QR码”。提供给模板的URL的QR码。 (在这种特殊情况下,我有一个表格解决方法,但我确信情况并非总是如此。)

1 个答案:

答案 0 :(得分:4)

帮助程序主要用于生成视图中的内容,因此在触发帮助程序时,这是在视图插入页面之前。当您的助手依赖于现有的视图元素时,您会遇到计时问题。 (因此你的魔法超时工作的原因)。

替代方法是使用图像而不是画布,让助手生成数据网址。

小提琴:http://jsfiddle.net/gwwar/L7TqJ/2/

<script id="test-template" type="text/x-handlebars-template">
    <h3>Hello {{world}}</h3>
    <img src="{{{generateQRCode col}}}"/>
</script>


Handlebars.registerHelper("generateQRCode", function (col) {
    var canvas = window.document.createElement("canvas");
    canvas.width = 128;
    canvas.height = 128;
    var ctx = canvas.getContext('2d');
    ctx.fillStyle = col;
    ctx.fillRect(0, 80, 128, 16);
    ctx.fillRect(16, 0, 32, 32);
    ctx.fillRect(80, 0, 32, 32);
    return canvas.toDataURL();
});

var T = Handlebars.compile($("#test-template").html());

$(function () { //onReady
    var obj = {
        world: "Blue-Green Planet",
        col: "green"
    };
    $('<div class="view" id="test1">').append(T(obj)).appendTo('#views');
});

认为这仍然太乱了?

您可能还想尝试使用ember,它使用把手作为视图图层,并在插入视图时触发事件。

编辑:我意识到我提出的一个解决方案可能会成为帮手。