我想创建一个实现虚拟HTML5 Canvas的jQuery插件,即一个物理上不比它在页面上显示的画布大(或不大)。但是要在画布上显示的内容可能比画布大很多倍,并且会根据滚动条动态地重新绘制。
您会认为这是非常常见的功能,但到目前为止,我还无法使用jQuery插件或其他方式找到示例。这非常类似于例如SlickGrid用于Div,除了这是Canvas。我可以想到两个解决方案:
使用jQuery UI Slider将滚动条实现为完全独立的元素,并使用其事件来控制Canvas重绘。
做SlickGrid为Div做的任何事情。它似乎使Div略大于显示的内容,并且可以滚动事件来动态地向Div添加/删除元素。但是我无法看到它如何修改滚动条以使其看起来好像在Div中有更多当前正在显示的内容。
你会推荐什么?我们非常感谢示例代码。
答案 0 :(得分:5)
我挖掘了SlickGrid代码并使用了方法2)(某种程度) - 这就像我想到的那样:
/*
jensk@migselv.com
Simple virtual CANVAS controlled by a native scrollbar made with two DIVs
Uses jCanvas by Caleb Evans (http://calebevans.me/projects/jcanvas/index.php)
Thanks to Michael Leibman of SlickGrid fame for ideas.
Still need to clean it up (get rid of hardcoded values) and make it a nice, configurable
jQuery component.
Currently also redraws the entire canvas on each scroll event. Could be optimized to
do real browser scrolling and only redrawing the needed parts.
Another gotcha is that since it is the zero width DIVs that causes the scroll events,
mouse wheel, trackpad, touchscreen etc. scrolling over the Canvas will not work - only
the scrollbar is active. To solve this, one could make the Canvas larger inside a
smaller DIV too, catch scroll events from it and perform redrawing and setting the DIV's
scrollTop accordingly.
*/
var h = 10000; // virtual canvas height
var vp = 400; // viewport height
var viewport, fakescrolldiv, canvas;
function onScroll() {
var scrollTop = viewport.scrollTop();
console.log("onScroll scrollTop=" + scrollTop);
$("canvas").clearCanvas();
// Red box top
$("canvas").drawRect({
fillStyle: "#F00",
x: 150,
y: 20 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
// Green box middle
$("canvas").drawRect({
fillStyle: "#0F0",
x: 150,
y: 140 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
// Blue box bottom
$("canvas").drawRect({
fillStyle: "#00F",
x: 150,
y: 260 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
var i = 0;
for (i = 0; i <= 396; i++) {
$("canvas").drawLine({
strokeStyle: "#000",
strokeWidth: 1,
x1: 0,
y1: i,
x2: (scrollTop + i) % 50,
y2: i
});
if ((scrollTop + i) % 50 === 0) {
$("canvas").drawText({
fillStyle: "#729fcf",
text: (scrollTop + i).toString(),
align: "left",
baseline: "top",
font: "normal 12pt Verdana",
x: 60,
y: i
});
}
}
}
$(function() {
viewport = $("#viewport");
fakescrolldiv = $("#fakescrolldiv");
canvas = $("#gfx");
viewport.css("height", vp);
fakescrolldiv.css("height", h);
viewport.scroll(onScroll);
viewport.trigger("scroll");
});
非常感谢任何改进或简化的建议。
答案 1 :(得分:2)
根据我的个人经验,您的选项(1)是一个很有吸引力的选择,但是将它变成可用的jQuery插件可能会有一些有趣的点。
我一直在研究一种财务数据可视化系统,该系统明确使用HTML5 Canvas进行图形和图表绘制。我们在画布中有不同的虚拟“场景”或“幻灯片”,它们在画布中“滑入”和“滑出”,就像您在大型虚拟画布中导航一样。所有事件处理按钮都是在画布上绘制的,它决定了我们要显示的屏幕,但我们有一个/两个普通的HTML表单,它们接受用户输入并带来那些“幻灯片”。我们使用jQuery来处理来自这些文本框的事件,但jQuery代码深深地嵌套在其他Canvas绘图代码中(与外部化调用不同,这可能是制作插件的理想选择)。
滑动或更新画布是另一回事。这是因为它不仅依赖于触发更新的jQuery事件,而且还依赖于负责更新的Canvas Framework(普通代码或KineticJS,EaselJS,jCotton等)。如果您使用框架,您还需要与框架接口。
为简单起见,我们假设有一个回调函数,您可以使用诸如移动偏移(x,y)之类的参数为Canvas框架调用,并且框架将添加/删除此偏移量到所有的x和y位置在画布中绘制的对象,大多数Canvas绘图框架也有一个render()
函数,它定期调用,以便下次绘制场景时,结果将自动显示(在您的情况下,滚动虚拟画布)。 p>
因此,它基本上归结为不仅将其编写为jQuery插件,而且还将其绑定到特定的Canvas Framework,例如KineticJS或其他人。
如果您使用基本的Canvas函数而不是使用任何这些框架,那么它是另一个故事,您可以为画布编写自己的渲染和更新函数,但在这种情况下,它将限制潜在用户遵守绘图函数的限制,除非您公开API以扩展它们;但话说回来,这意味着你正在编写自己的Canvas框架:)
我不确定我是否正确理解你的问题,在这种情况下你可以放心地忽略我的建议:),但如果我是对的,我的观点是:制作这样的插件也需要绑定到Canvas框架使其真正可用。
希望它有所帮助。