- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#canvasOne
{
border: 1px solid black;
}
</style>
<script src="http://code.jquery.com/jquery-1.10.2.js" type="text/javascript"></script>
</head>
<body>
<div align="center">
<canvas id="canvasOne">
</canvas>
</div>
<script type="text/javascript">
var myCanvas = document.getElementById("canvasOne");
var myContext = myCanvas.getContext("2d");
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
init();
var numShapes;
var shapes;
var dragIndex;
var dragging;
var mouseX;
var mouseY;
var dragHoldX;
var dragHoldY;
var timer;
var targetX;
var targetY;
var easeAmount;
var bgColor;
var nodes;
var colorArr;
function init()
{
myCanvas.width = $(window).width() - 200;
myCanvas.height = $(window).height() - 200;
shapes = [];
nodes = ["0;Person;24828760;Alok Kumar;Gorakhpur;#F44336;28",
"0;Suspect;04/Dec/2016;4;Suman_Biswas;#3F51B5;20","1;Rule;4;Apparent Means;3 Parameter;#EEFF41;20",
"0;Policy;36QA649749;In-Force;Quarterly;#FF9800;20","3;Product;Pension;Saral Pension;SRPEN;#795548;20","3;Payment;Cheque;Realized;Lucknow;#0091EA;20",
"0;Policy;162348873;Lapsed;Quarterly;#FF9800;20","6;Product;Pension;Life-Long Pension;LLPP;#795548;20","6;Payment;Cheque;Realized;Gorakhpur;#0091EA;20",
"0;Policy;1EQF178639;Lapsed;Monthly;#FF9800;20","9;Product;Life;Shield;SHIELDA;#795548;20","9;Payment;Demand Draft;Realized;Lucknow;#0091EA;20"];
numShapes = nodes.length;
makeShapes();
drawScreen();
myCanvas.addEventListener("mousedown", mouseDownListener, false);
}
//drawing
function makeShapes()
{
var tempX;
var tempY;
for(var i = 0; i < numShapes; i++)
{
var centerX = myCanvas.width/2;
var centerY = myCanvas.height/2;
var nodeColor = nodes[i].split(";")[5];
var nodeRadius = nodes[i].split(";")[6];
var nodeConnect = nodes[i].split(";")[0];
if(i == 0)//center of circle
{
tempX = centerX
tempY = centerY;
}
else
{
//tempX = Math.random() * (myCanvas.width - tempRadius);
//tempY = Math.random() * (myCanvas.height - tempRadius);
//var x = x0 + r * Math.cos(2 * Math.PI * i / items);
//var y = y0 + r * Math.sin(2 * Math.PI * i / items);
//250 is the distance from center node to outside nodes it can be actual radius in degrees
tempX = shapes[nodeConnect].x + 300 * Math.cos(2 * Math.PI * i / numShapes);
tempY = shapes[nodeConnect].y + 300 * Math.sin(2 * Math.PI * i / numShapes);
}
tempShape = {x: tempX, y: tempY, rad: nodeRadius, color: nodeColor, text: nodes[i]};
shapes.push(tempShape);
}
}
//drawing both shape (line and circle) and screen
function drawScreen()
{
myContext.fillStyle = "#ffffff";
myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
drawShapes();
}
function drawShapes()
{
//line
for(var i = 1; i < numShapes; i++)
{
myContext.beginPath();
myContext.strokeStyle = "#B2B19D";
var nodeConnect = nodes[i].split(";")[0];
myContext.moveTo(shapes[nodeConnect].x, shapes[nodeConnect].y);
myContext.lineTo(shapes[i].x, shapes[i].y);
myContext.stroke();
}
//circle
for(var i = 0; i < numShapes; i++)
{
myContext.fillStyle = shapes[i].color;
myContext.beginPath();
myContext.arc(shapes[i].x, shapes[i].y, shapes[i].rad, 0, 2*Math.PI, false);
myContext.closePath();
myContext.fill();
}
//text
for(var i = 0; i < numShapes; i++)
{
myContext.beginPath();
myContext.font = '10pt Arial';
myContext.fillStyle = 'black';
var textarr = shapes[i].text.split(";");
myContext.fillText(textarr[1], shapes[i].x + 30, shapes[i].y - 24);
/*myContext.fillText(textarr[2], shapes[i].x + 30, shapes[i].y + 1);
myContext.fillText(textarr[3], shapes[i].x + 30, shapes[i].y + 22);
myContext.fillText(textarr[4], shapes[i].x + 30, shapes[i].y + 44);*/
myContext.closePath();
myContext.fill();
}
}
//animation
function mouseDownListener(evt)
{
var highestIndex = -1;
var bRect = myCanvas.getBoundingClientRect();
mouseX = (evt.clientX - bRect.left) * (myCanvas.width/bRect.width);
mouseY = (evt.clientY - bRect.top) * (myCanvas.height/bRect.height);
for(var i = 0; i < numShapes; i++)
{
if(hitTest(shapes[i], mouseX, mouseY))
{
dragging = true;
if(i > highestIndex)
{
dragHoldX = mouseX - shapes[i].x;
dragHoldY = mouseY - shapes[i].y;
highestIndex = i;
dragIndex = i;
}
}
}
if(dragging)
{
window.addEventListener("mousemove", mouseMoveListener, false);
}
myCanvas.removeEventListener("mousedown", mouseDownListener, false);
window.addEventListener("mouseup", mouseUpListener, false);
if(evt.preventDefault)
{
evt.preventDefault;
}
return false;
}
function mouseMoveListener(evt)
{
var shapeRad = shapes[dragIndex].rad;
var minX = shapeRad;
var maxX = myCanvas.width - shapeRad;
var minY = shapeRad;
var maxY = myCanvas.height - shapeRad;
//get mouse position correctly
var bRect = myCanvas.getBoundingClientRect();
mouseX = (evt.clientX - bRect.left)*(myCanvas.width / bRect.width);
mouseY = (evt.clientY - bRect.top)*(myCanvas.height / bRect.height);
//clamp x and y position to prevent object from dragging outside canvas
posX = mouseX - dragHoldX;
posX = (posX < minX) ? minX : ((posX > maxX) ? maxX : posX);
posY = mouseY - dragHoldY;
posY = (posY < minY) ? minY : ((posY > maxY) ? maxY : posY);
shapes[dragIndex].x = posX;
shapes[dragIndex].y = posY;
drawScreen();
}
function mouseUpListener(evt)
{
myCanvas.addEventListener("mousedown", mouseDownListener, false);
window.removeEventListener("mouseup", mouseUpListener, false);
if(dragging)
{
dragging = false;
window.removeEventListener("mousemove", mouseMoveListener, false);
}
}
function hitTest(shape, mx, my)
{
var dx = mx - shape.x;
var dy = my - shape.y;
return(dx * dx + dy * dy < shape.rad * shape.rad);
}
</script>
</body>
</html>
最佳答案
<canvas>
上下文没有内置的滚动方法。
然后您可以通过多种方式规避此限制。
第一个,与@markE 的回答一样,缩放上下文的矩阵,以便您的绘图适合所需的空间。您还可以重构代码,使所有坐标都相对于 Canvas 大小。
这样,您就不需要滚动条了,您的所有绘图都会适当缩放,这是大多数常见情况下的理想行为。
但是如果你真的需要一些滚动功能,这里有一些方法:
最简单也是最推荐的一种:让浏览器处理。
您必须将 Canvas 的大小设置为绘图的最大值,并将其包裹在另一个将滚动的元素中。通过设置 overflow:auto
容器上的 css 属性,我们的滚动条出现并且我们有滚动功能。
在下面的示例中, Canvas 宽度为 5000 像素,容器宽度为 200 像素。
var ctx = canvas.getContext('2d');
ctx.textAlign = 'center';
for (var w = 0; w < canvas.width; w += 100) {
for (var h = 0; h < canvas.height; h += 100) {
ctx.fillText(w + ',' + h, w, h);
}
}
#container {
width: 200px;
height: 200px;
overflow: auto;
border: 1px solid;
}
canvas{
display: block;
}
<div id="container">
<canvas id="canvas" height="5000" width="5000"></canvas>
</div>
主要优势:
主要注意事项:
第二种解决方案是自己实现此功能,使用 Canvas 转换方法:特别是 translate
, transform
和 setTransform
.
这是一个例子:
var ctx = canvas.getContext('2d');
var app = {};
// the total area of our drawings, can be very large now
app.WIDTH = 5000;
app.HEIGHT = 5000;
app.draw = function() {
// reset everything (clears the canvas + transform + fillStyle + any other property of the context)
canvas.width = canvas.width;
// move our context by the inverse of our scrollbars' left and top property
ctx.setTransform(1, 0, 0, 1, -app.scrollbars.left, -app.scrollbars.top);
ctx.textAlign = 'center';
// draw only the visible area
var visibleLeft = app.scrollbars.left;
var visibleWidth = visibleLeft + canvas.width;
var visibleTop = app.scrollbars.top
var visibleHeight = visibleTop + canvas.height;
// you probably will have to make other calculations than these ones to get your drawings
// to draw only where required
for (var w = visibleLeft; w < visibleWidth + 50; w += 100) {
for (var h = visibleTop; h < visibleHeight + 50; h += 100) {
var x = Math.round((w) / 100) * 100;
var y = Math.round((h) / 100) * 100;
ctx.fillText(x + ',' + y, x, y);
}
}
// draw our scrollbars on top if needed
app.scrollbars.draw();
}
app.scrollbars = function() {
var scrollbars = {};
// initial position
scrollbars.left = 0;
scrollbars.top = 0;
// a single constructor for both horizontal and vertical
var ScrollBar = function(vertical) {
var that = {
vertical: vertical
};
that.left = vertical ? canvas.width - 10 : 0;
that.top = vertical ? 0 : canvas.height - 10;
that.height = vertical ? canvas.height - 10 : 5;
that.width = vertical ? 5 : canvas.width - 10;
that.fill = '#dedede';
that.cursor = {
radius: 5,
fill: '#bababa'
};
that.cursor.top = vertical ? that.cursor.radius : that.top + that.cursor.radius / 2;
that.cursor.left = vertical ? that.left + that.cursor.radius / 2 : that.cursor.radius;
that.draw = function() {
if (!that.visible) {
return;
}
// remember to reset the matrix
ctx.setTransform(1, 0, 0, 1, 0, 0);
// you can give it any shape you like, all canvas drawings operations are possible
ctx.fillStyle = that.fill;
ctx.fillRect(that.left, that.top, that.width, that.height);
ctx.beginPath();
ctx.arc(that.cursor.left, that.cursor.top, that.cursor.radius, 0, Math.PI * 2);
ctx.fillStyle = that.cursor.fill;
ctx.fill();
};
// check if we're hovered
that.isHover = function(x, y) {
if (x >= that.left - that.cursor.radius && x <= that.left + that.width + that.cursor.radius &&
y >= that.top - that.cursor.radius && y <= that.top + that.height + that.cursor.radius) {
// we are so record the position of the mouse and set ourself as the one hovered
scrollbars.mousePos = vertical ? y : x;
scrollbars.hovered = that;
that.visible = true;
return true;
}
// we were visible last call and no wheel event is happening
else if (that.visible && !scrollbars.willHide) {
that.visible = false;
// the app should be redrawn
return true;
}
}
return that;
};
scrollbars.horizontal = ScrollBar(0);
scrollbars.vertical = ScrollBar(1);
scrollbars.hovered = null;
scrollbars.dragged = null;
scrollbars.mousePos = null;
// check both of our scrollbars
scrollbars.isHover = function(x, y) {
return this.horizontal.isHover(x, y) || this.vertical.isHover(x, y);
};
// draw both of our scrollbars
scrollbars.draw = function() {
this.horizontal.draw();
this.vertical.draw();
};
// check if one of our scrollbars is visible
scrollbars.visible = function() {
return this.horizontal.visible || this.vertical.visible;
};
// hide it...
scrollbars.hide = function() {
// only if we're not using the mousewheel or dragging the cursor
if (this.willHide || this.dragged) {
return;
}
this.horizontal.visible = false;
this.vertical.visible = false;
};
// get the area's coord relative to our scrollbar
var toAreaCoord = function(pos, scrollBar) {
var sbBase = scrollBar.vertical ? scrollBar.top : scrollBar.left;
var sbMax = scrollBar.vertical ? scrollBar.height : scrollBar.width;
var areaMax = scrollBar.vertical ? app.HEIGHT - canvas.height : app.WIDTH - canvas.width;
var ratio = (pos - sbBase) / (sbMax - sbBase);
return areaMax * ratio;
};
// get the scrollbar's coord relative to our total area
var toScrollCoords = function(pos, scrollBar) {
var sbBase = scrollBar.vertical ? scrollBar.top : scrollBar.left;
var sbMax = scrollBar.vertical ? scrollBar.height : scrollBar.width;
var areaMax = scrollBar.vertical ? app.HEIGHT - canvas.height : app.WIDTH - canvas.width;
var ratio = pos / areaMax;
return ((sbMax - sbBase) * ratio) + sbBase;
}
scrollbars.scroll = function() {
// check which one of the scrollbars is active
var vertical = this.hovered.vertical;
// until where our cursor can go
var maxCursorPos = this.hovered[vertical ? 'height' : 'width'];
var pos = vertical ? 'top' : 'left';
// check that we're not out of the bounds
this.hovered.cursor[pos] = this.mousePos < 0 ? 0 :
this.mousePos > maxCursorPos ? maxCursorPos : this.mousePos;
// seems ok so tell the app we scrolled
this[pos] = toAreaCoord(this.hovered.cursor[pos], this.hovered);
// redraw everything
app.draw();
}
// because we will hide it after a small time
scrollbars.willHide;
// called by the wheel event
scrollbars.scrollBy = function(deltaX, deltaY) {
// it's not coming from our scrollbars
this.hovered = null;
// we're moving horizontally
if (deltaX) {
var newLeft = this.left + deltaX;
// make sure we're in the bounds
this.left = newLeft > app.WIDTH - canvas.width ? app.WIDTH - canvas.width : newLeft < 0 ? 0 : newLeft;
// update the horizontal cursor
this.horizontal.cursor.left = toScrollCoords(this.left, this.horizontal);
// show our scrollbar
this.horizontal.visible = true;
}
if (deltaY) {
var newTop = this.top + deltaY;
this.top = newTop > app.HEIGHT - canvas.height ? app.HEIGHT - canvas.height : newTop < 0 ? 0 : newTop;
this.vertical.cursor.top = toScrollCoords(this.top, this.vertical);
this.vertical.visible = true;
}
// if we were called less than the required timeout
clearTimeout(this.willHide);
this.willHide = setTimeout(function() {
scrollbars.willHide = null;
scrollbars.hide();
app.draw();
}, 500);
// redraw everything
app.draw();
};
return scrollbars;
}();
var mousedown = function(e) {
// tell the browser we handle this
e.preventDefault();
// we're over one the scrollbars
if (app.scrollbars.hovered) {
// new promotion ! it becomes the dragged one
app.scrollbars.dragged = app.scrollbars.hovered;
app.scrollbars.scroll();
}
};
var mousemove = function(e) {
// check the coordinates of our canvas in the document
var rect = canvas.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
// we're dragging something
if (app.scrollbars.dragged) {
// update the mouse position
app.scrollbars.mousePos = app.scrollbars.dragged.vertical ? y : x;
app.scrollbars.scroll();
} else if (app.scrollbars.isHover(x, y)) {
// something has changed, redraw to show or hide the scrollbar
app.draw();
}
e.preventDefault();
};
var mouseup = function() {
// we dropped it
app.scrollbars.dragged = null;
};
var mouseout = function() {
// we're out
if (app.scrollbars.visible()) {
app.scrollbars.hide();
app.scrollbars.dragged = false;
app.draw();
}
};
var mouseWheel = function(e) {
e.preventDefault();
app.scrollbars.scrollBy(e.deltaX, e.deltaY);
};
canvas.addEventListener('mousemove', mousemove);
canvas.addEventListener('mousedown', mousedown);
canvas.addEventListener('mouseup', mouseup);
canvas.addEventListener('mouseout', mouseout);
canvas.addEventListener('wheel', mouseWheel);
range.onchange = function() {
app.WIDTH = app.HEIGHT = this.value;
app.scrollbars.left = 0;
app.scrollbars.top = 0;
app.draw();
};
// an initial drawing
app.draw();
canvas {border: 1px solid;}
span{font-size: .8em;}
<canvas id="canvas" width="200" height="150"></canvas>
<span>
change the total area size
<input type="range" min="250" max="5000000" steps="250" value="5000" id="range" />
</span>
主要优势:
主要注意事项:
A third way我前段时间写了另一个问题,利用了使用 ctx.drawImage()
绘制其他 Canvas 的能力。 .它有自己的注意事项和优点,所以我让您选择您需要的那个,但最后一个也有一个非常有用的拖动和滑动功能。
关于Html5 Canvas 垂直和水平滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36219632/
如果附加了 'not-scroll' 类,我希望我的 body 不滚动,否则它应该正常工作。 我已经搜索这个问题两天了,但找不到任何适合我的解决方案。 我想要的是向 body 添加一个 class,并
我发现似乎是 iOS Safari 中的错误(我正在 iOS 8 上进行测试)。当绝对定位的 iFrame 漂浮在一段可滚动内容上方时,滚动 iFrame 也会滚动下面的内容。以下 HTML (ava
我有以下代码来显示一系列投资组合图片,这些图片以 SVG 格式存储在滚动 div 中: 在 Safari 中滚动使用两根手指或鼠标滚轮当光标位于 SVG 之一上时不起作用。 该页
我想用 javascript 做的是: 一旦你向下滚动页面,将#sidebar-box-fixed 的位置从 position: relative; 更改为定位:固定;。改回position:rela
我对 Elasticsearch 的滚动功能有点困惑。在 elasticsearch 中,每当用户在结果集上滚动时,是否可以每次调用搜索 API?来自文档 "search_type" => "scan
我试图做到这一点,以便当我向上或向下滚动页面时,它会运行不同的相应功能。我发现了一个类似的问题here但我已经尝试了他们的答案并且没有运气。 注意:此页面没有正常显示的滚动条。没有地方可以滚动。 bo
(C语言,GTK库) 在我的表单上,我有一个 GtkDrawingArea 小部件,我在上面使用 Cairo 绘制 GdkPixbufs(从文件加载)。我想要完成的是能够在窗口大小保持固定的情况下使用
最近我一直在尝试创建一个拉到(刷新,加载更多)swiftUI ScrollView !!,灵感来自 https://cocoapods.org/pods/SwiftPullToRefresh 我正在努
我正在开发一个应用程序,其中有两个带有可放置区域的列表和一个带有可拖动项目的侧面菜单。 当我滚动屏幕时,项目的位置困惑。 我试图在谷歌上寻找一些东西,最后得到了这个问题:jQuery draggabl
我在 UIWebView 中加载了一个 HTML 表单,而我的 UIWebView 恰好从 View 的中间开始并扩展。我必须锁定此 webView 不滚动并将其放在 ScrollView 之上以允许
如何在每个元素而不是整个元素上应用淡入淡出(与其高度相比)? HTML: CSS: * { padding: 0; margin: 0; box-sizing: border
我想使用带有垂直轴的 PageView 并使用鼠标滚动在页面之间移动,但是当我使用鼠标滚动时页面不滚动...仅页面单击并向上/向下滑动时滚动。 有什么办法吗? 我想保留属性 pageSnapping:
我制作这个程序是为了好玩,但我被卡住了,因为程序在屏幕外运行。如何在不完全更改代码的情况下实现滚动条。 public static void main(String args[]) throws IO
我想使用带有垂直轴的 PageView 并使用鼠标滚动在页面之间移动,但是当我使用鼠标滚动时页面不滚动...仅页面单击并向上/向下滑动时滚动。 有什么办法吗? 我想保留属性 pageSnapping:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
使用 jquery 技术从 css-tricks.com 获得滚动/跟随侧边栏,如果您不知道我在说什么,这里是代码: $(function() { var $sidebar = $
我是 jQuery Mobile 新手。我需要向我的应用程序添加 Facebook 滑动面板功能。 我经历了 sliding menu panel ,它工作正常,但我在菜单面板中的内容超出了窗口大小,
有没有办法在 js 或 jQuery 或任何其他工具中检测 ctrl + 滚动。我正在尝试执行一些动态布局代码,我需要检测不同分辨率下的屏幕宽度,我通过使用 setTimeout() 的计时器实现了这
我有一部分html代码:
我想控制 RichTextBox 滚动,但在控件中找不到任何方法来执行此操作。 这样做的原因是我希望当鼠标光标位于 RichTextBox 控件上时鼠标滚轮滚动有效(它没有事件焦点:鼠标滚轮事件由表单
我是一名优秀的程序员,十分优秀!