javascript 在画布上水平滚动。HTML5
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14368716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Horizontal Scrolling on Canvas. HTML5
提问by Philo
I'm creating a canvas via javascript on a webproject.
我正在通过 javascript 在 webproject 上创建画布。
The canvas has graphical representations on the x-y plane.
画布在 xy 平面上具有图形表示。
I am trying to add the horizontal-scrolling feature to the canvas.
我正在尝试将水平滚动功能添加到画布。
I have investigated a few methodologies:-
我研究了一些方法:-
1) draw 12 months worth of data on the canvas, when the mouse scrolls forward, 1st month's data disappears, and at the end a new months data is added, new canvas is drawn.
1)在画布上绘制12个月的数据,当鼠标向前滚动时,第1个月的数据消失,最后添加新的月份数据,绘制新的画布。
Con:- Everytime the mouse scrolls to pan thru the timeline - a new SQL query has to be made, making my web application very slow.
缺点:- 每次鼠标滚动以通过时间线平移时 - 必须进行新的 SQL 查询,使我的 Web 应用程序非常慢。
2) maybe I can draw say 10 years worth of data on the canvas via 1 SQL query, but only show 12 months worth of the data. masking the rest of the 9 years. Now when the client scrolls, I capture the scroll event and move to the appropriate part of the canvas. Is this possible? If so then how?
2)也许我可以通过 1 个 SQL 查询在画布上绘制 10 年的数据,但只显示 12 个月的数据。掩盖了剩下的 9 年。现在当客户端滚动时,我捕获滚动事件并移动到画布的适当部分。这可能吗?如果是,那么如何?
Can anyone advise?
任何人都可以建议吗?
My current representation of the canvas = with only 12 months worth of data
我当前的画布表示 = 只有 12 个月的数据
To be more specific on the scrolling, I would like to have a feeling such as the following widget for my client-side scrolling action:-
为了更具体地说明滚动,我想对我的客户端滚动操作有一种感觉,例如以下小部件:-
回答by Shmiddty
Here's a pretty basic implementation: http://jsfiddle.net/CQPeU/
这是一个非常基本的实现:http: //jsfiddle.net/CQPeU/
var can = document.getElementById("can"),
ctx = can.getContext('2d'),
dragging = false,
lastX = 0,
translated = 0;
// these two lines will make the y-axis grow upwards.
ctx.scale(1,-1);
ctx.translate(0, -400);
can.onmousedown = function(e){
var evt = e || event;
dragging = true;
lastX = evt.offsetX;
}
window.onmousemove = function(e){
var evt = e || event;
if (dragging){
var delta = evt.offsetX - lastX;
translated += delta;
ctx.translate(delta, 0); // translate the context.
lastX = evt.offsetX;
draw(); // redraw
}
}
window.onmouseup = function(){
dragging = false;
}
function draw() {
ctx.clearRect(-translated, 0, 600, 400); // this is why we need to keep track of how much we've translated
for (var i = 0; i < plot.length; i++) {
ctx.beginPath();
ctx.arc(plot[i].x, plot[i].y, 5, 0, 2 * Math.PI); // note we don't have to futz with the x/y values, and can use them directly.
ctx.fill();
}
}
To create a grid, you could do something like this:
要创建网格,您可以执行以下操作:
var grid = (function(dX, dY){
var can = document.createElement("canvas"),
ctx = can.getContext('2d');
can.width = dX;
can.height = dY;
// fill canvas color
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, dX, dY);
// x axis
ctx.strokeStyle = 'orange';
ctx.moveTo(.5, 0.5);
ctx.lineTo(dX + .5, 0.5);
ctx.stroke();
// y axis
ctx.moveTo(.5, .5);
ctx.lineTo(.5, dY + .5);
ctx.stroke();
return ctx.createPattern(can, 'repeat');
})(100, 50);
Which would be used like this:
这将像这样使用:
function draw() {
ctx.clearRect(-translated, 0, 600, 400);
ctx.rect(-translated, 0, 600, 400);
ctx.fillStyle = grid;
ctx.fill();
ctx.fillStyle = "#fff";
for (var i = 0; i < plot.length; i++) {
ctx.beginPath();
ctx.arc(plot[i].x, plot[i].y, 5, 0, 2 * Math.PI);
ctx.fill();
}
}
Updated demo: http://jsfiddle.net/CQPeU/2/
更新演示:http: //jsfiddle.net/CQPeU/2/
回答by pancake
To avoid the redraw on every Mouse Move event in the answer from @Shmiddty, you can draw the entire canvas oversize, then change the CSS margin property. This is a significant performance gain when the content of the canvas gets more complex.
为了避免在@Shmiddty 的答案中对每个鼠标移动事件进行重绘,您可以将整个画布绘制为超大尺寸,然后更改 CSS 边距属性。当画布的内容变得更复杂时,这是一个显着的性能提升。
Here is a demo: https://jsfiddle.net/ax7n8944/
这是一个演示:https: //jsfiddle.net/ax7n8944/
HTML:
HTML:
<div id="canvasdiv" style="width: 500px; height: 250px; overflow: hidden">
<canvas id="canvas" width="10000px" height="250px"></canvas>
</div>
JS:
JS:
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var dragging = false;
var lastX;
var marginLeft = 0;
for (var i = 0; i < 1000; i++) {
context.beginPath();
context.arc(Math.random() * 10000, Math.random() * 250, 20.0, 0, 2 * Math.PI, false);
context.stroke();
}
canvas.addEventListener('mousedown', function(e) {
var evt = e || event;
dragging = true;
lastX = evt.clientX;
e.preventDefault();
}, false);
window.addEventListener('mousemove', function(e) {
var evt = e || event;
if (dragging) {
var delta = evt.clientX - lastX;
lastX = evt.clientX;
marginLeft += delta;
canvas.style.marginLeft = marginLeft + "px";
}
e.preventDefault();
}, false);
window.addEventListener('mouseup', function() {
dragging = false;
}, false);
回答by jdnichollsc
It's better using Phaser Framework with the following plugin http://jdnichollsc.github.io/Phaser-Kinetic-Scrolling-Plugin/
最好使用带有以下插件的 Phaser Framework http://jdnichollsc.github.io/Phaser-Kinetic-Scrolling-Plugin/