最后,为了绘制用户笔记,在onPaint()处理函数中,我们首先创建了一个新的路径,将其移动到最后的位置,然后我们从鼠标区域获得新的位置,在最后的位置与新的位置之间绘制直线,同时,将当前鼠标位置(也就是新的位置)设置为新的最后的位置。
从 HTML5 移植由于 QML 的Canvas对象由 HTML 5 的 canvas 标签借鉴而来,将 HTML 5 的 canvas 应用移植到 QMLCanvas也是相当容易。我们以 Mozilla 提供的繁华曲线页面为例,演示移植的过程。可以在这里看到该页面的运行结果。下面是 HTML 5 canvas 的脚本部分:
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); ctx.fillRect(0,0,300,300); for (var i=0;i<3;i++) { for (var j=0;j<3;j++) { ctx.save(); ctx.strokeStyle = "#9CFF00"; ctx.translate(50+j*100,50+i*100); drawSpirograph(ctx,20*(j+2)/(j+1),-8*(i+3)/(i+1),10); ctx.restore(); } } } function drawSpirograph(ctx,R,r,O){ var x1 = R-O; var y1 = 0; var i = 1; ctx.beginPath(); ctx.moveTo(x1,y1); do { if (i>20000) break; var x2 = (R+r)*Math.cos(i*Math.PI/72) - (r+O)*Math.cos(((R+r)/r)*(i*Math.PI/72)) var y2 = (R+r)*Math.sin(i*Math.PI/72) - (r+O)*Math.sin(((R+r)/r)*(i*Math.PI/72)) ctx.lineTo(x2,y2); x1 = x2; y1 = y2; i++; } while (x2 != R-O && y2 != 0 ); ctx.stroke(); } draw();这里我们只解释如何进行移植,有关繁花曲线的算法则不在我们的阐述范围之内。幸运的是,我们需要改变的代码很少,因而这里也会很短。
HTML 按照顺序执行,draw() 会成为脚本的入口函数。但是在 QML 中,绘制必须在 onPaint 中完成,因此,我们需要将 draw() 函数的调用移至 onPaint。通常我们会在 onPaint 中获取绘制上下文,因此,我们将给 draw() 函数添加一个参数,用于接受Context2D对象。事实上,这就是我们所有的修改。移植之后的 QML 如下所示:
import QtQuick 2.2 Canvas { id: root width: 300; height: 300 onPaint: { var ctx = getContext("2d"); draw(ctx); } function draw (ctx) { ctx.fillRect(0, 0, 300, 300); for (var i = 0; i < 3; i++) { for (var j = 0; j < 3; j++) { ctx.save(); ctx.strokeStyle = "#9CFF00"; ctx.translate(50 + j * 100, 50 + i * 100); drawSpirograph(ctx, 20 * (j + 2) / (j + 1), -8 * (i + 3) / (i + 1), 10); ctx.restore(); } } } function drawSpirograph (ctx, R, r, O) { var x1 = R - O; var y1 = 0; var i = 1; ctx.beginPath(); ctx.moveTo(x1, y1); do { if (i > 20000) break; var x2 = (R + r) * Math.cos(i * Math.PI / 72) - (r + O) * Math.cos(((R + r) / r) * (i * Math.PI / 72)) var y2 = (R + r) * Math.sin(i * Math.PI / 72) - (r + O) * Math.sin(((R + r) / r) * (i * Math.PI / 72)) ctx.lineTo(x2, y2); x1 = x2; y1 = y2; i++; } while (x2 != R-O && y2 != 0 ); ctx.stroke(); } }运行一下这段代码: